Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm: (80 commits)
  KVM: Use CPU_DYING for disabling virtualization
  KVM: Tune hotplug/suspend IPIs
  KVM: Keep track of which cpus have virtualization enabled
  SMP: Allow smp_call_function_single() to current cpu
  i386: Allow smp_call_function_single() to current cpu
  x86_64: Allow smp_call_function_single() to current cpu
  HOTPLUG: Adapt thermal throttle to CPU_DYING
  HOTPLUG: Adapt cpuset hotplug callback to CPU_DYING
  HOTPLUG: Add CPU_DYING notifier
  KVM: Clean up #includes
  KVM: Remove kvmfs in favor of the anonymous inodes source
  KVM: SVM: Reliably detect if SVM was disabled by BIOS
  KVM: VMX: Remove unnecessary code in vmx_tlb_flush()
  KVM: MMU: Fix Wrong tlb flush order
  KVM: VMX: Reinitialize the real-mode tss when entering real mode
  KVM: Avoid useless memory write when possible
  KVM: Fix x86 emulator writeback
  KVM: Add support for in-kernel pio handlers
  KVM: VMX: Fix interrupt checking on lightweight exit
  KVM: Adds support for in-kernel mmio handlers
  ...
diff --git a/.gitignore b/.gitignore
index 060a71d..8d15830 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,6 @@
 
 # cscope files
 cscope.*
+
+*.orig
+*.rej
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index f08ca95..8b05636 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -12,6 +12,8 @@
 
 00-INDEX
 	- this file.
+ABI/
+	- info on kernel <-> userspace ABI and relative interface stability.
 BUG-HUNTING
 	- brute force method of doing binary search of patches to find bug.
 Changes
@@ -25,37 +27,57 @@
 DocBook/
 	- directory with DocBook templates etc. for kernel documentation.
 HOWTO
-	- The process and procedures of how to do Linux kernel development.
+	- the process and procedures of how to do Linux kernel development.
 IO-mapping.txt
 	- how to access I/O mapped memory from within device drivers.
 IPMI.txt
 	- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
 IRQ-affinity.txt
 	- how to select which CPU(s) handle which interrupt events on SMP.
+IRQ.txt
+	- description of what an IRQ is.
 ManagementStyle
 	- how to (attempt to) manage kernel hackers.
 MSI-HOWTO.txt
 	- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+PCIEBUS-HOWTO.txt
+	- a guide describing the PCI Express Port Bus driver.
 RCU/
 	- directory with info on RCU (read-copy update).
 README.DAC960
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
+README.cycladesZ
+	- info on Cyclades-Z firmware loading.
 SAK.txt
 	- info on Secure Attention Keys.
+SecurityBugs
+	- procedure for reporting security bugs found in the kernel.
+SubmitChecklist
+	- Linux kernel patch submission checklist.
 SubmittingDrivers
 	- procedure to get a new driver source included into the kernel tree.
 SubmittingPatches
 	- procedure to get a source patch included into the kernel tree.
 VGA-softcursor.txt
 	- how to change your VGA cursor from a blinking underscore.
+accounting/
+	- documentation on accounting and taskstats.
+aoe/
+	- description of AoE (ATA over Ethernet) along with config examples.
 applying-patches.txt
 	- description of various trees and how to apply their patches.
 arm/
 	- directory with info about Linux on the ARM architecture.
+atomic_ops.txt
+	- semantics and behavior of atomic and bitmask operations.
+auxdisplay/
+	- misc. LCD driver documentation (cfag12864b, ks0108).
 basic_profiling.txt
 	- basic instructions for those who wants to profile Linux kernel.
 binfmt_misc.txt
 	- info on the kernel support for extra binary formats.
+blackfin/
+	- directory with documentation for the Blackfin arch.
 block/
 	- info on the Block I/O (BIO) layer.
 cachetlb.txt
@@ -68,16 +90,32 @@
 	- cli()/sti() removal guide.
 computone.txt
 	- info on Computone Intelliport II/Plus Multiport Serial Driver.
+connector/
+	- docs on the netlink based userspace<->kernel space communication mod.
+console/
+	- documentation on Linux console drivers.
 cpqarray.txt
 	- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
 cpu-freq/
 	- info on CPU frequency and voltage scaling.
+cpu-hotplug.txt
+	- document describing CPU hotplug support in the Linux kernel.
+cpu-load.txt
+	- document describing how CPU load statistics are collected.
+cpusets.txt
+	- documents the cpusets feature; assign CPUs and Mem to a set of tasks.
+cputopology.txt
+	- documentation on how CPU topology info is exported via sysfs.
 cris/
 	- directory with info about Linux on CRIS architecture.
 crypto/
 	- directory with info on the Crypto API.
+dcdbas.txt
+	- information on the Dell Systems Management Base Driver.
 debugging-modules.txt
 	- some notes on debugging modules after Linux 2.6.3.
+dell_rbu.txt
+	- document demonstrating the use of the Dell Remote BIOS Update driver.
 device-mapper/
 	- directory with info on Device Mapper.
 devices.txt
@@ -86,32 +124,52 @@
 	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
 dnotify.txt
 	- info about directory notification in Linux.
+dontdiff
+	- file containing a list of files that should never be diff'ed.
 driver-model/
 	- directory with info about Linux driver model.
+drivers/
+	- directory with driver documentation (currently only EDAC).
 dvb/
 	- info on Linux Digital Video Broadcast (DVB) subsystem.
 early-userspace/
 	- info about initramfs, klibc, and userspace early during boot.
+ecryptfs.txt
+	- docs on eCryptfs: stacked cryptographic filesystem for Linux.
 eisa.txt
 	- info on EISA bus support.
 exception.txt
 	- how Linux v2.2 handles exceptions without verify_area etc.
+fault-injection/
+	- dir with docs about the fault injection capabilities infrastructure.
 fb/
 	- directory with info on the frame buffer graphics abstraction layer.
+feature-removal-schedule.txt
+	- list of files and features that are going to be removed.
 filesystems/
 	- directory with info on the various filesystems that Linux supports.
 firmware_class/
 	- request_firmware() hotplug interface info.
 floppy.txt
 	- notes and driver options for the floppy disk driver.
+fujitsu/
+	- Fujitsu FR-V Linux documentation.
+gpio.txt
+	- overview of GPIO (General Purpose Input/Output) access conventions.
 hayes-esp.txt
 	- info on using the Hayes ESP serial driver.
 highuid.txt
 	- notes on the change from 16 bit to 32 bit user/group IDs.
 hpet.txt
 	- High Precision Event Timer Driver for Linux.
+hrtimer/
+	- info on the timer_stats debugging facility for timer (ab)use.
+hrtimers/
+	- info on the hrtimers subsystem for high-resolution kernel timers.
 hw_random.txt
 	- info on Linux support for random number generator in i8xx chipsets.
+hwmon/
+	- directory with docs on various hardware monitoring drivers.
 i2c/
 	- directory with info about the I2C bus/protocol (2 wire, kHz speed).
 i2o/
@@ -122,16 +180,22 @@
 	- directory with info about Linux on Intel 64 bit architecture.
 ide.txt
 	- important info for users of ATA devices (IDE/EIDE disks and CD-ROMS).
+infiniband/
+	- directory with documents concerning Linux InfiniBand support.
 initrd.txt
 	- how to use the RAM disk as an initial/temporary root filesystem.
 input/
 	- info on Linux input device support.
 io_ordering.txt
 	- info on ordering I/O writes to memory-mapped addresses.
+ioctl/
+	- directory with documents describing various IOCTL calls.
 ioctl-number.txt
 	- how to implement and register device/driver ioctl calls.
 iostats.txt
 	- info on I/O statistics Linux kernel provides.
+irqflags-tracing.txt
+	- how to use the irq-flags tracing feature.
 isapnp.txt
 	- info on Linux ISA Plug & Play support.
 isdn/
@@ -140,26 +204,40 @@
 	- info on the in-kernel binary support for Java(tm).
 kbuild/
 	- directory with info about the kernel build process.
-kdumpt.txt
-       - mini HowTo on getting the crash dump code to work.
+kdump/
+	- directory with mini HowTo on getting the crash dump code to work.
 kernel-doc-nano-HOWTO.txt
 	- mini HowTo on generation and location of kernel documentation files.
 kernel-docs.txt
 	- listing of various WWW + books that document kernel internals.
 kernel-parameters.txt
 	- summary listing of command line / boot prompt args for the kernel.
+keys-request-key.txt
+	- description of the kernel key request service.
+keys.txt
+	- description of the kernel key retention service.
 kobject.txt
 	- info of the kobject infrastructure of the Linux kernel.
+kprobes.txt
+	- documents the kernel probes debugging feature.
+kref.txt
+	- docs on adding reference counters (krefs) to kernel objects.
 laptop-mode.txt
-	- How to conserve battery power using laptop-mode.
+	- how to conserve battery power using laptop-mode.
 ldm.txt
 	- a brief description of LDM (Windows Dynamic Disks).
+leds-class.txt
+	- documents LED handling under Linux.
+local_ops.txt
+	- semantics and behavior of local atomic operations.
+lockdep-design.txt
+	- documentation on the runtime locking correctness validator.
 locks.txt
 	- info on file locking implementations, flock() vs. fcntl(), etc.
 logo.gif
-	- Full colour GIF image of Linux logo (penguin).
+	- full colour GIF image of Linux logo (penguin - Tux).
 logo.txt
-	- Info on creator of above logo & site to get additional images from.
+	- info on creator of above logo & site to get additional images from.
 m68k/
 	- directory with info about Linux on Motorola 68k architecture.
 magic-number.txt
@@ -170,6 +248,8 @@
 	- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
 md.txt
 	- info on boot arguments for the multiple devices driver.
+memory-barriers.txt
+	- info on Linux kernel memory barriers.
 memory.txt
 	- info on typical Linux memory problems.
 mips/
@@ -177,9 +257,11 @@
 mono.txt
 	- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
 moxa-smartio
-	- info on installing/using Moxa multiport serial driver.
+	- file with info on installing/using Moxa multiport serial driver.
 mtrr.txt
 	- how to use PPro Memory Type Range Registers to increase performance.
+mutex-design.txt
+	- info on the generic mutex subsystem.
 nbd.txt
 	- info on a TCP implementation of a network block device.
 netlabel/
@@ -190,6 +272,8 @@
 	- short guide on setting up a diskless box with NFS root filesystem.
 nmi_watchdog.txt
 	- info on NMI watchdog for SMP systems.
+nommu-mmap.txt
+	- documentation about no-mmu memory mapping support.
 numastat.txt
 	- info on how to read Numa policy hit/miss statistics in sysfs.
 oops-tracing.txt
@@ -202,8 +286,16 @@
 	- how to use the parallel-port driver.
 parport-lowlevel.txt
 	- description and usage of the low level parallel port functions.
+pci-error-recovery.txt
+	- info on PCI error recovery.
 pci.txt
 	- info on the PCI subsystem for device driver authors.
+pcieaer-howto.txt
+	- the PCI Express Advanced Error Reporting Driver Guide HOWTO.
+pcmcia/
+	- info on the Linux PCMCIA driver.
+pi-futex.txt
+	- documentation on lightweight PI-futexes.
 pm.txt
 	- info on Linux power management support.
 pnp.txt
@@ -214,18 +306,32 @@
 	- directory with info on using Linux with the PowerPC.
 preempt-locking.txt
 	- info on locking under a preemptive kernel.
+prio_tree.txt
+	- info on radix-priority-search-tree use for indexing vmas.
 ramdisk.txt
 	- short guide on how to set up and use the RAM disk.
+rbtree.txt
+	- info on what red-black trees are and what they are for.
 riscom8.txt
 	- notes on using the RISCom/8 multi-port serial driver.
+robust-futex-ABI.txt
+	- documentation of the robust futex ABI.
+robust-futexes.txt
+	- a description of what robust futexes are.
 rocket.txt
 	- info on the Comtrol RocketPort multiport serial driver.
 rpc-cache.txt
 	- introduction to the caching mechanisms in the sunrpc layer.
+rt-mutex-design.txt
+	- description of the RealTime mutex implementation design.
+rt-mutex.txt
+	- desc. of RT-mutex subsystem with PI (Priority Inheritance) support.
 rtc.txt
 	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
 s390/
 	- directory with info on using Linux on the IBM S390.
+sched-arch.txt
+	- CPU Scheduler implementation hints for architecture specific code.
 sched-coding.txt
 	- reference for various scheduler-related methods in the O(1) scheduler.
 sched-design.txt
@@ -240,22 +346,32 @@
 	- directory with info on the low level serial API.
 serial-console.txt
 	- how to set up Linux with a serial line console as the default.
+sgi-ioc4.txt
+	- description of the SGI IOC4 PCI (multi function) device.
 sgi-visws.txt
 	- short blurb on the SGI Visual Workstations.
 sh/
 	- directory with info on porting Linux to a new architecture.
+sharedsubtree.txt
+	- a description of shared subtrees for namespaces.
 smart-config.txt
 	- description of the Smart Config makefile feature.
 smp.txt
 	- a few notes on symmetric multi-processing.
+sony-laptop.txt
+	- Sony Notebook Control Driver (SNC) Readme.
 sonypi.txt
 	- info on Linux Sony Programmable I/O Device support.
 sound/
 	- directory with info on sound card support.
 sparc/
 	- directory with info on using Linux on Sparc architecture.
+sparse.txt
+	- info on how to obtain and use the sparse tool for typechecking.
 specialix.txt
 	- info on hardware/driver for specialix IO8+ multiport serial card.
+spi/
+	- overview of Linux kernel Serial Peripheral Interface (SPI) support.
 spinlocks.txt
 	- info on using spinlocks to provide exclusive access in kernel.
 stable_api_nonsense.txt
@@ -274,24 +390,32 @@
 	- info on the magic SysRq key.
 telephony/
 	- directory with info on telephony (e.g. voice over IP) support.
+thinkpad-acpi.txt
+	- information on the (IBM and Lenovo) ThinkPad ACPI Extras driver.
 time_interpolators.txt
 	- info on time interpolators.
 tipar.txt
 	- information about Parallel link cable for Texas Instruments handhelds.
 tty.txt
 	- guide to the locking policies of the tty layer.
-unicode.txt
-	- info on the Unicode character/font mapping used in Linux.
 uml/
 	- directory with information about User Mode Linux.
+unicode.txt
+	- info on the Unicode character/font mapping used in Linux.
+unshare.txt
+	- description of the Linux unshare system call.
 usb/
 	- directory with info regarding the Universal Serial Bus.
+video-output.txt
+	- sysfs class driver interface to enable/disable a video output device.
 video4linux/
 	- directory with info regarding video/TV/radio cards and linux.
 vm/
 	- directory with info on the Linux vm code.
 voyager.txt
 	- guide to running Linux on the Voyager architecture.
+w1/
+	- directory with documents regarding the 1-wire (w1) subsystem.
 watchdog/
 	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
 x86_64/
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index b49b92e..a667eb1 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -218,6 +218,18 @@
 
 and no space around the '.' and "->" structure member operators.
 
+Do not leave trailing whitespace at the ends of lines.  Some editors with
+"smart" indentation will insert whitespace at the beginning of new lines as
+appropriate, so you can start typing the next line of code right away.
+However, some such editors do not remove the whitespace if you end up not
+putting a line of code there, such as if you leave a blank line.  As a result,
+you end up with lines containing trailing whitespace.
+
+Git will warn you about patches that introduce trailing whitespace, and can
+optionally strip the trailing whitespace for you; however, if applying a series
+of patches, this may make later patches in the series fail by changing their
+context lines.
+
 
 		Chapter 4: Naming
 
@@ -726,6 +738,33 @@
 defined that you shouldn't reproduce in your code.
 
 
+		Chapter 18:  Editor modelines and other cruft
+
+Some editors can interpret configuration information embedded in source files,
+indicated with special markers.  For example, emacs interprets lines marked
+like this:
+
+-*- mode: c -*-
+
+Or like this:
+
+/*
+Local Variables:
+compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+End:
+*/
+
+Vim interprets markers that look like this:
+
+/* vim:set sw=8 noet */
+
+Do not include any of these in source files.  People have their own personal
+editor configurations, and your source files should not override them.  This
+includes markers for indentation and mode configuration.  People may use their
+own custom mode, or may have some other magic method for making indentation
+work correctly.
+
+
 
 		Appendix I: References
 
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 46bcff2..fd2ef4d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -139,8 +139,10 @@
 !Elib/cmdline.c
      </sect1>
 
-     <sect1><title>CRC Functions</title>
+     <sect1 id="crc"><title>CRC Functions</title>
+!Elib/crc7.c
 !Elib/crc16.c
+!Elib/crc-itu-t.c
 !Elib/crc32.c
 !Elib/crc-ccitt.c
      </sect1>
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
index 45cad23..2de84dc 100644
--- a/Documentation/DocBook/procfs-guide.tmpl
+++ b/Documentation/DocBook/procfs-guide.tmpl
@@ -352,49 +352,93 @@
       <funcsynopsis>
 	<funcprototype>
 	  <funcdef>int <function>read_func</function></funcdef>
-	  <paramdef>char* <parameter>page</parameter></paramdef>
+	  <paramdef>char* <parameter>buffer</parameter></paramdef>
 	  <paramdef>char** <parameter>start</parameter></paramdef>
 	  <paramdef>off_t <parameter>off</parameter></paramdef>
 	  <paramdef>int <parameter>count</parameter></paramdef>
-	  <paramdef>int* <parameter>eof</parameter></paramdef>
+	  <paramdef>int* <parameter>peof</parameter></paramdef>
 	  <paramdef>void* <parameter>data</parameter></paramdef>
 	</funcprototype>
       </funcsynopsis>
 
       <para>
         The read function should write its information into the
-        <parameter>page</parameter>. For proper use, the function
-        should start writing at an offset of
-        <parameter>off</parameter> in <parameter>page</parameter> and
-        write at most <parameter>count</parameter> bytes, but because
-        most read functions are quite simple and only return a small
-        amount of information, these two parameters are usually
-        ignored (it breaks pagers like <literal>more</literal> and
-        <literal>less</literal>, but <literal>cat</literal> still
-        works).
+        <parameter>buffer</parameter>, which will be exactly
+        <literal>PAGE_SIZE</literal> bytes long.
       </para>
 
       <para>
-        If the <parameter>off</parameter> and
-        <parameter>count</parameter> parameters are properly used,
-        <parameter>eof</parameter> should be used to signal that the
+        The parameter
+        <parameter>peof</parameter> should be used to signal that the
         end of the file has been reached by writing
         <literal>1</literal> to the memory location
-        <parameter>eof</parameter> points to.
+        <parameter>peof</parameter> points to.
       </para>
 
       <para>
-        The parameter <parameter>start</parameter> doesn't seem to be
-        used anywhere in the kernel. The <parameter>data</parameter>
+        The <parameter>data</parameter>
         parameter can be used to create a single call back function for
         several files, see <xref linkend="usingdata"/>.
       </para>
 
       <para>
-        The <function>read_func</function> function must return the
-        number of bytes written into the <parameter>page</parameter>.
+        The rest of the parameters and the return value are described
+	by a comment in <filename>fs/proc/generic.c</filename> as follows:
       </para>
 
+      <blockquote>
+        <para>
+	You have three ways to return data:
+       	</para>
+        <orderedlist>
+          <listitem>
+            <para>
+	      Leave <literal>*start = NULL</literal>.  (This is the default.)
+	      Put the data of the requested offset at that
+	      offset within the buffer.  Return the number (<literal>n</literal>)
+	      of bytes there are from the beginning of the
+	      buffer up to the last byte of data.  If the
+	      number of supplied bytes (<literal>= n - offset</literal>) is
+	      greater than zero and you didn't signal eof
+	      and the reader is prepared to take more data
+	      you will be called again with the requested
+	      offset advanced by the number of bytes
+	      absorbed.  This interface is useful for files
+	      no larger than the buffer.
+	    </para>
+	  </listitem>
+	  <listitem>
+            <para>
+	      Set <literal>*start</literal> to an unsigned long value less than
+	      the buffer address but greater than zero.
+	      Put the data of the requested offset at the
+	      beginning of the buffer.  Return the number of
+	      bytes of data placed there.  If this number is
+	      greater than zero and you didn't signal eof
+	      and the reader is prepared to take more data
+	      you will be called again with the requested
+	      offset advanced by <literal>*start</literal>.  This interface is
+	      useful when you have a large file consisting
+	      of a series of blocks which you want to count
+	      and return as wholes.
+	      (Hack by Paul.Russell@rustcorp.com.au)
+	    </para>
+	  </listitem>
+	  <listitem>
+            <para>
+	      Set <literal>*start</literal> to an address within the buffer.
+	      Put the data of the requested offset at <literal>*start</literal>.
+	      Return the number of bytes of data placed there.
+	      If this number is greater than zero and you
+	      didn't signal eof and the reader is prepared to
+	      take more data you will be called again with the
+	      requested offset advanced by the number of bytes
+	      absorbed.
+	    </para>
+	  </listitem>
+	</orderedlist>
+      </blockquote>
+
       <para>
         <xref linkend="example"/> shows how to use a read call back
         function.
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index f4dffad..42b01bc 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -222,7 +222,15 @@
 	deadlock as soon as the RCU callback happens to interrupt that
 	acquisition's critical section.
 
-13.	SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
+13.	RCU callbacks can be and are executed in parallel.  In many cases,
+	the callback code simply wrappers around kfree(), so that this
+	is not an issue (or, more accurately, to the extent that it is
+	an issue, the memory-allocator locking handles it).  However,
+	if the callbacks do manipulate a shared data structure, they
+	must use whatever locking or other synchronization is required
+	to safely access and/or modify that data structure.
+
+14.	SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
 	may only be invoked from process context.  Unlike other forms of
 	RCU, it -is- permissible to block in an SRCU read-side critical
 	section (demarked by srcu_read_lock() and srcu_read_unlock()),
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 6ebffb5..19e7f65 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -1,4 +1,4 @@
-Linux Kernel patch sumbittal checklist
+Linux Kernel patch submission checklist
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Here are some basic things that developers should do if they want to see their
@@ -9,7 +9,6 @@
 kernel patches.
 
 
-
 1: Builds cleanly with applicable or modified CONFIG options =y, =m, and
    =n.  No gcc warnings/errors, no linker warnings/errors.
 
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 0958e97..3f9a791 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -464,9 +464,25 @@
 Nuff said.  If your code deviates too much from this, it is likely
 to be rejected without further review, and without comment.
 
+Once significant exception is when moving code from one file to
+another in this case you should not modify the moved code at all in
+the same patch which moves it.  This clearly delineates the act of
+moving the code and your changes.  This greatly aids review of the
+actual differences and allows tools to better track the history of
+the code itself.
+
 Check your patches with the patch style checker prior to submission
-(scripts/checkpatch.pl).  You should be able to justify all
-violations that remain in your patch.
+(scripts/checkpatch.pl).  The style checker should be viewed as
+a guide not as the final word.  If your code looks better with
+a violation then its probably best left alone.
+
+The checker reports at three levels:
+ - ERROR: things that are very likely to be wrong
+ - WARNING: things requiring careful review
+ - CHECK: things requiring thought
+
+You should be able to justify all violations that remain in your
+patch.
 
 
 
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index 71acc28..24c5aad 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -49,6 +49,7 @@
 int dbg;
 int print_delays;
 int print_io_accounting;
+int print_task_context_switch_counts;
 __u64 stime, utime;
 
 #define PRINTF(fmt, arg...) {			\
@@ -195,7 +196,7 @@
 	       "IO    %15s%15s\n"
 	       "      %15llu%15llu\n"
 	       "MEM   %15s%15s\n"
-	       "      %15llu%15llu\n\n",
+	       "      %15llu%15llu\n"
 	       "count", "real total", "virtual total", "delay total",
 	       t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
 	       t->cpu_delay_total,
@@ -204,6 +205,14 @@
 	       "count", "delay total", t->swapin_count, t->swapin_delay_total);
 }
 
+void task_context_switch_counts(struct taskstats *t)
+{
+	printf("\n\nTask   %15s%15s\n"
+	       "       %15lu%15lu\n",
+	       "voluntary", "nonvoluntary",
+	       t->nvcsw, t->nivcsw);
+}
+
 void print_ioacct(struct taskstats *t)
 {
 	printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
@@ -235,7 +244,7 @@
 	struct msgtemplate msg;
 
 	while (1) {
-		c = getopt(argc, argv, "diw:r:m:t:p:vl");
+		c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
 		if (c < 0)
 			break;
 
@@ -248,6 +257,10 @@
 			printf("printing IO accounting\n");
 			print_io_accounting = 1;
 			break;
+		case 'q':
+			printf("printing task/process context switch rates\n");
+			print_task_context_switch_counts = 1;
+			break;
 		case 'w':
 			logfile = strdup(optarg);
 			printf("write to file %s\n", logfile);
@@ -389,6 +402,8 @@
 							print_delayacct((struct taskstats *) NLA_DATA(na));
 						if (print_io_accounting)
 							print_ioacct((struct taskstats *) NLA_DATA(na));
+						if (print_task_context_switch_counts)
+							task_context_switch_counts((struct taskstats *) NLA_DATA(na));
 						if (fd) {
 							if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
 								err(1,"write error\n");
diff --git a/Documentation/accounting/taskstats-struct.txt b/Documentation/accounting/taskstats-struct.txt
index 661c797..8aa7529 100644
--- a/Documentation/accounting/taskstats-struct.txt
+++ b/Documentation/accounting/taskstats-struct.txt
@@ -22,6 +22,8 @@
     /* Extended accounting fields end */
     Their values are collected if CONFIG_TASK_XACCT is set.
 
+4) Per-task and per-thread context switch count statistics
+
 Future extension should add fields to the end of the taskstats struct, and
 should not change the relative position of each field within the struct.
 
@@ -158,4 +160,8 @@
 
 	/* Extended accounting fields end */
 
+4) Per-task and per-thread statistics
+	__u64	nvcsw;			/* Context voluntary switch counter */
+	__u64	nivcsw;			/* Context involuntary switch counter */
+
 }
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index debf681..866b761 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -253,7 +253,7 @@
 
 	The first of these two routines is invoked after map_vm_area()
 	has installed the page table entries.  The second is invoked
-	before unmap_vm_area() deletes the page table entries.
+	before unmap_kernel_range() deletes the page table entries.
 
 There exists another whole class of cpu cache issues which currently
 require a whole different set of interfaces to handle properly.
diff --git a/Documentation/cdrom/00-INDEX b/Documentation/cdrom/00-INDEX
index 916dafe..433edf2 100644
--- a/Documentation/cdrom/00-INDEX
+++ b/Documentation/cdrom/00-INDEX
@@ -2,32 +2,10 @@
 	- this file (info on CD-ROMs and Linux)
 Makefile
 	- only used to generate TeX output from the documentation.
-aztcd
-	- info on Aztech/Orchid/Okano/Wearnes/Conrad/CyCDROM driver.
 cdrom-standard.tex
 	- LaTeX document on standardizing the CD-ROM programming interface.
-cdu31a
-	- info on the Sony CDU31A/CDU33A CD-ROM driver.
-cm206
-	- info on the Philips/LMS cm206/cm260 CD-ROM driver.
-gscd
-	- info on the Goldstar R420 CD-ROM driver.
 ide-cd
 	- info on setting up and using ATAPI (aka IDE) CD-ROMs.
-isp16
-	- info on the CD-ROM interface on ISP16, MAD16 or Mozart sound card.
-mcd
-	- info on limitations of standard Mitsumi CD-ROM driver.
-mcdx
-	- info on improved Mitsumi CD-ROM driver.
-optcd
-	- info on the Optics Storage 8000 AT CD-ROM driver
 packet-writing.txt
 	- Info on the CDRW packet writing module
-sbpcd
-	- info on the SoundBlaster/Panasonic CD-ROM interface driver.
-sjcd
-	- info on the SANYO CDR-H94A CD-ROM interface driver.
-sonycd535
-	- info on the Sony CDU-535 (and 531) CD-ROM driver.
 
diff --git a/Documentation/cdrom/aztcd b/Documentation/cdrom/aztcd
deleted file mode 100644
index 6bf0290..0000000
--- a/Documentation/cdrom/aztcd
+++ /dev/null
@@ -1,822 +0,0 @@
-$Id: README.aztcd,v 2.60 1997/11/29 09:51:25 root Exp root $
-          Readme-File Documentation/cdrom/aztcd
-           			for 
-	     AZTECH CD-ROM CDA268-01A, ORCHID CD-3110,
-      OKANO/WEARNES CDD110, CONRAD TXC, CyCDROM CR520, CR540
-                           CD-ROM Drives 
-                       Version 2.6 and newer
-                   (for other drives see 6.-8.)
-
-NOTE: THIS DRIVER WILL WORK WITH THE CD-ROM DRIVES LISTED, WHICH HAVE
-      A PROPRIETARY INTERFACE (implemented on a sound card or on an
-      ISA-AT-bus card). 
-      IT WILL DEFINITELY NOT WORK WITH CD-ROM DRIVES WITH *IDE*-INTERFACE,
-      such as the Aztech CDA269-031SE !!! (The only known exceptions are
-      'faked' IDE drives like the CyCDROM CR520ie which work with aztcd
-      under certain conditions, see 7.). IF YOU'RE USING A CD-ROM DRIVE
-      WITH IDE-INTERFACE, SOMETIMES ALSO CALLED ATAPI-COMPATIBLE, PLEASE 
-      USE THE ide-cd.c DRIVER, WRITTEN BY MARK LORD AND SCOTT SNYDER !
-      THE STANDARD-KERNEL 1.2.x NOW ALSO SUPPORTS IDE-CDROM-DRIVES, SEE THE
-      HARDDISK (!) SECTION OF make config, WHEN COMPILING A NEW KERNEL!!!
-----------------------------------------------------------------------------
-
-Contents of this file:
-                         1.  NOTE
-                         2.  INSTALLATION
-                         3.  CONFIGURING YOUR KERNEL
-                         4.  RECOMPILING YOUR KERNEL
-                         4.1   AZTCD AS A RUN-TIME LOADABLE MODULE
-                         4.2   CDROM CONNECTED TO A SOUNDCARD
-                         5.  KNOWN PROBLEMS, FUTURE DEVELOPMENTS
-			 5.1   MULTISESSION SUPPORT
-			 5.2   STATUS RECOGNITION
-			 5.3   DOSEMU's CDROM SUPPORT
-                         6.  BUG REPORTS
-                         7.  OTHER DRIVES
-                         8.  IF YOU DON'T SUCCEED ... DEBUGGING  
-                         9.  TECHNICAL HISTORY OF THE DRIVER
-                        10.  ACKNOWLEDGMENTS
-                        11.  PROGRAMMING ADD ONS: CDPLAY.C
-                        APPENDIX: Source code of cdplay.c
-----------------------------------------------------------------------------
-
-1. NOTE 
-This software has been successfully in alpha and beta test and is part of
-the standard kernel since kernel 1.1.8x since December 1994. It works with
-AZTECH CDA268-01A, ORCHID CDS-3110, ORCHID/WEARNES CDD110 and CONRAD TXC 
-(Nr.99 31 23 -series 04) and has proven to be stable with kernel 
-versions 1.0.9 and newer. But with any software there still may be bugs in it. 
-So if you encounter problems, you are invited to help us improve this software. 
-Please send me a detailed bug report (see chapter BUG REPORTS). You are also 
-invited in helping us to increase the number of drives, which are supported.
-
-Please read the README-files carefully and always keep a backup copy of your 
-old kernel, in order to reboot if something goes wrong!
-
-2. INSTALLATION
-The driver consists of a header file 'aztcd.h', which normally should reside 
-in /usr/src/linux/drivers/cdrom and the source code 'aztcd.c', which normally 
-resides in the same place. It uses /dev/aztcd (/dev/aztcd0 in some distri-
-butions), which must be a valid block device with major number 29 and reside 
-in directory /dev. To mount a CD-ROM, your kernel needs to have the ISO9660-
-filesystem support included.
-
-PLEASE NOTE: aztcd.c has been developed in parallel to the linux kernel,
-which had and is having many major and minor changes which are not backward
-compatible. Quite definitely aztcd.c version 1.80 and newer will NOT work
-in kernels older than 1.3.33. So please always use the most recent version
-of aztcd.c with the appropriate linux-kernel.
-
-3.  CONFIGURING YOUR KERNEL
-If your kernel is already configured for using the AZTECH driver you will
-see the following message while Linux boots:
-    Aztech CD-ROM Init: DriverVersion=<version number> BaseAddress=<baseaddress>
-    Aztech CD-ROM Init: FirmwareVersion=<firmware version id of your I/O-card>>>
-    Aztech CD-ROM Init: <drive type> detected
-    Aztech CD-ROM Init: End
-If the message looks different and you are sure to have a supported drive,
-it may have a different base address. The Aztech driver does look for the 
-CD-ROM drive at the base address specified in aztcd.h at compile time. This 
-address can be overwritten by boot parameter aztcd=....You should reboot and 
-start Linux with boot parameter aztcd=<base address>, e.g. aztcd=0x320. If 
-you do not know the base address, start your PC with DOS and look at the boot 
-message of your CD-ROM's DOS driver. If that still does not help, use boot
-parameter aztcd=<base address>,0x79 , this tells aztcd to try a little harder.
-aztcd may be configured to use autoprobing the base address by recompiling
-it (see chapter 4.).
-
-If the message looks correct, as user 'root' you should be able to mount the 
-drive by
-          mount -t iso9660 -r /dev/aztcd0 /mnt
-and use it as any other filesystem. (If this does not work, check if
-/dev/aztcd0 and /mnt do exist and create them, if necessary by doing
-      mknod /dev/aztcd0 b 29 0
-      mkdir /mnt                       
-
-If you still get a different message while Linux boots or when you get the 
-message, that the ISO9660-filesystem is not supported by your kernel, when
-you try to mount the CD-ROM drive, you have to recompile your kernel.
-
-If you do *not* have an Aztech/Orchid/Okano/Wearnes/TXC drive and want to 
-bypass drive detection during Linux boot up, start with boot parameter aztcd=0.
-
-Most distributions nowadays do contain a boot disk image containing aztcd.
-Please note, that this driver will not work with IDE/ATAPI drives! With these 
-you must use ide-cd.c instead.
-
-4. RECOMPILING YOUR KERNEL
-If your kernel is not yet configured for the AZTECH driver and the ISO9660-
-filesystem, you have to recompile your kernel: 
-
-- Edit aztcd.h to set the I/O-address to your I/O-Base address (AZT_BASE_ADDR), 
-  the driver does not use interrupts or DMA, so if you are using an AZTECH
-  CD268, an ORCHID CD-3110 or ORCHID/WEARNES CDD110 that's the only item you 
-  have to set up. If you have a soundcard, read chapter 4.2.
-  Users of other drives should read chapter OTHER DRIVES of this file.
-  You also can configure that address by kernel boot parameter aztcd=... 
-- aztcd may be configured to use autoprobing the base address by setting
-  AZT_BASE_ADDR to '-1'. In that case aztcd probes the addresses listed 
-  under AZT_BASE_AUTO. But please remember, that autoprobing always may 
-  incorrectly influence other hardware components too!
-- There are some other points, which may be configured, e.g. auto-eject the
-  CD when unmounting a drive, tray locking etc., see aztcd.h for details.
-- If you're using a linux kernel version prior to 2.1.0, in aztcd.h
-  uncomment the line '#define AZT_KERNEL_PRIOR_2_1'
-- Build a new kernel, configure it for 'Aztech/Orchid/Okano/Wearnes support' 
-  (if you want aztcd to be part of the kernel). Do not configure it for
-  'Aztech... support', if you want to use aztcd as a run time loadable module. 
-  But in any case you must have the ISO9660-filesystem included in your
-  kernel.
-- Activate the new kernel, normally this is done by running LILO (don't for-
-  get to configure it before and to keep a copy of your old kernel in case
-  something goes wrong!).
-- Reboot
-- If you've included aztcd in your kernel, you now should see during boot 
-  some messages like
-    Aztech CD-ROM Init: DriverVersion=<version number> BaseAddress=<baseaddress>
-    Aztech CD-ROM Init: FirmwareVersion=<firmware version id of your I/O-card>
-    Aztech CD-ROM Init: <drive type> detected
-    Aztech CD-ROM Init: End
-- If you have not included aztcd in your kernel, but want to load aztcd as a 
-  run time loadable module see 4.1. 
-- If the message looks correct, as user 'root' you should be able to mount 
-  the drive by
-          mount -t iso9660 -r /dev/aztcd0 /mnt
-  and use it as any other filesystem. (If this does not work, check if
-  /dev/aztcd0 and /mnt do exist and create them, if necessary by doing
-      mknod /dev/aztcd0 b 29 0
-      mkdir /mnt                       
-- If this still does not help, see chapters OTHER DRIVES and DEBUGGING.
-
-4.1 AZTCD AS A RUN-TIME LOADABLE MODULE
-If you do not need aztcd permanently, you can also load and remove the driver
-during runtime via insmod and rmmod. To build aztcd as a loadable module you 
-must configure your kernel for AZTECH module support (answer 'm' when con-
-figuring the kernel). Anyhow, you may run into problems, if the version of 
-your boot kernel is not the same than the source kernel version, from which 
-you create the modules. So rebuild your kernel, if necessary. 
-
-Now edit the base address of your AZTECH interface card in
-/usr/src/linux/drivers/cdrom/aztcd.h to the appropriate value. 
-aztcd may be configured to use autoprobing the base address by setting
-AZT_BASE_ADDR to '-1'. In that case aztcd probes the addresses listed 
-under AZT_BASE_AUTO. But please remember, that autoprobing always may 
-incorrectly influence other hardware components too!
-There are also some special features which may be configured, e.g. 
-auto-eject a CD when unmounting the drive etc; see aztcd.h for details. 
-Then change to /usr/src/linux and do a 
-                    make modules  
-	            make modules_install
-After that you can run-time load the driver via
-                    insmod /lib/modules/X.X.X/misc/aztcd.o
-and remove it via   rmmod  aztcd.
-If you did not set the correct base address in aztcd.h, you can also supply the
-base address when loading the driver via
-                    insmod /lib/modules/X.X.X/misc/aztcd.o aztcd=<base address>
-Again specifying aztcd=-1 will cause autoprobing.
-If you do not have the iso9660-filesystem in your boot kernel, you also have
-to load it before you can mount the CDROM:
-                    insmod /lib/modules/X.X.X/fs/isofs.o
-The mount procedure works as described in 4. above.
-(In all commands 'X.X.X' is the current linux kernel version number)
-
-4.2 CDROM CONNECTED TO A SOUNDCARD
-Most soundcards do have a bus interface to the CDROM-drive. In many cases
-this soundcard needs to be configured, before the CDROM can be used. This
-configuration procedure consists of writing some kind of initialization
-data to the soundcard registers. The AZTECH-CDROM driver in the moment does
-only support one type of soundcard (SoundWave32). Users of other soundcards
-should try to boot DOS first and let their DOS drivers initialize the
-soundcard and CDROM, then warm boot (or use loadlin) their PC to start
-Linux.
-Support for the CDROM-interface of SoundWave32-soundcards is directly
-implemented in the AZTECH driver. Please edit linux/drivers/cdrom/aztdc.h,
-uncomment line '#define AZT_SW32' and set the appropriate value for
-AZT_BASE_ADDR and AZT_SW32_BASE_ADDR. This support was tested with an Orchid
-CDS-3110 connected to a SoundWave32.
-If you want your soundcard to be supported, find out, how it needs to be
-configured and mail me (see 6.) the appropriate information. 
-
-5. KNOWN PROBLEMS, FUTURE DEVELOPMENTS
-5.1 MULTISESSION SUPPORT
-Multisession support for CD's still is a myth. I implemented and tested a basic
-support for multisession and XA CDs, but I still have not enough CDs and appli-
-cations to test it rigorously. So if you'd like to help me, please contact me
-(Email address see below). As of version 1.4 and newer you can enable the 
-multisession support in aztcd.h by setting AZT_MULTISESSION to 1. Doing so 
-will cause the ISO9660-filesystem to deal with multisession CDs, ie. redirect 
-requests to the Table of Contents (TOC) information from the last session, 
-which contains the info of all previous sessions etc.. If you do set 
-AZT_MULTISESSION to 0, you can use multisession CDs anyway. In that case the 
-drive's firmware will do automatic redirection. For the ISO9660-filesystem any 
-multisession CD  will then look like a 'normal' single session CD. But never-
-theless the data of all sessions are viewable and accessible. So with practical-
-ly all real world applications you won't notice the difference. But as future
-applications may make use of advanced multisession features, I've started to
-implement the interface for the ISO9660 multisession interface via ioctl
-CDROMMULTISESSION.
-
-5.2 STATUS RECOGNITION
-The drive status recognition does not work correctly in all cases. Changing
-a disk or having the door open, when a drive is already mounted, is detected 
-by the Aztech driver itself, but nevertheless causes multiple read attempts
-by the different layers of the ISO9660-filesystem driver, which finally timeout,
-so you have to wait quite a little... But isn't it bad style to change a disk 
-in a mounted drive, anyhow ?!
-
-The driver uses busy wait in most cases for the drive handshake (macros
-STEN_LOW and DTEN_LOW). I tested with a 486/DX2 at 66MHz and a Pentium at
-60MHz and 90MHz. Whenever you use a much faster machine you are likely to get 
-timeout messages. In that case edit aztcd.h and increase the timeout value 
-AZT_TIMEOUT. 
-
-For some 'slow' drive commands I implemented waiting with a timer waitqueue
-(macro STEN_LOW_WAIT). If you get this timeout message, you may also edit
-aztcd.h and increase the timeout value AZT_STATUS_DELAY. The waitqueue has
-shown to be a little critical. If you get kernel panic messages, edit aztcd.c
-and substitute STEN_LOW_WAIT by STEN_LOW. Busy waiting with STEN_LOW is more
-stable, but also causes CPU overhead.
-
-5.3 DOSEMU's CD-ROM SUPPORT
-With release 1.20 aztcd was modified to allow access to CD-ROMS when running
-under dosemu-0.60.0 aztcd-versions before 1.20 are most likely to crash
-Linux, when a CD-ROM is accessed under dosemu. This problem has partly been
-fixed, but still when accessing a directory for the first time the system
-might hang for some 30sec. So be patient, when using dosemu's CD-ROM support
-in combination with aztcd :-) ! 
-This problem has now (July 1995) been fixed by a modification to dosemu's
-CD-ROM driver. The new version came with dosemu-0.60.2, see dosemu's
-README.CDROM.
-
-6. BUG REPORTS
-Please send detailed bug reports and bug fixes via EMail to
-
-        Werner.Zimmermann@fht-esslingen.de
-
-Please include a description of your CD-ROM drive type and interface card, 
-the exact firmware message during Linux bootup, the version number of the 
-AZTECH-CDROM-driver and the Linux kernel version. Also a description of your 
-system's other hardware could be of interest, especially microprocessor type, 
-clock frequency, other interface cards such as soundcards, ethernet adapter, 
-game cards etc..
-
-I will try to collect the reports and make the necessary modifications from 
-time to time. I may also come back to you directly with some bug fixes and 
-ask you to do further testing and debugging.
-
-Editors of CD-ROMs are invited to send a 'cooperation' copy of their
-CD-ROMs to the volunteers, who provided the CD-ROM support for Linux. My
-snail mail address for such 'stuff' is
-           Prof. Dr. W. Zimmermann
-           Fachhochschule fuer Technik Esslingen
-           Fachbereich IT
-           Flandernstrasse 101
-           D-73732 Esslingen
-           Germany
-
-
-7. OTHER DRIVES
-The following drives ORCHID CDS3110, OKANO CDD110, WEARNES CDD110 and Conrad
-TXC Nr. 993123-series 04 nearly look the same as AZTECH CDA268-01A, especially 
-they seem to use the same command codes. So it was quite simple to make the 
-AZTECH driver work with these drives. 
-
-Unfortunately I do not have any of these drives available, so I couldn't test
-it myself. In some installations, it seems necessary to initialize the drive 
-with the DOS driver before (especially if combined with a sound card) and then 
-do a warm boot (CTRL-ALT-RESET) or start Linux from DOS, e.g. with 'loadlin'.
-
-If you do not succeed, read chapter DEBUGGING. Thanks in advance!
-
-Sorry for the inconvenience, but it is difficult to develop for hardware, 
-which you don't have available for testing. So if you like, please help us.
-
-If you do have a CyCDROM CR520ie thanks to Hilmar Berger's help your chances
-are good, that it will work with aztcd. The CR520ie is sold as an IDE-drive
-and really is connected to the IDE interface (primary at 0x1F0 or secondary
-at 0x170, configured as slave, not as master). Nevertheless it is not ATAPI
-compatible but still uses Aztech's command codes.
-
-
-8. DEBUGGING : IF YOU DON'T SUCCEED, TRY THE FOLLOWING
--reread the complete README file
--make sure, that your drive is hardware configured for 
-    transfer mode: polled
-    IRQ:           not used
-    DMA:           not used
-    Base Address:  something like 300, 320 ...
- You can check this, when you start the DOS driver, which came with your
- drive. By appropriately configuring the drive and the DOS driver you can
- check, whether your drive does operate in this mode correctly under DOS. If
- it does not operate under DOS, it won't under Linux.
- If your drive's base address is something like 0x170 or 0x1F0 (and it is
- not a CyCDROM CR520ie or CR 940ie) you most likely are having an IDE/ATAPI-
- compatible drive, which is not supported by aztcd.c, use ide-cd.c instead.
- Make sure the Base Address is configured correctly in aztcd.h, also make
- sure, that /dev/aztcd0 exists with the correct major number (compare it with
- the entry in file /usr/include/linux/major.h for the Aztech drive). 
--insert a CD-ROM and close the tray
--cold boot your PC (i.e. via the power on switch or the reset button)
--if you start Linux via DOS, e.g. using loadlin, make sure, that the DOS
- driver for the CD-ROM drive is not loaded (comment out the calling lines 
- in DOS' config.sys!)
--look for the aztcd: init message during Linux init and note them exactly
--log in as root and do a mount -t iso9660 /dev/aztcd0 /mnt
--if you don't succeed in the first time, try several times. Try also to open
- and close the tray, then mount again. Please note carefully all commands
- you typed in and the aztcd-messages, which you get.
--if you get an 'Aztech CD-ROM init: aborted' message, read the remarks about
- the version string below.
-
-If this does not help, do the same with the following differences 
--start DOS before; make now sure, that the DOS driver for the CD-ROM is 
- loaded under DOS (i.e. uncomment it again in config.sys)
--warm boot your PC (i.e. via CTRL-ALT-DEL)
- if you have it, you can also start via loadlin (try both).
- ...
- Again note all commands and the aztcd-messages.
-
-If you see STEN_LOW or STEN_LOW_WAIT error messages, increase the timeout
-values.
-
-If this still does not help, 
--look in aztcd.c for the lines  #if 0
-                                #define AZT_TEST1
-                                ...
-                                #endif
- and substitute '#if 0' by '#if 1'.
--recompile your kernel and repeat the above two procedures. You will now get 
- a bundle of debugging messages from the driver. Again note your commands
- and the appropriate messages. If you have syslogd running, these messages
- may also be found in syslogd's kernel log file. Nevertheless in some
- installations syslogd does not yet run, when init() is called, thus look for
- the aztcd-messages during init, before the login-prompt appears.
- Then look in aztcd.c, to find out, what happened. The normal calling sequence 
- is: aztcd_init() during Linux bootup procedure init()
- after doing a 'mount -t iso9660 /dev/aztcd0 /mnt' the normal calling sequence is
-     aztcd_open()    -> Status 2c after cold reboot with CDROM or audio CD inserted
-                     -> Status 8  after warm reboot with CDROM inserted          
-                     -> Status 2e after cold reboot with no disk, closed tray
-                     -> Status 6e after cold reboot, mount with door open
-     aztUpdateToc()
-     aztGetDiskInfo()
-     aztGetQChannelInfo()   repeated several times
-     aztGetToc()
-     aztGetQChannelInfo()   repeated several times
-     a list of track information
-     do_aztcd_request()  }  
-     azt_transfer()    } repeated several times
-     azt_poll          }
- Check, if there is a difference in the calling sequence or the status flags!
- 
- There are a lot of other messages, eg. the ACMD-command code (defined in
- aztcd.h), status info from the getAztStatus-command and the state sequence of
- the finite state machine in azt_poll(). The most important are the status
- messages, look how they are defined and try to understand, if they make
- sense in the context where they appear. With a CD-ROM inserted the status 
- should always be 8, except in aztcd_open(). Try to open the tray, insert an
- audio disk, insert no disk or reinsert the CD-ROM and check, if the status
- bits change accordingly. The status bits are the most likely point, where 
- the drive manufacturers may implement changes.
-            
-If you still don't succeed, a good point to start is to look in aztcd.c in 
-function aztcd_init, where the drive should be detected during init. Do the
-following:
--reboot the system with boot parameter 'aztcd=<your base address>,0x79'. With
- parameter 0x79 most of the drive version detection is bypassed. After that 
- you should see the complete version string including leading and trailing 
- blanks during init. 
- Now adapt the statement
-      if ((result[1]=='A')&&(result[2]=='Z' ...)
- in aztcd_init() to exactly match the first 3 or 4 letters you have seen.
--Another point is the 'smart' card detection feature in aztcd_init(). Normally
- the CD-ROM drive is ready, when aztcd_init is trying to read the version
- string and a time consuming ACMD_SOFT_RESET command can be avoided. This is
- detected by looking, if AFL_OP_OK can be read correctly. If the CD-ROM drive 
- hangs in some unknown state, e.g. because of an error before a warm start or 
- because you first operated under DOS, even the version string may be correct, 
- but the following commands will not. Then change the code in such a way, 
- that the ACMD_SOFT_RESET is issued in any case, by substituting the
- if-statement 'if ( ...=AFL_OP_OK)' by 'if (1)'.
-
-If you succeed, please mail me the exact version string of your drive and
-the code modifications, you have made together with a short explanation.
-If you don't succeed, you may mail me the output of the debugging messages.
-But remember, they are only useful, if they are exact and complete and you
-describe in detail your hardware setup and what you did (cold/warm reboot,
-with/without DOS, DOS-driver started/not started, which Linux-commands etc.)
-
-
-9. TECHNICAL HISTORY OF THE DRIVER
-The AZTECH-Driver is a rework of the Mitsumi-Driver. Four major items had to
-be reworked:
-
-a) The Mitsumi drive does issue complete status information acknowledging
-each command, the Aztech drive does only signal that the command was
-processed. So whenever the complete status information is needed, an extra
-ACMD_GET_STATUS command is issued. The handshake procedure for the drive
-can be found in the functions aztSendCmd(), sendAztCmd() and getAztStatus().
-
-b) The Aztech Drive does not have a ACMD_GET_DISK_INFO command, so the
-necessary info about the number of tracks (firstTrack, lastTrack), disk
-length etc. has to be read from the TOC in the lead in track (see function
-aztGetDiskInfo()).
-
-c) Whenever data is read from the drive, the Mitsumi drive is started with a
-command to read an indefinite (0xffffff) number of sectors. When the appropriate 
-number of sectors is read, the drive is stopped by a ACDM_STOP command. This
-does not work with the Aztech drive. I did not find a way to stop it. The
-stop and pause commands do only work in AUDIO mode but not in DATA mode.
-Therefore I had to modify the 'finite state machine' in function azt_poll to
-only read a certain number of sectors and then start a new read on demand. As I 
-have not completely understood, how the buffer/caching scheme of the Mitsumi 
-driver was implemented, I am not sure, if I have covered all cases correctly, 
-whenever you get timeout messages, the bug is most likely to be in that
-function azt_poll() around switch(cmd) .... case ACD_S_DATA. 
-
-d) I did not get information about changing drive mode. So I doubt, that the
-code around function azt_poll() case AZT_S_MODE does work. In my test I have
-not been able to switch to reading in raw mode. For reading raw mode, Aztech
-uses a different command than for cooked mode, which I only have implemen-
-ted in the ioctl-section but not in the section which is used by the ISO9660. 
-
-The driver was developed on an AST PC with Intel 486/DX2, 8MB RAM, 340MB IDE 
-hard disk and on an AST PC with Intel Pentium 60MHz, 16MB RAM, 520MB IDE 
-running Linux kernel version 1.0.9 from the LST 1.8 Distribution. The kernel 
-was compiled with gcc.2.5.8. My CD-ROM drive is an Aztech CDA268-01A. My
-drive says, that it has Firmware Version AZT26801A1.3. It came with an ISA-bus
-interface card and works with polled I/O without DMA and without interrupts.
-The code for all other drives was 'remote' tested and debugged by a number of 
-volunteers on the Internet.
-
-Points, where I feel that possible problems might be and all points where I 
-did not completely understand the drive's behaviour or trust my own code are 
-marked with /*???*/ in the source code. There are also some parts in the 
-Mitsumi driver, where I did not completely understand their code.
-
-
-10. ACKNOWLEDGMENTS
-Without the help of P.Bush, Aztech, who delivered technical information
-about the Aztech Drive and without the help of E.Moenkeberg, GWDG, who did a
-great job in analyzing the command structure of various CD-ROM drives, this
-work would not have been possible. E.Moenkeberg was also a great help in 
-making the software 'kernel ready' and in answering many of the CDROM-related 
-questions in the newsgroups. He really is *the* Linux CD-ROM guru. Thanks 
-also to all the guys on the Internet, who collected valuable technical 
-information about CDROMs. 
-
-Joe Nardone (joe@access.digex.net) was a patient tester even for my first
-trial, which was more than slow, and made suggestions for code improvement.
-Especially the 'finite state machine' azt_poll() was rewritten by Joe to get
-clean C code and avoid the ugly 'gotos', which I copied from mcd.c.
-
-Robby Schirmer (schirmer@fmi.uni-passau.de) tested the audio stuff (ioctls) 
-and suggested a lot of patches for them.
-
-Joseph Piskor and Peter Nugent were the first users with the ORCHID CD3110
-and also were very patient with the problems which occurred.
-
-Reinhard Max delivered the information for the CDROM-interface of the
-SoundWave32 soundcards.
-
-Jochen Kunz and Olaf Kaluza delivered the information for supporting Conrad's 
-TXC drive.
-
-Hilmar Berger delivered the patches for supporting CyCDROM CR520ie.
-
-Anybody, who is interested in these items should have a look at 'ftp.gwdg.de',
-directory 'pub/linux/cdrom' and at 'ftp.cdrom.com', directory 'pub/cdrom'.
-
-11. PROGRAMMING ADD ONs: cdplay.c
-You can use the ioctl-functions included in aztcd.c in your own programs. As
-an example on how to do this, you will find a tiny CD Player for audio CDs 
-named 'cdplay.c'. It allows you to play audio CDs. You can play a specified 
-track, pause and resume or skip tracks forward and backwards. If you quit the 
-program without stopping the  drive, playing is continued. You can also 
-(mis)use cdplay to read and hexdump data disks. You can find the code in the 
-APPENDIX of this file, which you should cut out with an editor and store in a 
-separate file 'cdplay.c'. To compile it and make it executable, do
-  gcc -s -Wall -O2 -L/usr/lib cdplay.c -o /usr/local/bin/cdplay # compiles it
-  chmod +755 /usr/local/bin/cdplay                              # makes it executable
-  ln -s /dev/aztcd0 /dev/cdrom                                  # creates a link
-   (for /usr/lib substitute the top level directory, where your include files 
-    reside,  and for /usr/local/bin the directory, where you want the executable 
-    binary to reside )
-
-You have to set the correct permissions for cdplay *and* for /dev/mcd0 or
-/dev/aztcd0 in order to use it. Remember, that you should not have /dev/cdrom 
-mounted, when you're playing audio CDs. 
-
-This program is just a hack for testing the ioctl-functions in aztcd.c. I will 
-not maintain it, so if you run into problems, discard it or have a look into 
-the source code 'cdplay.c'. The program does only contain a minimum of user 
-protection and input error detection. If you use the commands in the wrong 
-order or if you try to read a CD at wrong addresses, you may get error messages
-or even hang your machine. If you get STEN_LOW, STEN_LOW_WAIT or segment violation 
-error messages when using cdplay, after that, the system might not be stable 
-any more, so you'd better reboot. As the ioctl-functions run in kernel mode,
-most normal Linux-multitasking protection features do not work. By using
-uninitialized 'wild' pointers etc., it is easy to write to other users' data 
-and program areas, destroy kernel tables etc.. So if you experiment with ioctls
-as always when you are doing systems programming and kernel hacking, you
-should have a backup copy of your system in a safe place (and you also
-should try restoring from a backup copy first)!
-
-A reworked and improved version called 'cdtester.c', which has yet more
-features for testing CDROM-drives can be found in
-Documentation/cdrom/sbpcd, written by E.Moenkeberg.
-
-Werner Zimmermann
-Fachhochschule fuer Technik Esslingen
-(EMail: Werner.Zimmermann@fht-esslingen.de)
-October, 1997
-
----------------------------------------------------------------------------
-APPENDIX: Source code of cdplay.c
-
-/* Tiny Audio CD Player
-
-   Copyright 1994, 1995, 1996 Werner Zimmermann (Werner.Zimmermann@fht-esslingen.de)
-
-This program originally was written to test the audio functions of the
-AZTECH.CDROM-driver, but it should work with every CD-ROM drive. Before 
-using it, you should set a symlink from /dev/cdrom to your real CDROM
-device.
-
-The GNU General Public License applies to this program.
-
-History:  V0.1  W.Zimmermann: First release. Nov. 8, 1994
-          V0.2  W.Zimmermann: Enhanced functionality. Nov. 9, 1994
-          V0.3  W.Zimmermann: Additional functions. Nov. 28, 1994          
-          V0.4  W.Zimmermann: fixed some bugs. Dec. 17, 1994
-          V0.5  W.Zimmermann: clean 'scanf' commands without compiler warnings
-                              Jan. 6, 1995
-          V0.6  W.Zimmermann: volume control (still experimental). Jan. 24, 1995
-          V0.7  W.Zimmermann: read raw modified. July 26, 95
-*/
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <linux/cdrom.h>
-#include <linux/../../drivers/cdrom/aztcd.h>
-
-void help(void)
-{ printf("Available Commands:  STOP         s      EJECT/CLOSE  e       QUIT         q\n");
-  printf("                     PLAY TRACK   t      PAUSE        p       RESUME       r\n");
-  printf("                     NEXT TRACK   n      REPEAT LAST  l       HELP         h\n");
-  printf("                     SUB CHANNEL  c      TRACK INFO   i       PLAY AT      a\n");
-  printf("                     READ         d      READ RAW     w       VOLUME       v\n");
-}
-
-int main(void)
-{ int handle;
-  unsigned char command=' ', ini=0, first=1, last=1;
-  unsigned int cmd, i,j,k, arg1,arg2,arg3;
-  struct cdrom_ti       ti;
-  struct cdrom_tochdr   tocHdr;
-  struct cdrom_subchnl  subchnl;
-  struct cdrom_tocentry entry;
-  struct cdrom_msf      msf;
-  union  { struct cdrom_msf msf;
-           unsigned char buf[CD_FRAMESIZE_RAW];
-         } azt;
-  struct cdrom_volctrl  volctrl;
-
-  printf("\nMini-Audio CD-Player V0.72   (C) 1994,1995,1996  W.Zimmermann\n");
-  handle=open("/dev/cdrom",O_RDWR);
-  ioctl(handle,CDROMRESUME);
-  
-  if (handle<=0) 
-    { printf("Drive Error: already playing, no audio disk, door open\n");
-      printf("             or no permission (you must be ROOT in order to use this program)\n");
-    }
-  else
-    { help();
-      while (1)
-        { printf("Type command (h = help):  ");
-          scanf("%s",&command); 
-          switch (command)
-            { case 'e':   cmd=CDROMEJECT;
-                          ioctl(handle,cmd);
-                          break;  
-              case 'p':   if (!ini)
-                             { printf("Command not allowed - play track first\n");
-                             }
-                          else
-                             { cmd=CDROMPAUSE;
-                               if (ioctl(handle,cmd)) printf("Drive Error\n");
-                             }
-                          break;
-              case 'r':   if (!ini)
-                             { printf("Command not allowed - play track first\n");
-                             }
-                          else
-                             { cmd=CDROMRESUME;
-                               if (ioctl(handle,cmd)) printf("Drive Error\n");
-                             }
-                          break;
-              case 's':   cmd=CDROMPAUSE;
-                          if (ioctl(handle,cmd)) printf("Drive error or already stopped\n");
-                          cmd=CDROMSTOP;
-                          if (ioctl(handle,cmd)) printf("Drive error\n");
-                          break;
-              case 't':   cmd=CDROMREADTOCHDR;
-                          if (ioctl(handle,cmd,&tocHdr)) printf("Drive Error\n");
-                          first=tocHdr.cdth_trk0;
-                          last= tocHdr.cdth_trk1;
-                          if ((first==0)||(first>last))
-                            { printf ("--could not read TOC\n");
-                            }
-                          else
-                            { printf("--first track: %d   --last track: %d   --enter track number: ",first,last);
-                              cmd=CDROMPLAYTRKIND;
-                              scanf("%i",&arg1);
-                              ti.cdti_trk0=arg1;
-                              if (ti.cdti_trk0<first) ti.cdti_trk0=first;
-                              if (ti.cdti_trk0>last)  ti.cdti_trk0=last;
-                              ti.cdti_ind0=0;
-                              ti.cdti_trk1=last;
-                              ti.cdti_ind1=0;
-                              if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
-                              ini=1;
-                            } 
-                          break;
-              case 'n':   if (!ini++) 
-                            { if (ioctl(handle,CDROMREADTOCHDR,&tocHdr)) printf("Drive Error\n");
-                              first=tocHdr.cdth_trk0;
-                              last= tocHdr.cdth_trk1;
-                              ti.cdti_trk0=first-1;
-                            }
-                          if ((first==0)||(first>last))
-                            { printf ("--could not read TOC\n");
-                            }
-                          else
-                            { cmd=CDROMPLAYTRKIND;
-                              if (++ti.cdti_trk0 > last)  ti.cdti_trk0=last;
-                              ti.cdti_ind0=0;
-                              ti.cdti_trk1=last;
-                              ti.cdti_ind1=0;
-                              if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
-                              ini=1;
-                            }
-                          break;
-              case 'l':   if (!ini++)
-                            { if (ioctl(handle,CDROMREADTOCHDR,&tocHdr)) printf("Drive Error\n");
-                              first=tocHdr.cdth_trk0;
-                              last= tocHdr.cdth_trk1;
-                              ti.cdti_trk0=first+1;
-                            }
-                          if ((first==0)||(first>last))
-                            { printf ("--could not read TOC\n");
-                            }
-                          else
-                            { cmd=CDROMPLAYTRKIND;
-                              if (--ti.cdti_trk0 < first) ti.cdti_trk0=first;
-                              ti.cdti_ind0=0;
-                              ti.cdti_trk1=last;
-                              ti.cdti_ind1=0;
-                              if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
-                              ini=1;
-                            }  
-                          break;
-              case 'c':   subchnl.cdsc_format=CDROM_MSF;
-                          if (ioctl(handle,CDROMSUBCHNL,&subchnl)) 
-                            printf("Drive Error\n");
-                          else
-                            { printf("AudioStatus:%s   Track:%d  Mode:%d   MSF=%d:%d:%d\n", \
-                              subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY ? "PLAYING":"NOT PLAYING",\
-                              subchnl.cdsc_trk,subchnl.cdsc_adr, \
-                              subchnl.cdsc_absaddr.msf.minute, subchnl.cdsc_absaddr.msf.second, \
-                              subchnl.cdsc_absaddr.msf.frame);
-                            }
-                          break;              
-              case 'i':   if (!ini)
-                            { printf("Command not allowed - play track first\n");
-                            }
-                          else
-                            { cmd=CDROMREADTOCENTRY;
-                              printf("Track No.: ");
-                              scanf("%d",&arg1);
-                              entry.cdte_track=arg1;
-                              if (entry.cdte_track<first) entry.cdte_track=first;
-                              if (entry.cdte_track>last)  entry.cdte_track=last;
-			      entry.cdte_format=CDROM_MSF;
-                              if (ioctl(handle,cmd,&entry)) 
-                               { printf("Drive error or invalid track no.\n");
-                               }
-                              else
-                               { printf("Mode %d Track, starts at %d:%d:%d\n", \
-                               entry.cdte_adr,entry.cdte_addr.msf.minute, \
-                               entry.cdte_addr.msf.second,entry.cdte_addr.msf.frame);
-                               }
-                            }
-                          break;
-              case 'a':   cmd=CDROMPLAYMSF;
-                          printf("Address (min:sec:frame)  ");
-                          scanf("%d:%d:%d",&arg1,&arg2,&arg3);
-                          msf.cdmsf_min0  =arg1;
-                          msf.cdmsf_sec0  =arg2;
-                          msf.cdmsf_frame0=arg3;
-                          if (msf.cdmsf_sec0  > 59) msf.cdmsf_sec0  =59;
-                          if (msf.cdmsf_frame0> 74) msf.cdmsf_frame0=74;
-                          msf.cdmsf_min1=60;
-                          msf.cdmsf_sec1=00;
-                          msf.cdmsf_frame1=00;
-                          if (ioctl(handle,cmd,&msf)) 
-                           { printf("Drive error or invalid address\n");
-                           }
-                          break;
-#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
-              case 'd':   cmd=CDROMREADCOOKED;
-                          printf("Address (min:sec:frame)  ");
-                          scanf("%d:%d:%d",&arg1,&arg2,&arg3);
-                          azt.msf.cdmsf_min0  =arg1;
-                          azt.msf.cdmsf_sec0  =arg2;
-                          azt.msf.cdmsf_frame0=arg3;
-                          if (azt.msf.cdmsf_sec0  > 59) azt.msf.cdmsf_sec0  =59;
-                          if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
-                          if (ioctl(handle,cmd,&azt.msf)) 
-                           { printf("Drive error, invalid address or unsupported command\n");
-                           }
-                          k=0;
-                          getchar();
-                          for (i=0;i<128;i++)
-                           { printf("%4d:",i*16);
-                             for (j=0;j<16;j++)
-                               { printf("%2x ",azt.buf[i*16+j]);
-                               }
-                             for (j=0;j<16;j++)
-                               { if (isalnum(azt.buf[i*16+j])) 
-                                   printf("%c",azt.buf[i*16+j]);
-                                 else
-                                   printf(".");
-                               }
-                             printf("\n"); 
-                             k++;
-                             if (k>=20)
-                              { printf("press ENTER to continue\n");
-                                getchar();
-                                k=0;
-                              }
-                           } 
-                          break;
-              case 'w':   cmd=CDROMREADRAW;
-                          printf("Address (min:sec:frame)  ");
-                          scanf("%d:%d:%d",&arg1,&arg2,&arg3);
-                          azt.msf.cdmsf_min0  =arg1;
-                          azt.msf.cdmsf_sec0  =arg2;
-                          azt.msf.cdmsf_frame0=arg3;                          
-                          if (azt.msf.cdmsf_sec0  > 59) azt.msf.cdmsf_sec0  =59;
-                          if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
-                          if (ioctl(handle,cmd,&azt)) 
-                           { printf("Drive error, invalid address or unsupported command\n");
-                           }
-                          k=0;
-                          for (i=0;i<147;i++)
-                           { printf("%4d:",i*16);
-                             for (j=0;j<16;j++)
-                               { printf("%2x ",azt.buf[i*16+j]);
-                               }
-                             for (j=0;j<16;j++)
-                               { if (isalnum(azt.buf[i*16+j])) 
-                                   printf("%c",azt.buf[i*16+j]);
-                                 else
-                                   printf(".");
-                               }
-                             printf("\n"); 
-                             k++;
-                             if (k>=20)
-                              { getchar();
-                                k=0;
-                              }
-                           } 
-                          break;
-#endif
-              case 'v':   cmd=CDROMVOLCTRL;
-                          printf("--Channel 0 Left  (0-255): ");
-                          scanf("%d",&arg1);
-                          printf("--Channel 1 Right (0-255): ");
-                          scanf("%d",&arg2);
-                          volctrl.channel0=arg1;
-                          volctrl.channel1=arg2;
-                          volctrl.channel2=0;
-                          volctrl.channel3=0;
-                          if (ioctl(handle,cmd,&volctrl)) 
-                           { printf("Drive error or unsupported command\n");
-                           }
-                          break;  
-              case 'q':   if (close(handle)) printf("Drive Error: CLOSE\n");
-                          exit(0);
-              case 'h':   help();
-                          break;
-              default:    printf("unknown command\n");
-                          break;
-            }
-       }
-    }
-  return 0;
-}
diff --git a/Documentation/cdrom/cdu31a b/Documentation/cdrom/cdu31a
deleted file mode 100644
index c0667da..0000000
--- a/Documentation/cdrom/cdu31a
+++ /dev/null
@@ -1,196 +0,0 @@
-
-		CDU31A/CDU33A Driver Info
-		-------------------------
-
-Information on the Sony CDU31A/CDU33A CDROM driver for the Linux
-kernel.
-
-   Corey Minyard (minyard@metronet.com)
-  
-   Colossians 3:17
-
-Crude Table of Contents
------------------------
-
-  Setting Up the Hardware
-  Configuring the Kernel
-  Configuring as a Module
-  Driver Special Features
-
-  
-This device driver handles Sony CDU31A/CDU33A CDROM drives and
-provides a complete block-level interface as well as an ioctl()
-interface as specified in include/linux/cdrom.h).  With this
-interface, CDROMs can be accessed, standard audio CDs can be played
-back normally, and CD audio information can be read off the drive.
-
-Note that this will only work for CDU31A/CDU33A drives.  Some vendors
-market their drives as CDU31A compatible.  They lie.  Their drives are
-really CDU31A hardware interface compatible (they can plug into the
-same card).  They are not software compatible.
-
-Setting Up the Hardware
------------------------
-
-The CDU31A driver is unable to safely tell if an interface card is
-present that it can use because the interface card does not announce
-its presence in any way besides placing 4 I/O locations in memory.  It
-used to just probe memory and attempt commands, but Linus wisely asked
-me to remove that because it could really screw up other hardware in
-the system.
-
-Because of this, you must tell the kernel where the drive interface
-is, what interrupts are used, and possibly if you are on a PAS-16
-soundcard.
-
-If you have the Sony CDU31A/CDU33A drive interface card, the following
-diagram will help you set it up.  If you have another card, you are on
-your own.  You need to make sure that the I/O address and interrupt is
-not used by another card in the system.  You will need to know the I/O
-address and interrupt you have set.  Note that use of interrupts is
-highly recommended, if possible, it really cuts down on CPU used.
-Unfortunately, most soundcards do not support interrupts for their
-CDROM interfaces.  By default, the Sony interface card comes with
-interrupts disabled.
-   
-        +----------+-----------------+----------------------+
-        |  JP1     |  34 Pin Conn    |                      |
-        |  JP2     +-----------------+                      |
-        |  JP3                                              |
-        |  JP4                                              |
-        |                                                   +--+
-        |                                                   |  +-+
-        |                                                   |  | |  External
-        |                                                   |  | |  Connector
-        |                                                   |  | |
-        |                                                   |  +-+
-        |                                                   +--+
-        |                                                   |
-        |                                          +--------+
-        |                                          |
-        +------------------------------------------+
-   
-      JP1 sets the Base Address, using the following settings:
-   
-        Address         Pin 1           Pin 2
-        -------         -----           -----
-        0x320           Short           Short
-        0x330           Short           Open
-        0x340           Open            Short
-        0x360           Open            Open
-   
-      JP2 and JP3 configure the DMA channel; they must be set the same.
-   
-        DMA             Pin 1           Pin 2           Pin 3
-        ---             -----           -----           -----
-        1               On              Off             On
-        2               Off             On              Off
-        3               Off             Off             On
-   
-      JP4 Configures the IRQ:
-   
-        IRQ     Pin 1           Pin 2           Pin 3           Pin 4
-        ---     -----           -----           -----           -----
-        3       Off             Off             On              Off
-        4       Off             Off*            Off             On
-        5       On              Off             Off             Off
-        6       Off             On              Off             Off
-   
-                  The documentation states to set this for interrupt
-                  4, but I think that is a mistake.
-
-Note that if you have another interface card, you will need to look at
-the documentation to find the I/O base address.  This is specified to
-the SLCD.SYS driver for DOS with the /B: parameter, so you can look at
-you DOS driver setup to find the address, if necessary.
-
-Configuring the Kernel
-----------------------
-
-You must tell the kernel where the drive is at boot time.  This can be
-done at the Linux boot prompt, by using LILO, or by using Bootlin.
-Note that this is no substitute for HOWTOs and LILO documentation, if
-you are confused please read those for info on bootline configuration
-and LILO.
-
-At the linux boot prompt, press the ALT key and add the following line
-after the boot name (you can let the kernel boot, it will tell you the
-default boot name while booting):
-
-	cdu31a=<base address>,<interrupt>[,PAS]
-
-The base address needs to have "0x" in front of it, since it is in
-hex.  For instance, to configure a drive at address 320 on interrupt 5,
-use the following:
-
-	cdu31a=0x320,5
-
-I use the following boot line:
-
-	cdu31a=0x1f88,0,PAS
-
-because I have a PAS-16 which does not support interrupt for the
-CDU31A interface.
-
-Adding this as an append line at the beginning of the /etc/lilo.conf
-file will set it for lilo configurations.  I have the following as the
-first line in my lilo.conf file:
-
-	append="cdu31a=0x1f88,0"
-
-I'm not sure how to set up Bootlin (I have never used it), if someone
-would like to fill in this section please do.
-
-
-Configuring as a Module
------------------------
-
-The driver supports loading as a module.  However, you must specify
-the boot address and interrupt on the boot line to insmod.  You can't
-use modprobe to load it, since modprobe doesn't support setting
-variables.
-
-Anyway, I use the following line to load my driver as a module
-
-  /sbin/insmod /lib/modules/`uname -r`/misc/cdu31a.o cdu31a_port=0x1f88
-
-You can set the following variables in the driver:
-
-  cdu31a_port=<I/O address> - sets the base I/O.  If hex, put 0x in
-			      front of it.  This must be specified.
-
-  cdu31a_irq=<interrupt> - Sets the interrupt number.  Leaving this
-			   off will turn interrupts off.
-
-
-Driver Special Features
------------------------
-
-This section describes features beyond the normal audio and CD-ROM
-functions of the drive.
-
-2048 byte buffer mode
-
-If a disk is mounted with -o block=2048, data is copied straight from
-the drive data port to the buffer.  Otherwise, the readahead buffer
-must be involved to hold the other 1K of data when a 1K block
-operation is done.  Note that with 2048 byte blocks you cannot execute
-files from the CD.
-
-XA compatibility
-
-The driver should support XA disks for both the CDU31A and CDU33A.  It
-does this transparently, the using program doesn't need to set it.
-
-Multi-Session
-
-A multi-session disk looks just like a normal disk to the user.  Just
-mount one normally, and all the data should be there.  A special
-thanks to Koen for help with this!
-
-Raw sector I/O
-
-Using the CDROMREADAUDIO it is possible to read raw audio and data
-tracks.  Both operations return 2352 bytes per sector.  On the data
-tracks, the first 12 bytes is not returned by the drive and the value
-of that data is indeterminate.
diff --git a/Documentation/cdrom/cm206 b/Documentation/cdrom/cm206
deleted file mode 100644
index 810368f..0000000
--- a/Documentation/cdrom/cm206
+++ /dev/null
@@ -1,185 +0,0 @@
-This is the readme file for the driver for the Philips/LMS cdrom drive
-cm206 in combination with the cm260 host adapter card. 
-
-				(c) 1995 David A. van Leeuwen
-   
-Changes since version 0.99
---------------------------
-- Interfacing to the kernel is routed though an extra interface layer, 
-  cdrom.c. This allows runtime-configurable `behavior' of the cdrom-drive, 
-  independent of the driver. 
-
-Features since version 0.33
----------------------------
-- Full audio support, that is, both  workman, workbone and cdp work
-  now reasonably. Reading TOC still takes some time. xmcd has been
-  reported to run successfully. 
-- Made auto-probe code a little better, I hope
-
-Features since version 0.28
----------------------------
-- Full speed transfer rate (300 kB/s).
-- Minimum kernel memory usage for buffering (less than 3 kB).
-- Multisession support.
-- Tray locking.
-- Statistics of driver accessible to the user.
-- Module support.
-- Auto-probing of adapter card's base port and irq line,
-  also configurable at boot time or module load time.
-
-
-Decide how you are going to use the driver. There are two
-options:
-
-   (a) installing the driver as a resident part of the kernel
-   (b) compiling the driver as a loadable module
-
-   Further, you must decide if you are going to specify the base port
-   address and the interrupt request line of the adapter card cm260 as
-   boot options for (a), module parameters for (b), use automatic
-   probing of these values, or hard-wire your adaptor card's settings
-   into the source code. If you don't care, you can choose 
-   autoprobing, which is the default. In that case you can move on to
-   the next step.
-
-Compiling the kernel
---------------------
-1) move to /usr/src/linux and do a 
-
-	make config
-
-   If you have chosen option (a), answer yes to CONFIG_CM206 and
-   CONFIG_ISO9660_FS.
-
-   If you have chosen option (b), answer yes to CONFIG_MODVERSIONS
-   and no (!) to CONFIG_CM206 and CONFIG_ISO9660_FS. 
-
-2) then do a 
-	
-	make clean; make zImage; make modules
-
-3) do the usual things to install a new image (backup the old one, run
-   `rdev -R zImage 1', copy the new image in place, run lilo).  Might
-   be `make zlilo'.
-
-Using the driver as a module
-----------------------------
-If you will only occasionally use the cd-rom driver, you can choose
-option (b), install as a loadable module. You may have to re-compile
-the module when you upgrade the kernel to a new version. 
-
-Since version 0.96, much of the functionality has been transferred to
-a generic cdrom interface in the file cdrom.c. The module cm206.o
-depends on cdrom.o. If the latter is not compiled into the kernel,
-you must explicitly load it before cm206.o:
-
-	 insmod /usr/src/linux/modules/cdrom.o
-
-To install the module, you use the command, as root
-
-	insmod /usr/src/linux/modules/cm206.o
-
-You can specify the base address on the command line as well as the irq 
-line to be used, e.g.
-
-	insmod /usr/src/linux/modules/cm206.o cm206=0x300,11
-
-The order of base port and irq line doesn't matter; if you specify only
-one, the other will have the value of the compiled-in default.  You
-may also have to install the file-system module `iso9660.o', if you
-didn't compile that into the kernel. 
-
-
-Using the driver as part of the kernel
---------------------------------------
-If you have chosen option (a), you can specify the base-port
-address and irq on the lilo boot command line, e.g.:
-
-	LILO: linux cm206=0x340,11
-
-This assumes that your linux kernel image keyword is `linux'. 
-If you specify either IRQ (3--11) or base port (0x300--0x370),
-auto probing is turned off for both settings, thus setting the 
-other value to the compiled-in default.
-
-Note that you can also put these parameters in the lilo configuration file:
-
-# linux config
-image = /vmlinuz
-   root = /dev/hda1
-   label = Linux
-   append = "cm206=0x340,11"
-   read-only
-
-
-If module parameters and LILO config options don't work
--------------------------------------------------------
-If autoprobing does not work, you can hard-wire the default values
-of the base port address (CM206_BASE) and interrupt request line
-(CM206_IRQ) into the file /usr/src/linux/drivers/cdrom/cm206.h. Change
-the defines of CM206_IRQ and CM206_BASE.
-
-
-Mounting the cdrom
-------------------
-1) Make sure that the right device is installed in /dev.
-
-  	mknod /dev/cm206cd b 32 0
-
-2) Make sure there is a mount point, e.g., /cdrom 
-
-	mkdir /cdrom
-
-3) mount using a command like this (run as root):
-
-	mount -rt iso9660 /dev/cm206cd /cdrom
-
-4) For user-mounts, add a line in /etc/fstab
-
-	/dev/cm206cd      /cdrom     iso9660 	ro,noauto,user
-
-   This will allow users to give the commands
-
-	mount /cdrom
-	umount /cdrom
-
-If things don't work
---------------------
-
-- Try to do a `dmesg' to find out if the driver said anything about
-  what is going wrong during the initialization.
-
-- Try to do a `dd if=/dev/cm206cd | od -tc | less' to read from the
-  CD.
-
-- Look in the /proc directory to see if `cm206' shows up under one of
-  `interrupts', `ioports', `devices' or `modules' (if applicable).
-
-
-DISCLAIMER 
----------- 
-I cannot guarantee that this driver works, or that the hardware will
-not be harmed, although I consider it most unlikely. 
-
-I hope that you'll find this driver in some way useful. 
-
-					David van Leeuwen
-					david@tm.tno.nl
-
-Note for Linux CDROM vendors
------------------------------
-You are encouraged to include this driver on your Linux CDROM. If
-you do, you might consider sending me a free copy of that cd-rom.
-You can contact me through my e-mail address, david@tm.tno.nl. 
-If this driver is compiled into a kernel to boot off a cdrom, 
-you should actually send me a free copy of that cd-rom. 
-
-Copyright
----------
-The copyright of the cm206 driver for Linux is 
-
-    (c) 1995 David A. van Leeuwen
-
-The driver is released under the conditions of the GNU general public
-license, which can be found in the file COPYING in the root of this
-source tree.
diff --git a/Documentation/cdrom/gscd b/Documentation/cdrom/gscd
deleted file mode 100644
index d01ca36..0000000
--- a/Documentation/cdrom/gscd
+++ /dev/null
@@ -1,60 +0,0 @@
-	Goldstar R420 CD-Rom device driver README
-
-For all kind of other information about the GoldStar R420 CDROM
-and this Linux device driver see the WWW page:
-
-        http://linux.rz.fh-hannover.de/~raupach        
-
-
-      If you are the editor of a Linux CD, you should
-      enable gscd.c within your boot floppy kernel. Please,
-      send me one of your CDs for free.
-
-
-This current driver version 0.4a only supports reading data from the disk.
-Currently we have no audio and no multisession or XA support.
-The polling interface is used, no DMA.
-
-
-Sometimes the GoldStar R420 is sold in a 'Reveal Multimedia Kit'. This kit's
-drive interface is compatible, too.
-
-
-Installation
-------------
-
-Change to '/usr/src/linux/drivers/cdrom' and edit the file 'gscd.h'. Insert
-the i/o address of your interface card.
-
-The default base address is 0x340. This will work for most applications. 
-Address selection is accomplished by jumpers PN801-1 to PN801-4 on the 
-GoldStar Interface Card.
-Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
-0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0             
-
-Then go back to '/usr/src/linux/' and 'make config' to build the new
-configuration for your kernel. If you want to use the GoldStar driver
-like a module, don't select 'GoldStar CDROM support'. By the way, you
-have to include the iso9660 filesystem.
-
-Now start compiling the kernel with 'make zImage'.
-If you want to use the driver as a module, you have to do 'make modules' 
-and 'make modules_install', additionally.
-Install your new kernel as usual - maybe you do it with 'make zlilo'.
-
-Before you can use the driver, you have to
-   mknod /dev/gscd0 b 16 0
-to create the appropriate device file (you only need to do this once).
-
-If you use modules, you can try to insert the driver.
-Say: 'insmod /usr/src/linux/modules/gscd.o'
-or:  'insmod /usr/src/linux/modules/gscd.o gscd=<address>'
-The driver should report its results.
-
-That's it! Mount a disk, i.e. 'mount -rt iso9660 /dev/gscd0 /cdrom'
-
-Feel free to report errors and suggestions to the following address.
-Be sure, I'm very happy to receive your comments!
- 
-        Oliver Raupach                                Hannover, Juni 1995
-(raupach@nwfs1.rz.fh-hannover.de)
diff --git a/Documentation/cdrom/isp16 b/Documentation/cdrom/isp16
deleted file mode 100644
index cc86533..0000000
--- a/Documentation/cdrom/isp16
+++ /dev/null
@@ -1,100 +0,0 @@
- -- Documentation/cdrom/isp16
-
-Docs by Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
-
-This is the README for version 0.6 of the cdrom interface on an
-ISP16, MAD16 or Mozart sound card.
-
-The detection and configuration of this interface used to be included
-in both the sjcd and optcd cdrom driver. Drives supported by these
-drivers came packed with Media Magic's multi media kit, which also
-included the ISP16 card. The idea (thanks Leo Spiekman)
-to move it from these drivers into a separate module and moreover, not to
-rely on the MAD16 sound driver, are as follows:
--duplication of code in the kernel is a waste of resources and should
- be avoided;
--however, kernels and notably those included with Linux distributions
- (cf Slackware 3.0 included version 0.5 of the isp16 configuration
- code included in the drivers) don't always come with sound support
- included. Especially when they already include a bunch of cdrom drivers.
- Hence, the cdrom interface should be configurable _independently_ of
- sound support.
-
-The ISP16, MAD16 and Mozart sound cards have an OPTi 82C928 or an
-OPTi 82C929 chip.  The interface on these cards should work with
-any cdrom attached to the card, which is 'electrically' compatible
-with Sanyo/Panasonic, Sony or Mitsumi non-ide drives. However, the
-command sets for any proprietary drives may differ
-(and hence may not be supported in the kernel) from these four types.
-For a fact I know the interface works and the way of configuration
-as described in this documentation works in combination with the
-sjcd (in Sanyo/Panasonic compatibility mode) cdrom drivers
-(probably with the optcd (in Sony compatibility mode) as well).
-If you have such an OPTi based sound card and you want to use the
-cdrom interface with a cdrom drive supported by any of the other cdrom
-drivers, it will probably work. Please let me know any experience you
-might have).
-I understand that cards based on the OPTi 82C929 chips may be configured
-(hardware jumpers that is) as an IDE interface. Initialisation of such a
-card in this mode is not supported (yet?).
-
-The suggestion to configure the ISP16 etc. sound card by booting DOS and 
-do a warm reboot to boot Linux somehow doesn't work, at least not
-on my machine (IPC P90), with the OPTi 82C928 based card.
-
-Booting the kernel through the boot manager LILO allows the use
-of some command line options on the 'LILO boot:' prompt. At boot time
-press Alt or Shift while the LILO prompt is written on the screen and enter
-any kernel options. Alternatively these options may be used in
-the appropriate section in /etc/lilo.conf. Adding 'append="<cmd_line_options>"'
-will do the trick as well.
-The syntax of 'cmd_line_options' is
-
-        isp16=[<port>[,<irq>[,<dma>]]][[,]<drive_type>]
-
-If there is no ISP16 or compatibles detected, there's probably no harm done.
-These options indicate the values that your cdrom drive has been (or will be)
-configured to use.
-Valid values for the base i/o address are:
-  port=0x340,0x320,0x330,0x360
-for the interrupt request number 
-  irq=0,3,5,7,9,10,11
-for the direct memory access line
-  dma=0,3,5,6,7
-and for the type of drive
-  drive_type=noisp16,Sanyo,Panasonic,Sony,Mitsumi.
-Note that these options are case sensitive.
-The values 0 for irq and dma indicate that they are not used, and
-the drive will be used in 'polling' mode. The values 5 and 7 for irq
-should be avoided in order to avoid any conflicts with optional
-sound card configuration.
-The syntax of the command line does not allow the specification of
-irq when there's nothing specified for the base address and no
-specification of dma when there is no specification of irq.
-The value 'noisp16' for drive_type, which may be used as the first
-non-integer option value (e.g. 'isp16=noisp16'), makes sure that probing
-for and subsequent configuration of an ISP16-compatible card is skipped
-all together. This can be useful to overcome possible conflicts which
-may arise while the kernel is probing your hardware.
-The default values are
-  port=0x340
-  irq=0
-  dma=0
-  drive_type=Sanyo
-reflecting my own configuration. The defaults can be changed in
-the file linux/drivers/cdrom/ips16.h.
-
-The cdrom interface can be configured at run time by loading the
-initialisation driver as a module. In that case, the interface
-parameters can be set by giving appropriate values on the command
-line. Configuring the driver can then be done by the following
-command (assuming you have iso16.o installed in a proper place):
-
-  insmod isp16.o isp16_cdrom_base=<port> isp16_cdrom_irq=<irq> \
-    isp16_cdrom_dma=<dma> isp16_cdrom_type=<drive_type>
-
-where port, irq, dma and drive_type can have any of the values mentioned
-above.
-
-
-Have fun!
diff --git a/Documentation/cdrom/mcdx b/Documentation/cdrom/mcdx
deleted file mode 100644
index 2bac4b7..0000000
--- a/Documentation/cdrom/mcdx
+++ /dev/null
@@ -1,29 +0,0 @@
-If you are using the driver as a module, you can specify your ports and IRQs
-like
-
- # insmod mcdx.o mcdx=0x300,11,0x304,5
-
-and so on ("address,IRQ" pairs).
-This will override the configuration in mcdx.h.
-
-This driver:
-
-    o   handles XA and (hopefully) multi session CDs as well as
-        ordinary CDs;
-    o   supports up to 5 drives (of course, you'll need free 
-        IRQs, i/o ports and slots);
-    o   plays audio
-
-This version doesn't support yet:
-
-    o   shared IRQs (but it seems to be possible - I've successfully
-                connected two drives to the same irq.  So it's `only' a 
-                problem of the driver.)
-
-This driver never will:
-
-    o   Read digital audio (i.e. copy directly), due to missing
-        hardware features. 
-
-
-heiko@lotte.sax.de
diff --git a/Documentation/cdrom/optcd b/Documentation/cdrom/optcd
deleted file mode 100644
index 6f46c7a..0000000
--- a/Documentation/cdrom/optcd
+++ /dev/null
@@ -1,57 +0,0 @@
-This is the README file for the Optics Storage 8000 AT CDROM device driver.
-
-This is the driver for the so-called 'DOLPHIN' drive, with the 34-pin
-Sony-compatible interface. For the IDE-compatible Optics Storage 8001
-drive, you will want the ATAPI CDROM driver. The driver also seems to
-work with the Lasermate CR328A. If you have a drive that works with
-this driver, and that doesn't report itself as DOLPHIN, please drop me
-a mail.
-
-The support for multisession CDs is in ALPHA stage. If you use it,
-please mail me your experiences. Multisession support can be disabled
-at compile time.
-
-You can find some older versions of the driver at
-      dutette.et.tudelft.nl:/pub/linux/
-and at Eberhard's mirror
-      ftp.gwdg.de:/pub/linux/cdrom/drivers/optics/
-
-Before you can use the driver, you have to create the device file once:
- # mknod /dev/optcd0 b 17 0
-
-To specify the base address if the driver is "compiled-in" to your kernel,
-you can use the kernel command line item (LILO option)
-             optcd=0x340
-with the right address.
-
-If you have compiled optcd as a module, you can load it with
- # insmod /usr/src/linux/modules/optcd.o
-or
- # insmod /usr/src/linux/modules/optcd.o optcd=0x340
-with the matching address value of your interface card.
-
-The driver employs a number of buffers to do read-ahead and block size
-conversion. The number of buffers is configurable in optcd.h, and has
-influence on the driver performance. For my machine (a P75), 6 buffers
-seems optimal, as can be seen from this table:
-
-#bufs	kb/s	%cpu
-1	97	0.1
-2	191	0.3
-3	188	0.2
-4	246	0.3
-5	189	19
-6	280	0.4
-7	281	7.0
-8	246	2.8
-16	281	3.4
-
-If you get a throughput significantly below 300 kb/s, try tweaking
-N_BUFS, and don't forget to mail me your results!
-
-I'd appreciate success/failure reports. If you find a bug, try
-recompiling the driver with some strategically chosen debug options
-(these can be found in optcd.h) and include the messages generated in
-your bug report. Good luck.
-
-Leo Spiekman (spiekman@dutette.et.tudelft.nl)
diff --git a/Documentation/cdrom/sbpcd b/Documentation/cdrom/sbpcd
deleted file mode 100644
index b3ba63f..0000000
--- a/Documentation/cdrom/sbpcd
+++ /dev/null
@@ -1,1061 +0,0 @@
-This README belongs to release 4.2 or newer of the SoundBlaster Pro
-(Matsushita, Kotobuki, Panasonic, CreativeLabs, Longshine and Teac)
-CD-ROM driver for Linux.
-
-sbpcd really, really is NOT for ANY IDE/ATAPI drive!
-Not even if you have an "original" SoundBlaster card with an IDE interface!
-So, you'd better have a look into README.ide if your port address is 0x1F0,
-0x170, 0x1E8, 0x168 or similar.
-I get tons of mails from IDE/ATAPI drive users - I really can't continue
-any more to answer them all. So, if your drive/interface information sheets
-mention "IDE" (primary, secondary, tertiary, quaternary) and the DOS driver
-invoking line within your CONFIG.SYS is using an address below 0x230:
-DON'T ROB MY LAST NERVE - jumper your interface to address 0x170 and IRQ 15
-(that is the "secondary IDE" configuration), set your drive to "master" and
-use ide-cd as your driver. If you do not have a second IDE hard disk, use the
-LILO commands
-   hdb=noprobe hdc=cdrom
-and get lucky.
-To make it fully clear to you: if you mail me about IDE/ATAPI drive problems,
-my answer is above, and I simply will discard your mail, hoping to stop the
-flood and to find time to lead my 12-year old son towards happy computing.
-
-The driver is able to drive the whole family of "traditional" AT-style (that
-is NOT the new "Enhanced IDE" or "ATAPI" drive standard) Matsushita,
-Kotobuki, Panasonic drives, sometimes labelled as "CreativeLabs". The
-well-known drives are CR-521, CR-522, CR-523, CR-562, CR-563.
-CR-574 is an IDE/ATAPI drive.
-
-The Longshine LCS-7260 is a double-speed drive which uses the "old"
-Matsushita command set. It is supported - with help by Serge Robyns.
-Vertos ("Elitegroup Computer Systems", ECS) has a similar drive - support
-has started; get in contact if you have such a "Vertos 100" or "ECS-AT"
-drive.
-
-There exists an "IBM External ISA CD-ROM Drive" which in fact is a CR-563
-with a special controller board. This drive is supported (the interface is
-of the "LaserMate" type), and it is possibly the best buy today (cheaper than
-an internal drive, and you can use it as an internal, too - e.g. plug it into
-a soundcard).
-
-CreativeLabs has a new drive "CD200" and a similar drive "CD200F". The latter
-is made by Funai and sometimes named "E2550UA", newer models may be named
-"MK4015". The CD200F drives should fully work.
-CD200 drives without "F" are still giving problems: drive detection and
-playing audio should work, data access will result in errors. I need qualified
-feedback about the bugs within the data functions or a drive (I never saw a
-CD200).
-
-The quad-speed Teac CD-55A drive is supported, but still does not reach "full
-speed". The data rate already reaches 500 kB/sec if you set SBP_BUFFER_FRAMES
-to 64 (it is not recommended to do that for normal "file access" usage, but it
-can speed up things a lot if you use something like "dd" to read from the
-drive; I use it for verifying self-written CDs this way).
-The drive itself is able to deliver 600 kB/sec, so this needs
-work; with the normal setup, the performance currently is not even as good as
-double-speed.
-
-This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives,
-and again: this driver is in no way usable for any IDE/ATAPI drive. If you 
-think your drive should work and it doesn't: send me the DOS driver for your
-beast (gzipped + uuencoded) and your CONFIG.SYS if you want to ask me for help,
-and include an original log message excerpt, and try to give all information
-a complete idiot needs to understand your hassle already with your first
-mail. And if you want to say "as I have mailed you before", be sure that I
-don't remember your "case" by such remarks; at the moment, I have some 
-hundreds of open correspondences about Linux CDROM questions (hope to reduce if
-the IDE/ATAPI user questions disappear). 
-
-
-This driver will work with the soundcard interfaces (SB Pro, SB 16, Galaxy,
-SoundFX, Mozart, MAD16 ...) and with the "no-sound" cards (Panasonic CI-101P,
-LaserMate, WDH-7001C, Longshine LCS-6853, Teac ...).
-
-It works with the "configurable" interface "Sequoia S-1000", too, which is 
-used on the Spea Media FX and Ensonic Soundscape sound cards. You have to
-specify the type "SBPRO 2" and the true CDROM port address with it, not the
-"configuration port" address.
-
-If you have a sound card which needs a "configuration driver" instead of
-jumpers for interface types and addresses (like Mozart cards) - those
-drivers get invoked before the DOS CDROM driver in your CONFIG.SYS, typical
-names are "cdsetup.sys" and "mztinit.sys" - let the sound driver do the
-CDROM port configuration (the leading comments in linux/drivers/sound/mad16.c
-are just for you!). Hannu Savolainen's mad16.c code is able to set up my
-Mozart card - I simply had to add
-   #define MAD16_CONF 0x06
-   #define MAD16_CDSEL 0x03
-to configure the CDROM interface for type "Panasonic" (LaserMate) and address
-0x340.
-
-The interface type has to get configured in linux/drivers/cdrom/sbpcd.h, 
-because the register layout is different between the "SoundBlaster" and the
-"LaserMate" type.
-
-I got a report that the Teac interface card "I/F E117098" is of type
-"SoundBlaster" (i.e. you have to set SBPRO to 1) even with the addresses
-0x300 and above. This is unusual, and it can't get covered by the auto
-probing scheme.
-The Teac 16-bit interface cards (like P/N E950228-00A, default address 0x2C0)
-need the SBPRO 3 setup.
-
-If auto-probing found the drive, the address is correct. The reported type
-may be wrong. A "mount" will give success only if the interface type is set
-right. Playing audio should work with a wrong set interface type, too.
-
-With some Teac and some CD200 drives I have seen interface cards which seem
-to lack the "drive select" lines; always drive 0 gets addressed. To avoid
-"mirror drives" (four drives detected where you only have one) with such
-interface cards, set MAX_DRIVES to 1 and jumper your drive to ID 0 (if
-possible).
-
-
-Up to 4 drives per interface card, and up to 4 interface cards are supported.
-All supported drive families can be mixed, but the CR-521 drives are 
-hard-wired to drive ID 0. The drives have to use different drive IDs, and each
-drive has to get a unique minor number (0...3), corresponding indirectly to 
-its drive ID.
-The drive IDs may be selected freely from 0 to 3 - they do not have to be in
-consecutive order.
-
-As Don Carroll, don@ds9.us.dell.com or FIDO 1:382/14, told me, it is possible
-to change old drives to any ID, too. He writes in this sense:
-   "In order to be able to use more than one single speed drive
-   (they do not have the ID jumpers) you must add a DIP switch
-   and two resistors. The pads are already on the board next to
-   the power connector. You will see the silkscreen for the
-   switch if you remove the top cover.
-                    1 2 3 4
-             ID 0 = x F F x             O = "on"
-             ID 1 = x O F x             F = "off"
-             ID 2 = x F O x             x = "don't care"
-             ID 3 = x O O x
-   Next to the switch are the positions for R76 (7k) and R78
-   (12k). I had to play around with the resistor values - ID 3
-   did not work with other values. If the values are not good,
-   ID 3 behaves like ID 0."
-
-To use more than 4 drives, you simply need a second controller card at a 
-different address and a second cable.
-
-The driver supports reading of data from the CD and playing of audio tracks.
-The audio part should run with WorkMan, xcdplayer, with the "non-X11" products
-CDplayer and WorkBone - tell me if it is not compatible with other software.
-The only accepted measure for correctness with the audio functions is the
-"cdtester" utility (appended) - most audio player programmers seem to be
-better musicians than programmers. ;-)
-
-With the CR-56x and the CD200 drives, the reading of audio frames is possible.
-This is implemented by an IOCTL function which reads READ_AUDIO frames of
-2352 bytes at once (configurable with the "READ_AUDIO" define, default is 0).
-Reading the same frame a second time gives different data; the frame data 
-start at a different position, but all read bytes are valid, and we always
-read 98 consecutive chunks (of 24 Bytes) as a frame. Reading more than 1 frame
-at once possibly misses some chunks at each frame boundary. This lack has to
-get corrected by external, "higher level" software which reads the same frame 
-again and tries to find and eliminate overlapping chunks (24-byte-pieces).
-
-The transfer rate with reading audio (1-frame-pieces) currently is very slow.
-This can be better reading bigger chunks, but the "missing" chunks possibly
-occur at the beginning of each single frame.
-The software interface possibly may change a bit the day the SCSI driver
-supports it too.
-
-With all but the CR-52x drives, MultiSession is supported.
-Photo CDs work (the "old" drives like CR-521 can access only the first
-session of a photoCD).
-At ftp.gwdg.de:/pub/linux/hpcdtoppm/ you will find Hadmut Danisch's package to
-convert photo CD image files and Gerd Knorr's viewing utility.
-
-The transfer rate will reach 150 kB/sec with CR-52x drives, 300 kB/sec with
-CR-56x drives, and currently not more than 500 kB/sec (usually less than
-250 kB/sec) with the Teac quad speed drives.
-XA (PhotoCD) disks with "old" drives give only 50 kB/sec.
-
-This release consists of
-- this README file
-- the driver file linux/drivers/cdrom/sbpcd.c
-- the stub files linux/drivers/cdrom/sbpcd[234].c
-- the header file linux/drivers/cdrom/sbpcd.h.
-
-
-To install:
------------
-
-1. Setup your hardware parameters. Though the driver does "auto-probing" at a
-   lot of (not all possible!) addresses, this step is recommended for
-   everyday use. You should let sbpcd auto-probe once and use the reported
-   address if a drive got found. The reported type may be incorrect; it is
-   correct if you can mount a data CD. There is no choice for you with the
-   type; only one is right, the others are deadly wrong.
-
-   a. Go into /usr/src/linux/drivers/cdrom/sbpcd.h and configure it for your
-      hardware (near the beginning):
-      a1. Set it up for the appropriate type of interface board.
-          "Original" CreativeLabs sound cards need "SBPRO 1".
-          Most "compatible" sound cards (almost all "non-CreativeLabs" cards)
-          need "SBPRO 0".
-          The "no-sound" board from OmniCd needs the "SBPRO 1" setup.
-          The Teac 8-bit "no-sound" boards need the "SBPRO 1" setup.
-          The Teac 16-bit "no-sound" boards need the "SBPRO 3" setup.
-          All other "no-sound" boards need the "SBPRO 0" setup.
-          The Spea Media FX and Ensoniq SoundScape cards need "SBPRO 2".
-          sbpcd.c holds some examples in its auto-probe list.
-          If you configure "SBPRO" wrong, the playing of audio CDs will work,
-          but you will not be able to mount a data CD.
-      a2. Tell the address of your CDROM_PORT (not of the sound port).
-      a3. If 4 drives get found, but you have only one, set MAX_DRIVES to 1.
-      a4. Set DISTRIBUTION to 0.
-   b. Additionally for 2.a1 and 2.a2, the setup may be done during
-      boot time (via the "kernel command line" or "LILO option"):
-          sbpcd=0x320,LaserMate
-      or
-          sbpcd=0x230,SoundBlaster
-      or
-          sbpcd=0x338,SoundScape
-      or
-          sbpcd=0x2C0,Teac16bit
-      This is especially useful if you install a fresh distribution.
-      If the second parameter is a number, it gets taken as the type
-      setting; 0 is "LaserMate", 1 is "SoundBlaster", 2 is "SoundScape",
-      3 is "Teac16bit".
-      So, for example
-          sbpcd=0x230,1
-      is equivalent to
-          sbpcd=0x230,SoundBlaster
-
-2. "cd /usr/src/linux" and do a "make config" and select "y" for Matsushita
-   CD-ROM support and for ISO9660 FileSystem support. If you do not have a
-   second, third, or fourth controller installed, do not say "y" to the 
-   secondary Matsushita CD-ROM questions.
-
-3. Then make the kernel image ("make zlilo" or similar).
-
-4. Make the device file(s). This step usually already has been done by the
-   MAKEDEV script.
-   The driver uses MAJOR 25, so, if necessary, do
-        mknod /dev/sbpcd  b 25 0       (if you have only one drive)
-   and/or
-        mknod /dev/sbpcd0 b 25 0
-        mknod /dev/sbpcd1 b 25 1
-        mknod /dev/sbpcd2 b 25 2
-        mknod /dev/sbpcd3 b 25 3
-   to make the node(s).
-
-   The "first found" drive gets MINOR 0 (regardless of its jumpered ID), the
-   "next found" (at the same cable) gets MINOR 1, ...
-   
-   For a second interface board, you have to make nodes like
-        mknod /dev/sbpcd4 b 26 0
-        mknod /dev/sbpcd5 b 26 1
-   and so on. Use the MAJORs 26, 27, 28.
-
-   If you further make a link like
-        ln -s sbpcd /dev/cdrom
-   you can use the name /dev/cdrom, too.
-
-5. Reboot with the new kernel.
-
-You should now be able to do
-              mkdir /CD
-and 
-              mount -rt iso9660 /dev/sbpcd /CD
-or
-              mount -rt iso9660 -o block=2048 /dev/sbpcd /CD
-and see the contents of your CD in the /CD directory.
-To use audio CDs, a mounting is not recommended (and it would fail if the
-first track is not a data track).
-
-
-Using sbpcd as a "loadable module":
------------------------------------
-
-If you do NOT select "Matsushita/Panasonic CDROM driver support" during the
-"make config" of your kernel, you can build the "loadable module" sbpcd.o.
-
-If sbpcd gets used as a module, the support of more than one interface
-card (i.e. drives 4...15) is disabled.
-
-You can specify interface address and type with the "insmod" command like:
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x340,0
-or
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x230,1
-or
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x338,2
-where the last number represents the SBPRO setting (no strings allowed here).
-
-
-Things of interest:
--------------------
-
-The driver is configured to try the LaserMate type of interface at I/O port
-0x0340 first. If this is not appropriate, sbpcd.h should get changed
-(you will find the right place - just at the beginning).
-
-No DMA and no IRQ is used.
-
-To reduce or increase the amount of kernel messages, edit sbpcd.c and play
-with the "DBG_xxx" switches (initialization of the variable "sbpcd_debug").
-Don't forget to reflect on what you do; enabling all DBG_xxx switches at once
-may crash your system, and each message line is accompanied by a delay.
-
-The driver uses the "variable BLOCK_SIZE" feature. To use it, you have to
-specify "block=2048" as a mount option. Doing this will disable the direct
-execution of a binary from the CD; you have to copy it to a device with the
-standard BLOCK_SIZE (1024) first. So, do not use this if your system is
-directly "running from the CDROM" (like some of Yggdrasil's installation
-variants). There are CDs on the market (like the German "unifix" Linux
-distribution) which MUST get handled with a block_size of 1024. Generally,
-one can say all the CDs which hold files of the name YMTRANS.TBL are defective;
-do not use block=2048 with those.
-
-Within sbpcd.h, you will find some "#define"s (e.g. EJECT and JUKEBOX). With
-these, you can configure the driver for some special things.
-You can use the appended program "cdtester" to set the auto-eject feature
-during runtime. Jeff Tranter's "eject" utility can do this, too (and more)
-for you.
-
-There is an ioctl CDROMMULTISESSION to obtain with a user program if
-the CD is an XA disk and - if it is - where the last session starts. The
-"cdtester" program illustrates how to call it.
-
-
-Auto-probing at boot time:
---------------------------
-
-The driver does auto-probing at many well-known interface card addresses,
-but not all:
-Some probings can cause a hang if an NE2000 ethernet card gets touched, because
-SBPCD's auto-probing happens before the initialization of the net drivers.
-Those "hazardous" addresses are excluded from auto-probing; the "kernel 
-command line" feature has to be used during installation if you have your 
-drive at those addresses. The "module" version is allowed to probe at those
-addresses, too.
-
-The auto-probing looks first at the configured address resp. the address
-submitted by the kernel command line. With this, it is possible to use this
-driver within installation boot floppies, and for any non-standard address,
-too.
-
-Auto-probing will make an assumption about the interface type ("SBPRO" or not),
-based upon the address. That assumption may be wrong (initialization will be
-o.k., but you will get I/O errors during mount). In that case, use the "kernel
-command line" feature and specify address & type at boot time to find out the
-right setup.
-
-For everyday use, address and type should get configured within sbpcd.h. That
-will stop the auto-probing due to success with the first try.
-
-The kernel command "sbpcd=0" suppresses each auto-probing and causes
-the driver not to find any drive; it is meant for people who love sbpcd
-so much that they do not want to miss it, even if they miss the drives. ;-)  
-
-If you configure "#define CDROM_PORT 0" in sbpcd.h, the auto-probing is
-initially disabled and needs an explicit kernel command to get activated.
-Once activated, it does not stop before success or end-of-list. This may be
-useful within "universal" CDROM installation boot floppies (but using the 
-loadable module would be better because it allows an "extended" auto-probing
-without fearing NE2000 cards).
-
-To shorten the auto-probing list to a single entry, set DISTRIBUTION 0 within
-sbpcd.h.
-
-
-Setting up address and interface type:
---------------------------------------
-
-If your I/O port address is not 0x340, you have to look for the #defines near
-the beginning of sbpcd.h and configure them: set SBPRO to 0 or 1 or 2, and
-change CDROM_PORT to the address of your CDROM I/O port.
-
-Almost all of the "SoundBlaster compatible" cards behave like the no-sound
-interfaces, i.e. need SBPRO 0! 
-
-With "original" SB Pro cards, an initial setting of CD_volume through the
-sound card's MIXER register gets done.
-If you are using a "compatible" sound card of types "LaserMate" or "SPEA",
-you can set SOUND_BASE (in sbpcd.h) to get it done with your card, too...
-
-
-Using audio CDs:
-----------------
-
-Workman, WorkBone, xcdplayer, cdplayer and the nice little tool "cdplay" (see
-README.aztcd from the Aztech driver package) should work.
-
-The program CDplayer likes to talk to "/dev/mcd" only, xcdplayer wants
-"/dev/rsr0", workman loves "/dev/sr0" or "/dev/cdrom" - so, make the 
-appropriate links to use them without the need to supply parameters.
-
-
-Copying audio tracks:
----------------------
-
-The following program will copy track 1 (or a piece of it) from an audio CD
-into the file "track01":
-
-/*=================== begin program ========================================*/
-/*
- * read an audio track from a CD
- *
- * (c) 1994 Eberhard Moenkeberg <emoenke@gwdg.de>
- *          may be used & enhanced freely
- *
- * Due to non-existent sync bytes at the beginning of each audio frame (or due
- * to a firmware bug within all known drives?), it is currently a kind of
- * fortune if two consecutive frames fit together.
- * Usually, they overlap, or a little piece is missing. This happens in units
- * of 24-byte chunks. It has to get fixed by higher-level software (reading
- * until an overlap occurs, and then eliminate the overlapping chunks). 
- * ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz holds an example of
- * such an algorithm.
- * This example program further is missing to obtain the SubChannel data
- * which belong to each frame.
- *
- * This is only an example of the low-level access routine. The read data are
- * pure 16-bit CDDA values; they have to get converted to make sound out of
- * them.
- * It is no fun to listen to it without prior overlap/underlap correction!
- */
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <linux/cdrom.h>
-
-static struct cdrom_tochdr hdr;
-static struct cdrom_tocentry entry[101];
-static struct cdrom_read_audio arg;
-static u_char buffer[CD_FRAMESIZE_RAW];
-static int datafile, drive;
-static int i, j, limit, track, err;
-static char filename[32];
-
-int main(int argc, char *argv[])
-{
-/*
- * open /dev/cdrom
- */
-  drive=open("/dev/cdrom", 0);
-  if (drive<0)
-    {
-      fprintf(stderr, "can't open drive.\n");
-      exit (-1);
-    }
-/*
- * get TocHeader
- */
-  fprintf(stdout, "getting TocHeader...\n");
-  err=ioctl(drive, CDROMREADTOCHDR, &hdr);
-  if (err!=0)
-    {
-      fprintf(stderr, "can't get TocHeader (error %d).\n", err);
-      exit (-1);
-    }
-  else
-    fprintf(stdout, "TocHeader: %d %d\n", hdr.cdth_trk0, hdr.cdth_trk1);
-/*
- * get and display all TocEntries
- */
-  fprintf(stdout, "getting TocEntries...\n");
-  for (i=1;i<=hdr.cdth_trk1+1;i++)
-    {
-      if (i!=hdr.cdth_trk1+1) entry[i].cdte_track = i;
-      else entry[i].cdte_track = CDROM_LEADOUT;
-      entry[i].cdte_format = CDROM_LBA;
-      err=ioctl(drive, CDROMREADTOCENTRY, &entry[i]);
-      if (err!=0)
-	{
-	  fprintf(stderr, "can't get TocEntry #%d (error %d).\n", i, err);
-	  exit (-1);
-	}
-      else
-	{
-	  fprintf(stdout, "TocEntry #%d: %1X %1X %06X %02X\n",
-		 entry[i].cdte_track,
-		 entry[i].cdte_adr,
-		 entry[i].cdte_ctrl,
-		 entry[i].cdte_addr.lba,
-		 entry[i].cdte_datamode);
-	}
-    }
-  fprintf(stdout, "got all TocEntries.\n");
-/*
- * ask for track number (not implemented here)
- */
-track=1;
-#if 0 /* just read a little piece (4 seconds) */
-entry[track+1].cdte_addr.lba=entry[track].cdte_addr.lba+300;
-#endif
-/*
- * read track into file
- */
-  sprintf(filename, "track%02d\0", track);
-  datafile=creat(filename, 0755);
-  if (datafile<0)
-    {
-      fprintf(stderr, "can't open datafile %s.\n", filename);
-      exit (-1);
-    }
-  arg.addr.lba=entry[track].cdte_addr.lba;
-  arg.addr_format=CDROM_LBA; /* CDROM_MSF would be possible here, too. */
-  arg.nframes=1;
-  arg.buf=&buffer[0];
-  limit=entry[track+1].cdte_addr.lba;
-  for (;arg.addr.lba<limit;arg.addr.lba++)
-    {
-      err=ioctl(drive, CDROMREADAUDIO, &arg);
-      if (err!=0)
-	{
-	  fprintf(stderr, "can't read abs. frame #%d (error %d).\n", 
-		 arg.addr.lba, err);
-	}
-      j=write(datafile, &buffer[0], CD_FRAMESIZE_RAW);
-      if (j!=CD_FRAMESIZE_RAW)
-	{
-	  fprintf(stderr,"I/O error (datafile) at rel. frame %d\n",
-			 arg.addr.lba-entry[track].cdte_addr.lba);
-	}
-      arg.addr.lba++;
-    }
-    return 0;
-}
-/*===================== end program ========================================*/
-
-At ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz is an adapted version of
-Heiko Eissfeldt's digital-audio to .WAV converter (the original is there, too).
-This is preliminary, as Heiko himself will care about it.
-
-
-Known problems:
----------------
-
-Currently, the detection of disk change or removal is actively disabled.
-
-Most attempts to read the UPC/EAN code result in a stream of zeroes. All my
-drives are mostly telling there is no UPC/EAN code on disk or there is, but it
-is an all-zero number. I guess now almost no CD holds such a number.
-
-Bug reports, comments, wishes, donations (technical information is a donation,
-too :-) etc. to emoenke@gwdg.de.
-
-SnailMail address, preferable for CD editors if they want to submit a free
-"cooperation" copy:
-                         Eberhard Moenkeberg
-                         Reinholdstr. 14
-                         D-37083 Goettingen
-                         Germany
----
-
-
-Appendix -- the "cdtester" utility:
-
-/*
- * cdtester.c -- test the audio functions of a CD driver
- *
- * (c) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
- *          published under the GPL
- *
- *          made under heavy use of the "Tiny Audio CD Player"
- *          from Werner Zimmermann <zimmerma@rz.fht-esslingen.de>
- *          (see linux/drivers/block/README.aztcd)
- */
-#undef AZT_PRIVATE_IOCTLS /* not supported by every CDROM driver */
-#define SBP_PRIVATE_IOCTLS /* not supported by every CDROM driver */
-
-#include <stdio.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <linux/cdrom.h>
-
-#ifdef AZT_PRIVATE_IOCTLS
-#include <linux/../../drivers/cdrom/aztcd.h>
-#endif /* AZT_PRIVATE_IOCTLS */
-#ifdef SBP_PRIVATE_IOCTLS
-#include <linux/../../drivers/cdrom/sbpcd.h>
-#include <linux/fs.h>
-#endif /* SBP_PRIVATE_IOCTLS */
-
-struct cdrom_tochdr hdr;
-struct cdrom_tochdr tocHdr;
-struct cdrom_tocentry TocEntry[101];
-struct cdrom_tocentry entry;
-struct cdrom_multisession ms_info;
-struct cdrom_read_audio read_audio;
-struct cdrom_ti ti;
-struct cdrom_subchnl subchnl;
-struct cdrom_msf msf;
-struct cdrom_volctrl volctrl;
-#ifdef AZT_PRIVATE_IOCTLS
-union
-{
-	struct cdrom_msf msf;
-	unsigned char buf[CD_FRAMESIZE_RAW];
-} azt;
-#endif /* AZT_PRIVATE_IOCTLS */
-int i, i1, i2, i3, j, k;
-unsigned char sequence=0;
-unsigned char command[80];
-unsigned char first=1, last=1;
-char *default_device="/dev/cdrom";
-char dev[20];
-char filename[20];
-int drive;
-int datafile;
-int rc;
-
-void help(void)
-{
-	printf("Available Commands:\n");
-	printf("STOP          s      EJECT        e       QUIT         q\n");
-	printf("PLAY TRACK    t      PAUSE        p       RESUME       r\n");
-	printf("NEXT TRACK    n      REPEAT LAST  l       HELP         h\n");
-	printf("SUBCHANNEL_Q  c      TRACK INFO   i       PLAY AT      a\n");
-	printf("READ          d      READ RAW     w       READ AUDIO   A\n");
-	printf("MS-INFO       M      TOC          T       START        S\n");
-	printf("SET EJECTSW   X      DEVICE       D       DEBUG        Y\n");
-	printf("AUDIO_BUFSIZ  Z      RESET        R       SET VOLUME   v\n");
-	printf("GET VOLUME    V\n");
-}
-
-/*
- *  convert MSF number (3 bytes only) to Logical_Block_Address 
- */
-int msf2lba(u_char *msf)
-{
-	int i;
-	
-	i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET;
-	if (i<0) return (0);
-	return (i);
-}
-/*
- *  convert logical_block_address to m-s-f_number (3 bytes only)
- */
-void lba2msf(int lba, unsigned char *msf)
-{
-	lba += CD_BLOCK_OFFSET;
-	msf[0] = lba / (CD_SECS*CD_FRAMES);
-	lba %= CD_SECS*CD_FRAMES;
-	msf[1] = lba / CD_FRAMES;
-	msf[2] = lba % CD_FRAMES;
-}
-
-int init_drive(char *dev)
-{
-	unsigned char msf_ent[3];
-
-	/*
-	 * open the device
-	 */
-	drive=open(dev,0);
-	if (drive<0) return (-1);
-	/*
-	 * get TocHeader
-	 */
-	printf("getting TocHeader...\n");
-	rc=ioctl(drive,CDROMREADTOCHDR,&hdr);
-	if (rc!=0)
-	{
-		printf("can't get TocHeader (error %d).\n",rc);
-		return (-2);
-	}
-	else
-		first=hdr.cdth_trk0;
-		last=hdr.cdth_trk1;
-		printf("TocHeader: %d %d\n",hdr.cdth_trk0,hdr.cdth_trk1);
-	/*
-	 * get and display all TocEntries
-	 */
-	printf("getting TocEntries...\n");
-	for (i=1;i<=hdr.cdth_trk1+1;i++)
-	{
-		if (i!=hdr.cdth_trk1+1) TocEntry[i].cdte_track = i;
-		else TocEntry[i].cdte_track = CDROM_LEADOUT;
-		TocEntry[i].cdte_format = CDROM_LBA;
-		rc=ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]);
-		if (rc!=0)
-		{
-			printf("can't get TocEntry #%d (error %d).\n",i,rc);
-		}
-		else
-		{
-			lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]);
-			if (TocEntry[i].cdte_track==CDROM_LEADOUT)
-			{
-				printf("TocEntry #%02X: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n",
-				       TocEntry[i].cdte_track,
-				       TocEntry[i].cdte_adr,
-				       TocEntry[i].cdte_ctrl,
-				       msf_ent[0],
-				       msf_ent[1],
-				       msf_ent[2],
-				       TocEntry[i].cdte_addr.lba,
-				       TocEntry[i].cdte_datamode);
-			}
-			else
-			{
-				printf("TocEntry #%02d: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n",
-				       TocEntry[i].cdte_track,
-				       TocEntry[i].cdte_adr,
-				       TocEntry[i].cdte_ctrl,
-				       msf_ent[0],
-				       msf_ent[1],
-				       msf_ent[2],
-				       TocEntry[i].cdte_addr.lba,
-				       TocEntry[i].cdte_datamode);
-			}
-		}
-	}
-	return (hdr.cdth_trk1); /* number of tracks */
-}
-
-void display(int size,unsigned char *buffer)
-{
-	k=0;
-	getchar();
-	for (i=0;i<(size+1)/16;i++)
-	{
-		printf("%4d:",i*16);
-		for (j=0;j<16;j++)
-		{
-			printf(" %02X",buffer[i*16+j]);
-		}
-		printf("  ");
-		for (j=0;j<16;j++)
-		{
-			if (isalnum(buffer[i*16+j])) 
-				printf("%c",buffer[i*16+j]);
-			else
-				printf(".");
-		}
-		printf("\n"); 
-		k++;
-		if (k>=20)
-		{
-			printf("press ENTER to continue\n");
-			getchar();
-			k=0;
-		}
-	} 
-} 
-
-int main(int argc, char *argv[])
-{
-	printf("\nTesting tool for a CDROM driver's audio functions V0.1\n");
-	printf("(C) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>\n");
-	printf("initializing...\n");
-	
-	rc=init_drive(default_device);
-	if (rc<0) printf("could not open %s (rc=%d).\n",default_device,rc);
-	help();
-	while (1)
-	{
-		printf("Give a one-letter command (h = help): ");
-		scanf("%s",command);
-		command[1]=0;
-		switch (command[0])
-		{
-		case 'D':
-			printf("device name (f.e. /dev/sbpcd3): ? ");
-			scanf("%s",&dev);
-			close(drive);
-			rc=init_drive(dev);
-			if (rc<0) printf("could not open %s (rc %d).\n",dev,rc);
-			break;
-		case 'e':
-			rc=ioctl(drive,CDROMEJECT);
-			if (rc<0) printf("CDROMEJECT: rc=%d.\n",rc);
-			break;
-		case 'p':
-			rc=ioctl(drive,CDROMPAUSE);
-			if (rc<0) printf("CDROMPAUSE: rc=%d.\n",rc);
-			break;
-		case 'r':
-			rc=ioctl(drive,CDROMRESUME);
-			if (rc<0) printf("CDROMRESUME: rc=%d.\n",rc);
-			break;
-		case 's':
-			rc=ioctl(drive,CDROMSTOP);
-			if (rc<0) printf("CDROMSTOP: rc=%d.\n",rc);
-			break;
-		case 'S':
-			rc=ioctl(drive,CDROMSTART);
-			if (rc<0) printf("CDROMSTART: rc=%d.\n",rc);
-			break;
-		case 't':
-			rc=ioctl(drive,CDROMREADTOCHDR,&tocHdr);
-			if (rc<0)
-			{
-				printf("CDROMREADTOCHDR: rc=%d.\n",rc);
-				break;
-			}
-			first=tocHdr.cdth_trk0;
-			last= tocHdr.cdth_trk1;
-			if ((first==0)||(first>last))
-			{
-				printf ("--got invalid TOC data.\n");
-			}
-			else
-			{
-				printf("--enter track number(first=%d, last=%d): ",first,last);
-				scanf("%d",&i1);
-				ti.cdti_trk0=i1;
-				if (ti.cdti_trk0<first) ti.cdti_trk0=first;
-				if (ti.cdti_trk0>last) ti.cdti_trk0=last;
-				ti.cdti_ind0=0;
-				ti.cdti_trk1=last;
-				ti.cdti_ind1=0;
-				rc=ioctl(drive,CDROMSTOP);
-				rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
-				if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
-			}
-			break;
-		case 'n':
-			rc=ioctl(drive,CDROMSTOP);
-			if (++ti.cdti_trk0>last) ti.cdti_trk0=last;
-			ti.cdti_ind0=0;
-			ti.cdti_trk1=last;
-			ti.cdti_ind1=0;
-			rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
-			if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
-			break;
-		case 'l':
-			rc=ioctl(drive,CDROMSTOP);
-			if (--ti.cdti_trk0<first) ti.cdti_trk0=first;
-			ti.cdti_ind0=0;
-			ti.cdti_trk1=last;
-			ti.cdti_ind1=0;
-			rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
-			if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
-			break;
-		case 'c':
-			subchnl.cdsc_format=CDROM_MSF;
-			rc=ioctl(drive,CDROMSUBCHNL,&subchnl);
-			if (rc<0) printf("CDROMSUBCHNL: rc=%d.\n",rc);
-			else
-			{
-				printf("AudioStatus:%s  Track:%d  Mode:%d  MSF=%02d:%02d:%02d\n",
-				       subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY ? "PLAYING":"NOT PLAYING",
-				       subchnl.cdsc_trk,subchnl.cdsc_adr, 
-				       subchnl.cdsc_absaddr.msf.minute,
-				       subchnl.cdsc_absaddr.msf.second,
-				       subchnl.cdsc_absaddr.msf.frame);
-			}
-			break;              
-		case 'i':
-			printf("Track No.: ");
-			scanf("%d",&i1);
-			entry.cdte_track=i1;
-			if (entry.cdte_track<first) entry.cdte_track=first;
-			if (entry.cdte_track>last)  entry.cdte_track=last;
-			entry.cdte_format=CDROM_MSF;
-			rc=ioctl(drive,CDROMREADTOCENTRY,&entry);
-			if (rc<0) printf("CDROMREADTOCENTRY: rc=%d.\n",rc);
-			else
-			{
-				printf("Mode %d Track, starts at %02d:%02d:%02d\n",
-				       entry.cdte_adr,
-				       entry.cdte_addr.msf.minute,
-				       entry.cdte_addr.msf.second,
-				       entry.cdte_addr.msf.frame);
-			}
-			break;
-		case 'a':
-			printf("Address (min:sec:frm)  ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			msf.cdmsf_min0=i1;
-			msf.cdmsf_sec0=i2;
-			msf.cdmsf_frame0=i3;
-			if (msf.cdmsf_sec0>59) msf.cdmsf_sec0=59;
-			if (msf.cdmsf_frame0>74) msf.cdmsf_frame0=74;
-			lba2msf(TocEntry[last+1].cdte_addr.lba-1,&msf.cdmsf_min1);
-			rc=ioctl(drive,CDROMSTOP);
-			rc=ioctl(drive,CDROMPLAYMSF,&msf);
-			if (rc<0) printf("CDROMPLAYMSF: rc=%d.\n",rc);
-			break;
-		case 'V':
-			rc=ioctl(drive,CDROMVOLREAD,&volctrl);
-			if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc);
-			printf("Volume: channel 0 (left) %d, channel 1 (right) %d\n",volctrl.channel0,volctrl.channel1);
-			break;  
-		case 'R':
-			rc=ioctl(drive,CDROMRESET);
-			if (rc<0) printf("CDROMRESET: rc=%d.\n",rc);
-			break;
-#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
-		case 'd':
-			printf("Address (min:sec:frm)  ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			azt.msf.cdmsf_min0=i1;
-			azt.msf.cdmsf_sec0=i2;
-			azt.msf.cdmsf_frame0=i3;
-			if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59;
-			if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74;
-			rc=ioctl(drive,CDROMREADMODE1,&azt.msf);
-			if (rc<0) printf("CDROMREADMODE1: rc=%d.\n",rc);
-			else display(CD_FRAMESIZE,azt.buf);
-			break;
-		case 'w':
-			printf("Address (min:sec:frame)  ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			azt.msf.cdmsf_min0=i1;
-			azt.msf.cdmsf_sec0=i2;
-			azt.msf.cdmsf_frame0=i3;
-			if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59;
-			if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74;
-			rc=ioctl(drive,CDROMREADMODE2,&azt.msf);
-			if (rc<0) printf("CDROMREADMODE2: rc=%d.\n",rc);
-			else display(CD_FRAMESIZE_RAW,azt.buf); /* currently only 2336 */
-			break;  
-#endif
-		case 'v':
-			printf("--Channel 0 (Left)  (0-255): ");
-			scanf("%d",&i1);
-			volctrl.channel0=i1;
-			printf("--Channel 1 (Right) (0-255): ");
-			scanf("%d",&i1);
-			volctrl.channel1=i1;
-			volctrl.channel2=0;
-			volctrl.channel3=0;
-			rc=ioctl(drive,CDROMVOLCTRL,&volctrl);
-			if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc);
-			break;  
-		case 'q':
-			close(drive);
-			exit(0);
-		case 'h':
-			help();
-			break;
-		case 'T': /* display TOC entry - without involving the driver */
-			scanf("%d",&i);
-			if ((i<hdr.cdth_trk0)||(i>hdr.cdth_trk1))
-				printf("invalid track number.\n");
-			else
-				printf("TocEntry %02d: adr=%01X ctrl=%01X msf=%02d:%02d:%02d mode=%02X\n",
-				       TocEntry[i].cdte_track,
-				       TocEntry[i].cdte_adr,
-				       TocEntry[i].cdte_ctrl,
-				       TocEntry[i].cdte_addr.msf.minute,
-				       TocEntry[i].cdte_addr.msf.second,
-				       TocEntry[i].cdte_addr.msf.frame,
-				       TocEntry[i].cdte_datamode);
-			break;
-		case 'A': /* read audio data into file */
-			printf("Address (min:sec:frm) ? ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			read_audio.addr.msf.minute=i1;
-			read_audio.addr.msf.second=i2;
-			read_audio.addr.msf.frame=i3;
-			read_audio.addr_format=CDROM_MSF;
-			printf("# of frames ? ");
-			scanf("%d",&i1);
-			read_audio.nframes=i1;
-			k=read_audio.nframes*CD_FRAMESIZE_RAW;
-			read_audio.buf=malloc(k);
-			if (read_audio.buf==NULL)
-			{
-				printf("can't malloc %d bytes.\n",k);
-				break;
-			}
-			sprintf(filename,"audio_%02d%02d%02d_%02d.%02d\0",
-				read_audio.addr.msf.minute,
-				read_audio.addr.msf.second,
-				read_audio.addr.msf.frame,
-				read_audio.nframes,
-				++sequence);
-			datafile=creat(filename, 0755);
-			if (datafile<0)
-			{
-				printf("can't open datafile %s.\n",filename);
-				break;
-			}
-			rc=ioctl(drive,CDROMREADAUDIO,&read_audio);
-			if (rc!=0)
-			{
-				printf("CDROMREADAUDIO: rc=%d.\n",rc);
-			}
-			else
-			{
-				rc=write(datafile,&read_audio.buf,k);
-				if (rc!=k) printf("datafile I/O error (%d).\n",rc);
-			}
-			close(datafile);
-			break;
-		case 'X': /* set EJECT_SW (0: disable, 1: enable auto-ejecting) */
-			scanf("%d",&i);
-			rc=ioctl(drive,CDROMEJECT_SW,i);
-			if (rc!=0)
-				printf("CDROMEJECT_SW: rc=%d.\n",rc);
-			else
-				printf("EJECT_SW set to %d\n",i);
-			break;
-		case 'M': /* get the multisession redirection info */
-			ms_info.addr_format=CDROM_LBA;
-			rc=ioctl(drive,CDROMMULTISESSION,&ms_info);
-			if (rc!=0)
-			{
-				printf("CDROMMULTISESSION(lba): rc=%d.\n",rc);
-			}
-			else
-			{
-				if (ms_info.xa_flag) printf("MultiSession offset (lba): %d (0x%06X)\n",ms_info.addr.lba,ms_info.addr.lba);
-				else
-				{
-					printf("this CD is not an XA disk.\n");
-					break;
-				}
-			}
-			ms_info.addr_format=CDROM_MSF;
-			rc=ioctl(drive,CDROMMULTISESSION,&ms_info);
-			if (rc!=0)
-			{
-				printf("CDROMMULTISESSION(msf): rc=%d.\n",rc);
-			}
-			else
-			{
-				if (ms_info.xa_flag)
-					printf("MultiSession offset (msf): %02d:%02d:%02d (0x%02X%02X%02X)\n",
-					       ms_info.addr.msf.minute,
-					       ms_info.addr.msf.second,
-					       ms_info.addr.msf.frame,
-					       ms_info.addr.msf.minute,
-					       ms_info.addr.msf.second,
-					       ms_info.addr.msf.frame);
-				else printf("this CD is not an XA disk.\n");
-			}
-			break;
-#ifdef SBP_PRIVATE_IOCTLS
-		case 'Y': /* set the driver's message level */
-#if 0 /* not implemented yet */
-			printf("enter switch name (f.e. DBG_CMD): ");
-			scanf("%s",&dbg_switch);
-			j=get_dbg_num(dbg_switch);
-#else
-			printf("enter DDIOCSDBG switch number: ");
-			scanf("%d",&j);
-#endif
-			printf("enter 0 for \"off\", 1 for \"on\": ");
-			scanf("%d",&i);
-			if (i==0) j|=0x80;
-			printf("calling \"ioctl(drive,DDIOCSDBG,%d)\"\n",j);
-			rc=ioctl(drive,DDIOCSDBG,j);
-			printf("DDIOCSDBG: rc=%d.\n",rc);
-			break;
-		case 'Z': /* set the audio buffer size */
-			printf("# frames wanted: ? ");
-			scanf("%d",&j);
-			rc=ioctl(drive,CDROMAUDIOBUFSIZ,j);
-			printf("%d frames granted.\n",rc);
-			break;
-#endif /* SBP_PRIVATE_IOCTLS */
-		default:
-			printf("unknown command: \"%s\".\n",command);
-			break;
-		}
-	}
-	return 0;
-}
-/*==========================================================================*/
-
diff --git a/Documentation/cdrom/sjcd b/Documentation/cdrom/sjcd
deleted file mode 100644
index 74a1484..0000000
--- a/Documentation/cdrom/sjcd
+++ /dev/null
@@ -1,60 +0,0 @@
- -- Documentation/cdrom/sjcd
-				80% of the work takes 20% of the time,
-				20% of the work takes 80% of the time...
-						(Murphy's law)
-
-				Once started, training can not be stopped...
-						(Star Wars)
-
-This is the README for the sjcd cdrom driver, version 1.6.
-
-This file is meant as a tips & tricks edge for the usage of the SANYO CDR-H94A
-cdrom drive. It will grow as the questions arise. ;-)
-For info on configuring the ISP16 sound card look at Documentation/cdrom/isp16.
-
-The driver should work with any of the Panasonic, Sony or Mitsumi style
-CDROM interfaces.
-The cdrom interface on Media Magic's soft configurable sound card ISP16,
-which used to be included in the driver, is now supported in a separate module.
-This initialisation module will probably also work with other interfaces
-based on an OPTi 82C928 or 82C929 chip (like MAD16 and Mozart): see the
-documentation Documentation/cdrom/isp16.
-
-The device major for sjcd is 18, and minor is 0. Create a block special
-file in your /dev directory (e.g., /dev/sjcd) with these numbers.
-(For those who don't know, being root and doing the following should do
-the trick:
-  mknod -m 644 /dev/sjcd b 18 0
-and mount the cdrom by /dev/sjcd).
-
-The default configuration parameters are:
-  base address 0x340
-  no irq
-  no dma
-(Actually the CDR-H94A doesn't know how to use irq and dma.)
-As of version 1.2, setting base address at boot time is supported
-through the use of command line options: type at the "boot:" prompt:
-  linux sjcd=<base_address>
-(where you would use the kernel labeled "linux" in lilo's configuration
-file /etc/lilo.conf). You could also use 'append="sjcd=<configuration_info>"'
-in the appropriate section of /etc/lilo.conf
-If you're building a kernel yourself you can set your default base
-i/o address with SJCD_BASE_ADDR in /usr/src/linux/drivers/cdrom/sjcd.h.
-
-The sjcd driver supports being loaded as a module. The following
-command will set the base i/o address on the fly (assuming you
-have installed the module in an appropriate place).
-  insmod sjcd.o sjcd_base=<base_address>
-
-
-Have fun!
-
-If something is wrong, please email to		vadim@rbrf.ru
-					or 	vadim@ipsun.ras.ru
-					or	model@cecmow.enet.dec.com
-					or	H.T.M.v.d.Maarel@marin.nl
-
-It happens sometimes that Vadim is not reachable by mail. For these
-instances, Eric van der Maarel will help too.
-
-		Vadim V. Model, Eric van der Maarel, Eberhard Moenkeberg
diff --git a/Documentation/cdrom/sonycd535 b/Documentation/cdrom/sonycd535
deleted file mode 100644
index b81e109..0000000
--- a/Documentation/cdrom/sonycd535
+++ /dev/null
@@ -1,122 +0,0 @@
-              README FOR LINUX SONY CDU-535/531 DRIVER
-              ========================================
-
-This is the Sony CDU-535 (and 531) driver version 0.7 for Linux.
-I do not think I have the documentation to add features like DMA support
-so if anyone else wants to pursue it or help me with it, please do.
-(I need to see what was done for the CDU-31A driver -- perhaps I can
-steal some of that code.)
-
-This is a Linux device driver for the Sony CDU-535 CDROM drive.  This is
-one of the older Sony drives with its own interface card (Sony bus).
-The DOS driver for this drive is named SONY_CDU.SYS - when you boot DOS
-your drive should be identified as a SONY CDU-535.  The driver works
-with a CDU-531 also.  One user reported that the driver worked on drives
-OEM'ed by Procomm, drive and interface board were labelled Procomm.
-
-The Linux driver is based on Corey Minyard's sonycd 0.3 driver for
-the CDU-31A.  Ron Jeppesen just changed the commands that were sent
-to the drive to correspond to the CDU-535 commands and registers.
-There were enough changes to let bugs creep in but it seems to be stable.
-Ron was able to tar an entire CDROM (should read all blocks) and built
-ghostview and xfig off Walnut Creek's X11R5/GNU CDROM.  xcdplayer and
-workman work with the driver.  Others have used the driver without
-problems except those dealing with wait loops (fixed in third release).
-Like Minyard's original driver this one uses a polled interface (this
-is also the default setup for the DOS driver).  It has not been tried
-with interrupts or DMA enabled on the board.
-
-REQUIREMENTS
-============
-
-	- Sony CDU-535 drive, preferably without interrupts and DMA 
-	  enabled on the card.
-
-	- Drive must be set up as unit 1.  Only the first unit will be 
-	  recognized
-
-	- You must enter your interface address into 
-          /usr/src/linux/drivers/cdrom/sonycd535.h and build the
-          appropriate kernel or use the "kernel command line" parameter
-                sonycd535=0x320
-          with the correct interface address.
-
-NOTES:
-======
-
-1) The drive MUST be turned on when booting or it will not be recognized!
-   (but see comments on modularized version below)
-
-2) when the cdrom device is opened the eject button is disabled to keep the
-   user from ejecting a mounted disk and replacing it with another.
-   Unfortunately xcdplayer and workman also open the cdrom device so you
-   have to use the eject button in the software.  Keep this in mind if your
-   cdrom player refuses to give up its disk -- exit workman or xcdplayer, or
-   umount the drive if it has been mounted.
-
-THANKS
-======
-
-Many thanks to Ron Jeppesen (ronj.an@site007.saic.com) for getting
-this project off the ground.  He wrote the initial release
-and the first two patches to this driver (0.1, 0.2, and 0.3).
-Thanks also to Eberhard Moenkeberg (emoenke@gwdg.de) for prodding
-me to place this code into the mainstream Linux source tree
-(as of Linux version 1.1.91), as well as some patches to make
-it a better device citizen.  Further thanks to Joel Katz
-<joelkatz@webchat.org> for his MODULE patches (see details below),
-Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
-to make the driver work with the older CDU-510/515 series, and
-Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
-the verify_area() checks were ignoring the results of said checks
-(note: verify_area() has since been replaced by access_ok()).
-
-(Acknowledgments from Ron Jeppesen in the 0.3 release:)
-Thanks to Corey Minyard who wrote the original CDU-31A driver on which
-this driver is based.  Thanks to Ken Pizzini and Bob Blair who provided 
-patches and feedback on the first release of this driver.
-
-Ken Pizzini
-ken@halcyon.com
-
-------------------------------------------------------------------------------
-(The following is from Joel Katz <joelkatz@webchat.org>.)
-
-	To build a version of sony535.o that can be installed as a module,
-use the following command:
-
-gcc -c -D__KERNEL__ -DMODULE -O2 sonycd535.c -o sonycd535.o
-
-	To install the module, simply type:
-
-insmod sony535.o
-	or
-insmod sony535.o sonycd535=<address>
-
-	And to remove it:
-
-rmmod sony535
-
-	The code checks to see if MODULE is defined and behaves as it used
-to if MODULE is not defined. That means your patched file should behave
-exactly as it used to if compiled into the kernel.
-
-	I have an external drive, and I usually leave it powered off. I used
-to have to reboot if I needed to use the CDROM drive. Now I don't.
-
-	Even if you have an internal drive, why waste the 96K of memory
-(unswappable) that the driver uses if you use your CD-ROM drive infrequently?
-
-	This driver will not install (whether compiled in or loaded as a
-module) if the CDROM drive is not available during its initialization. This
-means that you can have the driver compiled into the kernel and still load
-the module later (assuming the driver doesn't install itself during
-power-on). This only wastes 12K when you boot with the CDROM drive off.
-
-	This is what I usually do; I leave the driver compiled into the
-kernel, but load it as a module if I powered the system up with the drive
-off and then later decided to use the CDROM drive.
-
-	Since the driver only uses a single page to point to the chunks,
-attempting to set the buffer cache to more than 2 Megabytes would be very
-bad; don't do that.
diff --git a/Documentation/fault-injection/failcmd.sh b/Documentation/fault-injection/failcmd.sh
deleted file mode 100644
index 63177ab..0000000
--- a/Documentation/fault-injection/failcmd.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-echo 1 > /proc/self/make-it-fail
-exec $*
diff --git a/Documentation/fault-injection/failmodule.sh b/Documentation/fault-injection/failmodule.sh
deleted file mode 100644
index 474a8b9..0000000
--- a/Documentation/fault-injection/failmodule.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-#
-# Usage: failmodule <failname> <modulename> [stacktrace-depth]
-#
-#	<failname>: "failslab", "fail_alloc_page", or "fail_make_request"
-#
-#	<modulename>: module name that you want to inject faults.
-#
-#	[stacktrace-depth]: the maximum number of stacktrace walking allowed
-#
-
-STACKTRACE_DEPTH=5
-if [ $# -gt 2 ]; then
-	STACKTRACE_DEPTH=$3
-fi
-
-if [ ! -d /debug/$1 ]; then
-	echo "Fault-injection $1 does not exist" >&2
-	exit 1
-fi
-if [ ! -d /sys/module/$2 ]; then
-	echo "Module $2 does not exist" >&2
-	exit 1
-fi
-
-# Disable any fault injection
-echo 0 > /debug/$1/stacktrace-depth
-
-echo `cat /sys/module/$2/sections/.text` > /debug/$1/require-start
-echo `cat /sys/module/$2/sections/.exit.text` > /debug/$1/require-end
-echo $STACKTRACE_DEPTH > /debug/$1/stacktrace-depth
diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt
index b7ca560..4bc374a 100644
--- a/Documentation/fault-injection/fault-injection.txt
+++ b/Documentation/fault-injection/fault-injection.txt
@@ -103,6 +103,11 @@
 	default is 'N', setting it to 'Y' will inject failures
 	only into non-sleep allocations (GFP_ATOMIC allocations).
 
+- /debug/fail_page_alloc/min-order:
+
+	specifies the minimum page allocation order to be injected
+	failures.
+
 o Boot option
 
 In order to inject faults while debugfs is not available (early boot time),
@@ -156,70 +161,77 @@
 Application Examples
 --------------------
 
-o inject slab allocation failures into module init/cleanup code
+o Inject slab allocation failures into module init/exit code
 
-------------------------------------------------------------------------------
 #!/bin/bash
 
-FAILCMD=Documentation/fault-injection/failcmd.sh
-BLACKLIST="root_plug evbug"
+FAILTYPE=failslab
+echo Y > /debug/$FAILTYPE/task-filter
+echo 10 > /debug/$FAILTYPE/probability
+echo 100 > /debug/$FAILTYPE/interval
+echo -1 > /debug/$FAILTYPE/times
+echo 0 > /debug/$FAILTYPE/space
+echo 2 > /debug/$FAILTYPE/verbose
+echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
 
-FAILNAME=failslab
-echo Y > /debug/$FAILNAME/task-filter
-echo 10 > /debug/$FAILNAME/probability
-echo 100 > /debug/$FAILNAME/interval
-echo -1 > /debug/$FAILNAME/times
-echo 2 > /debug/$FAILNAME/verbose
-echo 1 > /debug/$FAILNAME/ignore-gfp-wait
-
-blacklist()
+faulty_system()
 {
-	echo $BLACKLIST | grep $1 > /dev/null 2>&1
+	bash -c "echo 1 > /proc/self/make-it-fail && exec $*"
 }
 
-oops()
-{
-	dmesg | grep BUG > /dev/null 2>&1
-}
+if [ $# -eq 0 ]
+then
+	echo "Usage: $0 modulename [ modulename ... ]"
+	exit 1
+fi
 
-find /lib/modules/`uname -r` -name '*.ko' -exec basename {} .ko \; |
-	while read i
-	do
-		oops && exit 1
+for m in $*
+do
+	echo inserting $m...
+	faulty_system modprobe $m
 
-		if ! blacklist $i
-		then
-			echo inserting $i...
-			bash $FAILCMD modprobe $i
-		fi
-	done
-
-lsmod | awk '{ if ($3 == 0) { print $1 } }' |
-	while read i
-	do
-		oops && exit 1
-
-		if ! blacklist $i
-		then
-			echo removing $i...
-			bash $FAILCMD modprobe -r $i
-		fi
-	done
+	echo removing $m...
+	faulty_system modprobe -r $m
+done
 
 ------------------------------------------------------------------------------
 
-o inject slab allocation failures only for a specific module
+o Inject page allocation failures only for a specific module
 
-------------------------------------------------------------------------------
 #!/bin/bash
 
-FAILMOD=Documentation/fault-injection/failmodule.sh
+FAILTYPE=fail_page_alloc
+module=$1
 
-echo injecting errors into the module $1...
+if [ -z $module ]
+then
+	echo "Usage: $0 <modulename>"
+	exit 1
+fi
 
-modprobe $1
-bash $FAILMOD failslab $1 10
-echo 25 > /debug/failslab/probability
+modprobe $module
 
-------------------------------------------------------------------------------
+if [ ! -d /sys/module/$module/sections ]
+then
+	echo Module $module is not loaded
+	exit 1
+fi
+
+cat /sys/module/$module/sections/.text > /debug/$FAILTYPE/require-start
+cat /sys/module/$module/sections/.data > /debug/$FAILTYPE/require-end
+
+echo N > /debug/$FAILTYPE/task-filter
+echo 10 > /debug/$FAILTYPE/probability
+echo 100 > /debug/$FAILTYPE/interval
+echo -1 > /debug/$FAILTYPE/times
+echo 0 > /debug/$FAILTYPE/space
+echo 2 > /debug/$FAILTYPE/verbose
+echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
+echo 1 > /debug/$FAILTYPE/ignore-gfp-highmem
+echo 10 > /debug/$FAILTYPE/stacktrace-depth
+
+trap "echo 0 > /debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
+
+echo "Injecting errors into the module $module... (interrupt to stop)"
+sleep 1000000
 
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 092c65d..d05e624 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -41,14 +41,6 @@
 
 ---------------------------
 
-What:	RAW driver (CONFIG_RAW_DRIVER)
-When:	December 2005
-Why:	declared obsolete since kernel 2.6.3
-	O_DIRECT can be used instead
-Who:	Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What:	old NCR53C9x driver
 When:	October 2007
 Why:	Replaced by the much better esp_scsi driver.  Actual low-level
@@ -119,13 +111,6 @@
 
 ---------------------------
 
-What:  drivers depending on OSS_OBSOLETE_DRIVER
-When:  options in 2.6.20, code in 2.6.22
-Why:   OSS drivers with ALSA replacements
-Who:   Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What:	Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
 	(temporary transition config option provided until then)
 	The transition config option will also be removed at the same time.
@@ -264,6 +249,14 @@
 
 ---------------------------
 
+What:	'time' kernel boot parameter
+When:	January 2008
+Why:	replaced by 'printk.time=<value>' so that printk timestamps can be
+	enabled or disabled as needed
+Who:	Randy Dunlap <randy.dunlap@oracle.com>
+
+---------------------------
+
 What:  drivers depending on OSS_OBSOLETE
 When:  options in 2.6.23, code in 2.6.25
 Why:   obsolete OSS drivers
@@ -304,3 +297,16 @@
 Who:	Patrick McHardy <kaber@trash.net>
 
 ---------------------------
+
+What: The arch/ppc and include/asm-ppc directories
+When: Jun 2008
+Why:  The arch/powerpc tree is the merged architecture for ppc32 and ppc64
+      platforms.  Currently there are efforts underway to port the remaining
+      arch/ppc platforms to the merged tree.  New submissions to the arch/ppc
+      tree have been frozen with the 2.6.22 kernel release and that tree will
+      remain in bug-fix only mode until its scheduled removal.  Platforms
+      that are not ported by June 2008 will be removed due to the lack of an
+      interested maintainer.
+Who:  linuxppc-dev@ozlabs.org
+
+---------------------------
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
index b34cdb5..d1b9825 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -238,6 +238,8 @@
 		struct config_group *(*make_group)(struct config_group *group,
 						   const char *name);
 		int (*commit_item)(struct config_item *item);
+		void (*disconnect_notify)(struct config_group *group,
+					  struct config_item *item);
 		void (*drop_item)(struct config_group *group,
 				  struct config_item *item);
 	};
@@ -268,6 +270,16 @@
 for the item to actually disappear from the subsystem's usage.  But it
 is gone from configfs.
 
+When drop_item() is called, the item's linkage has already been torn
+down.  It no longer has a reference on its parent and has no place in
+the item hierarchy.  If a client needs to do some cleanup before this
+teardown happens, the subsystem can implement the
+ct_group_ops->disconnect_notify() method.  The method is called after
+configfs has removed the item from the filesystem view but before the
+item is removed from its parent group.  Like drop_item(),
+disconnect_notify() is void and cannot fail.  Client subsystems should
+not drop any references here, as they still must do it in drop_item().
+
 A config_group cannot be removed while it still has child items.  This
 is implemented in the configfs rmdir(2) code.  ->drop_item() will not be
 called, as the item has not been dropped.  rmdir(2) will fail, as the
@@ -280,18 +292,18 @@
 
 	struct configfs_subsystem {
 		struct config_group	su_group;
-		struct semaphore	su_sem;
+		struct mutex		su_mutex;
 	};
 
 	int configfs_register_subsystem(struct configfs_subsystem *subsys);
 	void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
 
-	A subsystem consists of a toplevel config_group and a semaphore.
+	A subsystem consists of a toplevel config_group and a mutex.
 The group is where child config_items are created.  For a subsystem,
 this group is usually defined statically.  Before calling
 configfs_register_subsystem(), the subsystem must have initialized the
 group via the usual group _init() functions, and it must also have
-initialized the semaphore.
+initialized the mutex.
 	When the register call returns, the subsystem is live, and it
 will be visible via configfs.  At that point, mkdir(2) can be called and
 the subsystem must be ready for it.
@@ -303,7 +315,7 @@
 shows a trivial object displaying and storing an attribute, and a simple
 group creating and destroying these children.
 
-[Hierarchy Navigation and the Subsystem Semaphore]
+[Hierarchy Navigation and the Subsystem Mutex]
 
 There is an extra bonus that configfs provides.  The config_groups and
 config_items are arranged in a hierarchy due to the fact that they
@@ -314,19 +326,19 @@
 
 A subsystem can navigate the cg_children list and the ci_parent pointer
 to see the tree created by the subsystem.  This can race with configfs'
-management of the hierarchy, so configfs uses the subsystem semaphore to
+management of the hierarchy, so configfs uses the subsystem mutex to
 protect modifications.  Whenever a subsystem wants to navigate the
 hierarchy, it must do so under the protection of the subsystem
-semaphore.
+mutex.
 
-A subsystem will be prevented from acquiring the semaphore while a newly
+A subsystem will be prevented from acquiring the mutex while a newly
 allocated item has not been linked into this hierarchy.   Similarly, it
-will not be able to acquire the semaphore while a dropping item has not
+will not be able to acquire the mutex while a dropping item has not
 yet been unlinked.  This means that an item's ci_parent pointer will
 never be NULL while the item is in configfs, and that an item will only
 be in its parent's cg_children list for the same duration.  This allows
 a subsystem to trust ci_parent and cg_children while they hold the
-semaphore.
+mutex.
 
 [Item Aggregation Via symlink(2)]
 
@@ -386,6 +398,33 @@
 rmdir(2).  They also are not considered when rmdir(2) on the parent
 group is checking for children.
 
+[Dependant Subsystems]
+
+Sometimes other drivers depend on particular configfs items.  For
+example, ocfs2 mounts depend on a heartbeat region item.  If that
+region item is removed with rmdir(2), the ocfs2 mount must BUG or go
+readonly.  Not happy.
+
+configfs provides two additional API calls: configfs_depend_item() and
+configfs_undepend_item().  A client driver can call
+configfs_depend_item() on an existing item to tell configfs that it is
+depended on.  configfs will then return -EBUSY from rmdir(2) for that
+item.  When the item is no longer depended on, the client driver calls
+configfs_undepend_item() on it.
+
+These API cannot be called underneath any configfs callbacks, as
+they will conflict.  They can block and allocate.  A client driver
+probably shouldn't calling them of its own gumption.  Rather it should
+be providing an API that external subsystems call.
+
+How does this work?  Imagine the ocfs2 mount process.  When it mounts,
+it asks for a heartbeat region item.  This is done via a call into the
+heartbeat code.  Inside the heartbeat code, the region item is looked
+up.  Here, the heartbeat code calls configfs_depend_item().  If it
+succeeds, then heartbeat knows the region is safe to give to ocfs2.
+If it fails, it was being torn down anyway, and heartbeat can gracefully
+pass up an error.
+
 [Committable Items]
 
 NOTE: Committable items are currently unimplemented.
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c
index 2d6a14a..e56d492 100644
--- a/Documentation/filesystems/configfs/configfs_example.c
+++ b/Documentation/filesystems/configfs/configfs_example.c
@@ -453,7 +453,7 @@
 		subsys = example_subsys[i];
 
 		config_group_init(&subsys->su_group);
-		init_MUTEX(&subsys->su_sem);
+		mutex_init(&subsys->su_mutex);
 		ret = configfs_register_subsystem(subsys);
 		if (ret) {
 			printk(KERN_ERR "Error %d while registering subsystem %s\n",
diff --git a/Documentation/ecryptfs.txt b/Documentation/filesystems/ecryptfs.txt
similarity index 100%
rename from Documentation/ecryptfs.txt
rename to Documentation/filesystems/ecryptfs.txt
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 8756a07..ebffdff 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -171,7 +171,9 @@
 This shows you nearly the same information you would get if you viewed it with
 the ps  command.  In  fact,  ps  uses  the  proc  file  system  to  obtain its
 information. The  statm  file  contains  more  detailed  information about the
-process memory usage. Its seven fields are explained in Table 1-2.
+process memory usage. Its seven fields are explained in Table 1-2.  The stat
+file contains details information about the process itself.  Its fields are
+explained in Table 1-3.
 
 
 Table 1-2: Contents of the statm files (as of 2.6.8-rc3)
@@ -188,16 +190,65 @@
  dt       number of dirty pages			(always 0 on 2.6)
 ..............................................................................
 
+
+Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
+..............................................................................
+ Field          Content
+  pid           process id
+  tcomm         filename of the executable
+  state         state (R is running, S is sleeping, D is sleeping in an
+                uninterruptible wait, Z is zombie, T is traced or stopped)
+  ppid          process id of the parent process
+  pgrp          pgrp of the process
+  sid           session id
+  tty_nr        tty the process uses
+  tty_pgrp      pgrp of the tty
+  flags         task flags
+  min_flt       number of minor faults
+  cmin_flt      number of minor faults with child's
+  maj_flt       number of major faults
+  cmaj_flt      number of major faults with child's
+  utime         user mode jiffies
+  stime         kernel mode jiffies
+  cutime        user mode jiffies with child's
+  cstime        kernel mode jiffies with child's
+  priority      priority level
+  nice          nice level
+  num_threads   number of threads
+  start_time    time the process started after system boot
+  vsize         virtual memory size
+  rss           resident set memory size
+  rsslim        current limit in bytes on the rss
+  start_code    address above which program text can run
+  end_code      address below which program text can run
+  start_stack   address of the start of the stack
+  esp           current value of ESP
+  eip           current value of EIP
+  pending       bitmap of pending signals (obsolete)
+  blocked       bitmap of blocked signals (obsolete)
+  sigign        bitmap of ignored signals (obsolete)
+  sigcatch      bitmap of catched signals (obsolete)
+  wchan         address where process went to sleep
+  0             (place holder)
+  0             (place holder)
+  exit_signal   signal to send to parent thread on exit
+  task_cpu      which CPU the task is scheduled on
+  rt_priority   realtime priority
+  policy        scheduling policy (man sched_setscheduler)
+  blkio_ticks   time spent waiting for block IO
+..............................................................................
+
+
 1.2 Kernel data
 ---------------
 
 Similar to  the  process entries, the kernel data files give information about
 the running kernel. The files used to obtain this information are contained in
-/proc and  are  listed  in Table 1-3. Not all of these will be present in your
+/proc and  are  listed  in Table 1-4. Not all of these will be present in your
 system. It  depends  on the kernel configuration and the loaded modules, which
 files are there, and which are missing.
 
-Table 1-3: Kernel info in /proc 
+Table 1-4: Kernel info in /proc
 ..............................................................................
  File        Content                                           
  apm         Advanced power management info                    
@@ -473,10 +524,10 @@
 
 More detailed  information  can  be  found  in  the  controller  specific
 subdirectories. These  are  named  ide0,  ide1  and  so  on.  Each  of  these
-directories contains the files shown in table 1-4.
+directories contains the files shown in table 1-5.
 
 
-Table 1-4: IDE controller info in  /proc/ide/ide? 
+Table 1-5: IDE controller info in  /proc/ide/ide?
 ..............................................................................
  File    Content                                 
  channel IDE channel (0 or 1)                    
@@ -486,11 +537,11 @@
 ..............................................................................
 
 Each device  connected  to  a  controller  has  a separate subdirectory in the
-controllers directory.  The  files  listed in table 1-5 are contained in these
+controllers directory.  The  files  listed in table 1-6 are contained in these
 directories.
 
 
-Table 1-5: IDE device information 
+Table 1-6: IDE device information
 ..............................................................................
  File             Content                                    
  cache            The cache                                  
@@ -1297,6 +1348,21 @@
 hugetlb_shm_group contains group id that is allowed to create SysV shared
 memory segment using hugetlb page.
 
+hugepages_treat_as_movable
+--------------------------
+
+This parameter is only useful when kernelcore= is specified at boot time to
+create ZONE_MOVABLE for pages that may be reclaimed or migrated. Huge pages
+are not movable so are not normally allocated from ZONE_MOVABLE. A non-zero
+value written to hugepages_treat_as_movable allows huge pages to be allocated
+from ZONE_MOVABLE.
+
+Once enabled, the ZONE_MOVABLE is treated as an area of memory the huge
+pages pool can easily grow or shrink within. Assuming that applications are
+not running that mlock() a lot of memory, it is likely the huge pages pool
+can grow to the size of ZONE_MOVABLE by repeatedly entering the desired value
+into nr_hugepages and triggering page reclaim.
+
 laptop_mode
 -----------
 
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index a47cc81..045f3e0 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -3,7 +3,7 @@
 
 	Original author: Richard Gooch <rgooch@atnf.csiro.au>
 
-		  Last updated on October 28, 2005
+		  Last updated on June 24, 2007.
 
   Copyright (C) 1999 Richard Gooch
   Copyright (C) 2005 Pekka Enberg
@@ -107,7 +107,7 @@
 struct file_system_type
 -----------------------
 
-This describes the filesystem. As of kernel 2.6.13, the following
+This describes the filesystem. As of kernel 2.6.22, the following
 members are defined:
 
 struct file_system_type {
@@ -119,6 +119,8 @@
         struct module *owner;
         struct file_system_type * next;
         struct list_head fs_supers;
+	struct lock_class_key s_lock_key;
+	struct lock_class_key s_umount_key;
 };
 
   name: the name of the filesystem type, such as "ext2", "iso9660",
@@ -137,11 +139,12 @@
 
   next: for internal VFS use: you should initialize this to NULL
 
+  s_lock_key, s_umount_key: lockdep-specific
+
 The get_sb() method has the following arguments:
 
-  struct super_block *sb: the superblock structure. This is partially
-	initialized by the VFS and the rest must be initialized by the
-	get_sb() method
+  struct file_system_type *fs_type: decribes the filesystem, partly initialized
+  	by the specific filesystem code
 
   int flags: mount flags
 
@@ -150,12 +153,13 @@
   void *data: arbitrary mount options, usually comes as an ASCII
 	string
 
-  int silent: whether or not to be silent on error
+  struct vfsmount *mnt: a vfs-internal representation of a mount point
 
 The get_sb() method must determine if the block device specified
-in the superblock contains a filesystem of the type the method
-supports. On success the method returns the superblock pointer, on
-failure it returns NULL.
+in the dev_name and fs_type contains a filesystem of the type the method
+supports. If it succeeds in opening the named block device, it initializes a
+struct super_block descriptor for the filesystem contained by the block device.
+On failure it returns an error.
 
 The most interesting member of the superblock structure that the
 get_sb() method fills in is the "s_op" field. This is a pointer to
@@ -193,7 +197,7 @@
 -----------------------
 
 This describes how the VFS can manipulate the superblock of your
-filesystem. As of kernel 2.6.13, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct super_operations {
         struct inode *(*alloc_inode)(struct super_block *sb);
@@ -216,8 +220,6 @@
         void (*clear_inode) (struct inode *);
         void (*umount_begin) (struct super_block *);
 
-        void (*sync_inodes) (struct super_block *sb,
-                                struct writeback_control *wbc);
         int (*show_options)(struct seq_file *, struct vfsmount *);
 
         ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
@@ -300,9 +302,6 @@
 
   umount_begin: called when the VFS is unmounting a filesystem.
 
-  sync_inodes: called when the VFS is writing out dirty data associated with
-  	a superblock.
-
   show_options: called by the VFS to show mount options for /proc/<pid>/mounts.
 
   quota_read: called by the VFS to read from filesystem quota file.
@@ -324,7 +323,7 @@
 -----------------------
 
 This describes how the VFS can manipulate an inode in your
-filesystem. As of kernel 2.6.13, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct inode_operations {
 	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
@@ -348,6 +347,7 @@
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
+	void (*truncate_range)(struct inode *, loff_t, loff_t);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -444,6 +444,9 @@
   removexattr: called by the VFS to remove an extended attribute from
   	a file. This method is called by removexattr(2) system call.
 
+  truncate_range: a method provided by the underlying filesystem to truncate a
+  	range of blocks , i.e. punch a hole somewhere in a file.
+
 
 The Address Space Object
 ========================
@@ -522,7 +525,7 @@
 -------------------------------
 
 This describes how the VFS can manipulate mapping of a file to page cache in
-your filesystem. As of kernel 2.6.16, the following members are defined:
+your filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct address_space_operations {
 	int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -543,6 +546,7 @@
 			int);
 	/* migrate the contents of a page to the specified target */
 	int (*migratepage) (struct page *, struct page *);
+	int (*launder_page) (struct page *);
 };
 
   writepage: called by the VM to write a dirty page to backing store.
@@ -689,6 +693,10 @@
 	transfer any private data across and update any references
         that it has to the page.
 
+  launder_page: Called before freeing a page - it writes back the dirty page. To
+  	prevent redirtying the page, it is kept locked during the whole
+	operation.
+
 The File Object
 ===============
 
@@ -699,9 +707,10 @@
 ----------------------
 
 This describes how the VFS can manipulate an open file. As of kernel
-2.6.17, the following members are defined:
+2.6.22, the following members are defined:
 
 struct file_operations {
+	struct module *owner;
 	loff_t (*llseek) (struct file *, loff_t, int);
 	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
 	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
@@ -728,10 +737,8 @@
 	int (*check_flags)(int);
 	int (*dir_notify)(struct file *filp, unsigned long arg);
 	int (*flock) (struct file *, int, struct file_lock *);
-	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned 
-int);
-	ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned  
-int);
+	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);
+	ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int);
 };
 
 Again, all methods are called without any locks being held, unless
diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
index 22b0814..20d368c 100644
--- a/Documentation/hrtimer/timer_stats.txt
+++ b/Documentation/hrtimer/timer_stats.txt
@@ -67,3 +67,7 @@
 
     Thomas, Ingo
 
+Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
+timer will appear as follows
+  10D,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index 3de7d37..5c7fbf9 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -67,7 +67,7 @@
 0x00	00-1F	linux/wavefront.h	conflict!
 0x02	all	linux/fd.h
 0x03	all	linux/hdreg.h
-0x04	all	linux/umsdos_fs.h
+0x04	D2-DC	linux/umsdos_fs.h	Dead since 2.6.11, but don't reuse these.
 0x06	all	linux/lp.h
 0x09	all	linux/md.h
 0x12	all	linux/fs.h
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4d880b3..9a54148 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -34,7 +34,6 @@
 	APIC	APIC support is enabled.
 	APM	Advanced Power Management support is enabled.
 	AX25	Appropriate AX.25 support is enabled.
-	CD	Appropriate CD support is enabled.
 	DRM	Direct Rendering Management support is enabled.
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
@@ -238,16 +237,9 @@
 			Disable PIN 1 of APIC timer
 			Can be useful to work around chipset bugs.
 
-	ad1816=		[HW,OSS]
-			Format: <io>,<irq>,<dma>,<dma2>
-			See also Documentation/sound/oss/AD1816.
-
 	ad1848=		[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>,<type>
 
-	adlib=		[HW,OSS]
-			Format: <io>
-
 	advansys=	[HW,SCSI]
 			See header of drivers/scsi/advansys.c.
 
@@ -326,9 +318,6 @@
 
 	autotest	[IA64]
 
-	aztcd=		[HW,CD] Aztech CD268 CDROM driver
-			Format: <io>,0x79 (?)
-
 	baycom_epp=	[HW,AX25]
 			Format: <io>,<mode>
 
@@ -371,10 +360,6 @@
 			possible to determine what the correct size should be.
 			This option provides an override for these situations.
 
-	cdu31a=		[HW,CD]
-			Format: <io>,<irq>[,PAS]
-			See header of drivers/cdrom/cdu31a.c.
-
 	chandev=	[HW,NET] Generic channel device initialisation
 
 	checkreqprot	[SELINUX] Set initial checkreqprot flag value.
@@ -428,9 +413,6 @@
 	hpet=		[IA-32,HPET] option to disable HPET and use PIT.
 			Format: disable
 
-	cm206=		[HW,CD]
-			Format: { auto | [<io>,][<irq>] }
-
 	com20020=	[HW,NET] ARCnet - COM20020 chipset
 			Format:
 			<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
@@ -462,13 +444,20 @@
 			Documentation/networking/netconsole.txt for an
 			alternative.
 
-		uart,io,<addr>[,options]
-		uart,mmio,<addr>[,options]
+		uart[8250],io,<addr>[,options]
+		uart[8250],mmio,<addr>[,options]
 			Start an early, polled-mode console on the 8250/16550
 			UART at the specified I/O port or MMIO address,
 			switching to the matching ttyS device later.  The
 			options are the same as for ttyS, above.
 
+	earlycon=	[KNL] Output early console device and options.
+		uart[8250],io,<addr>[,options]
+		uart[8250],mmio,<addr>[,options]
+			Start an early, polled-mode console on the 8250/16550
+			UART at the specified I/O port or MMIO address.
+			The options are the same as for ttyS, above.
+
 	cpcihp_generic=	[HW,PCI] Generic port I/O CompactPCI driver
 			Format:
 			<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
@@ -660,9 +649,6 @@
 	gpt		[EFI] Forces disk with valid GPT signature but
 			invalid Protective MBR to be treated as GPT.
 
-	gscd=		[HW,CD]
-			Format: <io>
-
 	gvp11=		[HW,SCSI]
 
 	hashdist=	[KNL,NUMA] Large hashes allocated during boot
@@ -826,14 +812,37 @@
 			tasks in the system -- can cause problems and
 			suboptimal load balancer performance.
 
-	isp16=		[HW,CD]
-			Format: <io>,<irq>,<dma>,<setup>
-
 	iucv=		[HW,NET]
 
 	js=		[HW,JOY] Analog joystick
 			See Documentation/input/joystick.txt.
 
+	kernelcore=nn[KMG]	[KNL,IA-32,IA-64,PPC,X86-64] This parameter
+			specifies the amount of memory usable by the kernel
+			for non-movable allocations.  The requested amount is
+			spread evenly throughout all nodes in the system. The
+			remaining memory in each node is used for Movable
+			pages. In the event, a node is too small to have both
+			kernelcore and Movable pages, kernelcore pages will
+			take priority and other nodes will have a larger number
+			of kernelcore pages.  The Movable zone is used for the
+			allocation of pages that may be reclaimed or moved
+			by the page migration subsystem.  This means that
+			HugeTLB pages may not be allocated from this zone.
+			Note that allocations like PTEs-from-HighMem still
+			use the HighMem zone if it exists, and the Normal
+			zone if it does not.
+
+	movablecore=nn[KMG]	[KNL,IA-32,IA-64,PPC,X86-64] This parameter
+			is similar to kernelcore except it specifies the
+			amount of memory used for migratable allocations.
+			If both kernelcore and movablecore is specified,
+			then kernelcore will be at *least* the specified
+			value but may be more. If movablecore on its own
+			is specified, the administrator must be careful
+			that the amount of memory usable for all allocations
+			is not too small.
+
 	keepinitrd	[HW,ARM]
 
 	kstack=N	[IA-32,X86-64] Print N words from the kernel stack
@@ -967,11 +976,6 @@
 
 	mcatest=	[IA-64]
 
-	mcd=		[HW,CD]
-			Format: <port>,<irq>,<mitsumi_bug_93_wait>
-
-	mcdx=		[HW,CD]
-
 	mce		[IA-32] Machine Check Exception
 
 	md=		[HW] RAID subsystems devices and level
@@ -1181,6 +1185,8 @@
 
 	nosmp		[SMP] Tells an SMP kernel to act as a UP kernel.
 
+	nosoftlockup	[KNL] Disable the soft-lockup detector.
+
 	nosync		[HW,M68K] Disables sync negotiation for all devices.
 
 	notsc		[BUGS=IA-32] Disable Time Stamp Counter
@@ -1189,20 +1195,19 @@
 
 	nowb		[ARM]
 
+	numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
+			one of ['zone', 'node', 'default'] can be specified
+			This can be set from sysctl after boot.
+			See Documentation/sysctl/vm.txt for details.
+
 	nr_uarts=	[SERIAL] maximum number of UARTs to be registered.
 
 	opl3=		[HW,OSS]
 			Format: <io>
 
-	opl3sa2=	[HW,OSS] Format:
-			<io>,<irq>,<dma>,<dma2>,<mss_io>,<mpu_io>,<ymode>,<loopback>[,<isapnp>,<multiple]
-
 	oprofile.timer=	[HW]
 			Use timer interrupt instead of performance counters
 
-	optcd=		[HW,CD]
-			Format: <io>
-
 	osst=		[HW,SCSI] SCSI Tape Driver
 			Format: <buffer_size>,<write_threshold>
 			See also Documentation/scsi/st.txt.
@@ -1381,6 +1386,15 @@
 			autoconfiguration.
 			Ranges are in pairs (memory base and size).
 
+	print-fatal-signals=
+			[KNL] debug: print fatal signals
+			print-fatal-signals=1: print segfault info to
+			the kernel console.
+			default: off.
+
+	printk.time=	Show timing data prefixed to each printk message line
+			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
+
 	profile=	[KNL] Enable kernel profiling via /proc/profile
 			Format: [schedule,]<number>
 			Param: "schedule" - profile schedule points.
@@ -1493,6 +1507,10 @@
 
 	rootfstype=	[KNL] Set root filesystem type
 
+	rootwait	[KNL] Wait (indefinitely) for root device to show up.
+			Useful for devices that are detected asynchronously
+			(e.g. USB and MMC devices).
+
 	rw		[KNL] Mount root device read-write on boot
 
 	S		[KNL] Run init in single mode
@@ -1505,11 +1523,6 @@
 
 	sbni=		[NET] Granch SBNI12 leased line adapter
 
-	sbpcd=		[HW,CD] Soundblaster CD adapter
-			Format: <io>,<type>
-			See a comment before function sbpcd_setup() in
-			drivers/cdrom/sbpcd.c.
-
 	sc1200wdt=	[HW,WDT] SC1200 WDT (watchdog) driver
 			Format: <io>[,<timeout>[,<isapnp>]]
 
@@ -1562,41 +1575,41 @@
 	simeth=		[IA-64]
 	simscsi=
 
-	sjcd=		[HW,CD]
-			Format: <io>,<irq>,<dma>
-			See header of drivers/cdrom/sjcd.c.
-
 	slram=		[HW,MTD]
 
-	slub_debug	[MM, SLUB]
-			Enabling slub_debug allows one to determine the culprit
-			if slab objects become corrupted. Enabling slub_debug
-			creates guard zones around objects and poisons objects
-			when not in use. Also tracks the last alloc / free.
-			For more information see Documentation/vm/slub.txt.
+	slub_debug[=options[,slabs]]	[MM, SLUB]
+			Enabling slub_debug allows one to determine the
+			culprit if slab objects become corrupted. Enabling
+			slub_debug can create guard zones around objects and
+			may poison objects when not in use. Also tracks the
+			last alloc / free. For more information see
+			Documentation/vm/slub.txt.
 
 	slub_max_order= [MM, SLUB]
-			Determines the maximum allowed order for slabs. Setting
-			this too high may cause fragmentation.
-			For more information see Documentation/vm/slub.txt.
+			Determines the maximum allowed order for slabs.
+			A high setting may cause OOMs due to memory
+			fragmentation. For more information see
+			Documentation/vm/slub.txt.
 
 	slub_min_objects=	[MM, SLUB]
-			The minimum objects per slab. SLUB will increase the
-			slab order up to slub_max_order to generate a
-			sufficiently big slab to satisfy the number of objects.
-			The higher the number of objects the smaller the overhead
-			of tracking slabs.
+			The minimum number of objects per slab. SLUB will
+			increase the slab order up to slub_max_order to
+			generate a sufficiently large slab able to contain
+			the number of objects indicated. The higher the number
+			of objects the smaller the overhead of tracking slabs
+			and the less frequently locks need to be acquired.
 			For more information see Documentation/vm/slub.txt.
 
 	slub_min_order=	[MM, SLUB]
 			Determines the mininum page order for slabs. Must be
-			lower than slub_max_order
+			lower than slub_max_order.
 			For more information see Documentation/vm/slub.txt.
 
 	slub_nomerge	[MM, SLUB]
-			Disable merging of slabs of similar size. May be
+			Disable merging of slabs with similar size. May be
 			necessary if there is some reason to distinguish
-			allocs to different slabs.
+			allocs to different slabs. Debug options disable
+			merging on their own.
 			For more information see Documentation/vm/slub.txt.
 
 	smart2=		[HW]
@@ -1738,9 +1751,6 @@
 
 	snd-ymfpci=	[HW,ALSA]
 
-	sonycd535=	[HW,CD]
-			Format: <io>[,<irq>]
-
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
 			See Documentation/sonypi.txt
 
@@ -1812,6 +1822,7 @@
 			Set number of hash buckets for TCP connection
 
 	time		Show timing data prefixed to each printk message line
+			[deprecated, see 'printk.time']
 
 	tipar.timeout=	[HW,PPT]
 			Set communications timeout in tenths of a second
diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt
index 1c41db2..59108ce 100644
--- a/Documentation/m68k/kernel-options.txt
+++ b/Documentation/m68k/kernel-options.txt
@@ -82,13 +82,6 @@
   /dev/fd : -> 0x0200 (floppy disk)
   /dev/xda: -> 0x0c00 (first XT disk, unused in Linux/m68k)
   /dev/xdb: -> 0x0c40 (second XT disk, unused in Linux/m68k)
-  /dev/ada: -> 0x1c00 (first ACSI device)
-  /dev/adb: -> 0x1c10 (second ACSI device)
-  /dev/adc: -> 0x1c20 (third ACSI device)
-  /dev/add: -> 0x1c30 (forth ACSI device)
-
-The last four names are available only if the kernel has been compiled
-with Atari and ACSI support.
 
   The name must be followed by a decimal number, that stands for the
 partition number. Internally, the value of the number is just
diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt
index 0b27863..98c4392 100644
--- a/Documentation/networking/net-modules.txt
+++ b/Documentation/networking/net-modules.txt
@@ -146,12 +146,6 @@
 	irq = 0
 	(Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300)
 
-atari_bionet.c:
-	Supports full autoprobing. (m68k/Atari)
-
-atari_pamsnet.c:
-	Supports full autoprobing. (m68k/Atari)
-
 atarilance.c:
 	Supports full autoprobing. (m68k/Atari)
 
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 7d5b60d..7f60dfe 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -86,6 +86,20 @@
 and do a replace of spaces to "\x" - that's what I do, as I'm too lazy 
 to write a program to automate this all).
 
+Alternatively, you can use the shell script in scripts/decodecode.
+Its usage is:  decodecode < oops.txt
+
+The hex bytes that follow "Code:" may (in some architectures) have a series
+of bytes that precede the current instruction pointer as well as bytes at and
+following the current instruction pointer.  In some cases, one instruction
+byte or word is surrounded by <> or (), as in "<86>" or "(f00d)".  These
+<> or () markings indicate the current instruction pointer.  Example from
+i386, split into multiple lines for readability:
+
+Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
+64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
+7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
+
 Finally, if you want to see where the code comes from, you can do
 
 	cd /usr/src/linux
@@ -237,6 +251,8 @@
   7: 'U' if a user or user application specifically requested that the
      Tainted flag be set, ' ' otherwise.
 
+  8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
diff --git a/Documentation/power/freezing-of-tasks.txt b/Documentation/power/freezing-of-tasks.txt
new file mode 100644
index 0000000..af1a282
--- /dev/null
+++ b/Documentation/power/freezing-of-tasks.txt
@@ -0,0 +1,160 @@
+Freezing of tasks
+	(C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+
+I. What is the freezing of tasks?
+
+The freezing of tasks is a mechanism by which user space processes and some
+kernel threads are controlled during hibernation or system-wide suspend (on some
+architectures).
+
+II. How does it work?
+
+There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE
+and PF_FREEZER_SKIP (the last one is auxiliary).  The tasks that have
+PF_NOFREEZE unset (all user space processes and some kernel threads) are
+regarded as 'freezable' and treated in a special way before the system enters a
+suspend state as well as before a hibernation image is created (in what follows
+we only consider hibernation, but the description also applies to suspend).
+
+Namely, as the first step of the hibernation procedure the function
+freeze_processes() (defined in kernel/power/process.c) is called.  It executes
+try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
+sends a fake signal to each of them.  A task that receives such a signal and has
+TIF_FREEZE set, should react to it by calling the refrigerator() function
+(defined in kernel/power/process.c), which sets the task's PF_FROZEN flag,
+changes its state to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is
+cleared for it.  Then, we say that the task is 'frozen' and therefore the set of
+functions handling this mechanism is called 'the freezer' (these functions are
+defined in kernel/power/process.c and include/linux/freezer.h).  User space
+processes are generally frozen before kernel threads.
+
+It is not recommended to call refrigerator() directly.  Instead, it is
+recommended to use the try_to_freeze() function (defined in
+include/linux/freezer.h), that checks the task's TIF_FREEZE flag and makes the
+task enter refrigerator() if the flag is set.
+
+For user space processes try_to_freeze() is called automatically from the
+signal-handling code, but the freezable kernel threads need to call it
+explicitly in suitable places.  The code to do this may look like the following:
+
+	do {
+		hub_events();
+		wait_event_interruptible(khubd_wait,
+					!list_empty(&hub_event_list));
+		try_to_freeze();
+	} while (!signal_pending(current));
+
+(from drivers/usb/core/hub.c::hub_thread()).
+
+If a freezable kernel thread fails to call try_to_freeze() after the freezer has
+set TIF_FREEZE for it, the freezing of tasks will fail and the entire
+hibernation operation will be cancelled.  For this reason, freezable kernel
+threads must call try_to_freeze() somewhere.
+
+After the system memory state has been restored from a hibernation image and
+devices have been reinitialized, the function thaw_processes() is called in
+order to clear the PF_FROZEN flag for each frozen task.  Then, the tasks that
+have been frozen leave refrigerator() and continue running.
+
+III. Which kernel threads are freezable?
+
+Kernel threads are not freezable by default.  However, a kernel thread may clear
+PF_NOFREEZE for itself by calling set_freezable() (the resetting of PF_NOFREEZE
+directly is strongly discouraged).  From this point it is regarded as freezable
+and must call try_to_freeze() in a suitable place.
+
+IV. Why do we do that?
+
+Generally speaking, there is a couple of reasons to use the freezing of tasks:
+
+1. The principal reason is to prevent filesystems from being damaged after
+hibernation.  At the moment we have no simple means of checkpointing
+filesystems, so if there are any modifications made to filesystem data and/or
+metadata on disks, we cannot bring them back to the state from before the
+modifications.  At the same time each hibernation image contains some
+filesystem-related information that must be consistent with the state of the
+on-disk data and metadata after the system memory state has been restored from
+the image (otherwise the filesystems will be damaged in a nasty way, usually
+making them almost impossible to repair).  We therefore freeze tasks that might
+cause the on-disk filesystems' data and metadata to be modified after the
+hibernation image has been created and before the system is finally powered off.
+The majority of these are user space processes, but if any of the kernel threads
+may cause something like this to happen, they have to be freezable.
+
+2. The second reason is to prevent user space processes and some kernel threads
+from interfering with the suspending and resuming of devices.  A user space
+process running on a second CPU while we are suspending devices may, for
+example, be troublesome and without the freezing of tasks we would need some
+safeguards against race conditions that might occur in such a case.
+
+Although Linus Torvalds doesn't like the freezing of tasks, he said this in one
+of the discussions on LKML (http://lkml.org/lkml/2007/4/27/608):
+
+"RJW:> Why we freeze tasks at all or why we freeze kernel threads?
+
+Linus: In many ways, 'at all'.
+
+I _do_ realize the IO request queue issues, and that we cannot actually do
+s2ram with some devices in the middle of a DMA.  So we want to be able to
+avoid *that*, there's no question about that.  And I suspect that stopping
+user threads and then waiting for a sync is practically one of the easier
+ways to do so.
+
+So in practice, the 'at all' may become a 'why freeze kernel threads?' and
+freezing user threads I don't find really objectionable."
+
+Still, there are kernel threads that may want to be freezable.  For example, if
+a kernel that belongs to a device driver accesses the device directly, it in
+principle needs to know when the device is suspended, so that it doesn't try to
+access it at that time.  However, if the kernel thread is freezable, it will be
+frozen before the driver's .suspend() callback is executed and it will be
+thawed after the driver's .resume() callback has run, so it won't be accessing
+the device while it's suspended.
+
+3. Another reason for freezing tasks is to prevent user space processes from
+realizing that hibernation (or suspend) operation takes place.  Ideally, user
+space processes should not notice that such a system-wide operation has occurred
+and should continue running without any problems after the restore (or resume
+from suspend).  Unfortunately, in the most general case this is quite difficult
+to achieve without the freezing of tasks.  Consider, for example, a process
+that depends on all CPUs being online while it's running.  Since we need to
+disable nonboot CPUs during the hibernation, if this process is not frozen, it
+may notice that the number of CPUs has changed and may start to work incorrectly
+because of that.
+
+V. Are there any problems related to the freezing of tasks?
+
+Yes, there are.
+
+First of all, the freezing of kernel threads may be tricky if they depend one
+on another.  For example, if kernel thread A waits for a completion (in the
+TASK_UNINTERRUPTIBLE state) that needs to be done by freezable kernel thread B
+and B is frozen in the meantime, then A will be blocked until B is thawed, which
+may be undesirable.  That's why kernel threads are not freezable by default.
+
+Second, there are the following two problems related to the freezing of user
+space processes:
+1. Putting processes into an uninterruptible sleep distorts the load average.
+2. Now that we have FUSE, plus the framework for doing device drivers in
+userspace, it gets even more complicated because some userspace processes are
+now doing the sorts of things that kernel threads do
+(https://lists.linux-foundation.org/pipermail/linux-pm/2007-May/012309.html).
+
+The problem 1. seems to be fixable, although it hasn't been fixed so far.  The
+other one is more serious, but it seems that we can work around it by using
+hibernation (and suspend) notifiers (in that case, though, we won't be able to
+avoid the realization by the user space processes that the hibernation is taking
+place).
+
+There are also problems that the freezing of tasks tends to expose, although
+they are not directly related to it.  For example, if request_firmware() is
+called from a device driver's .resume() routine, it will timeout and eventually
+fail, because the user land process that should respond to the request is frozen
+at this point.  So, seemingly, the failure is due to the freezing of tasks.
+Suppose, however, that the firmware file is located on a filesystem accessible
+only through another device that hasn't been resumed yet.  In that case,
+request_firmware() will fail regardless of whether or not the freezing of tasks
+is used.  Consequently, the problem is not really related to the freezing of
+tasks, since it generally exists anyway.  [The solution to this particular
+problem is to keep the firmware in memory after it's loaded for the first time
+and upload if from memory to the device whenever necessary.]
diff --git a/Documentation/power/kernel_threads.txt b/Documentation/power/kernel_threads.txt
deleted file mode 100644
index fb57784..0000000
--- a/Documentation/power/kernel_threads.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-KERNEL THREADS
-
-
-Freezer
-
-Upon entering a suspended state the system will freeze all
-tasks. This is done by delivering pseudosignals. This affects
-kernel threads, too. To successfully freeze a kernel thread
-the thread has to check for the pseudosignal and enter the
-refrigerator. Code to do this looks like this:
-
-	do {
-		hub_events();
-		wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
-		try_to_freeze();
-	} while (!signal_pending(current));
-
-from drivers/usb/core/hub.c::hub_thread()
-
-
-The Unfreezable
-
-Some kernel threads however, must not be frozen. The kernel must
-be able to finish pending IO operations and later on be able to
-write the memory image to disk. Kernel threads needed to do IO
-must stay awake. Such threads must mark themselves unfreezable
-like this:
-
-	/*
-	 * This thread doesn't need any user-level access,
-	 * so get rid of all our resources.
-	 */
-	daemonize("usb-storage");
-
-	current->flags |= PF_NOFREEZE;
-
-from drivers/usb/storage/usb.c::usb_stor_control_thread()
-
-Such drivers are themselves responsible for staying quiet during
-the actual snapshotting.
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 152b510..aea7e92 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -140,21 +140,11 @@
 website, and not to the Linux Kernel Mailing List. We are working
 toward merging suspend2 into the mainline kernel.
 
-Q: A kernel thread must voluntarily freeze itself (call 'refrigerator').
-I found some kernel threads that don't do it, and they don't freeze
-so the system can't sleep. Is this a known behavior?
+Q: What is the freezing of tasks and why are we using it?
 
-A: All such kernel threads need to be fixed, one by one. Select the
-place where the thread is safe to be frozen (no kernel semaphores
-should be held at that point and it must be safe to sleep there), and
-add:
-
-       try_to_freeze();
-
-If the thread is needed for writing the image to storage, you should
-instead set the PF_NOFREEZE process flag when creating the thread (and
-be very careful).
-
+A: The freezing of tasks is a mechanism by which user space processes and some
+kernel threads are controlled during hibernation or system-wide suspend (on some
+architectures).  See freezing-of-tasks.txt for details.
 
 Q: What is the difference between "platform" and "shutdown"?
 
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index d42d981..0c24348 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -42,15 +42,16 @@
     1) Defining child nodes of an SOC
     2) Representing devices without a current OF specification
       a) MDIO IO device
-      c) PHY nodes
       b) Gianfar-compatible ethernet nodes
+      c) PHY nodes
       d) Interrupt controllers
       e) I2C
       f) Freescale SOC USB controllers
       g) Freescale SOC SEC Security Engines
       h) Board Control and Status (BCSR)
       i) Freescale QUICC Engine module (QE)
-      g) Flash chip nodes
+      j) Flash chip nodes
+      k) Global Utilities Block
 
   VII - Specifying interrupt information for devices
     1) interrupts property
@@ -626,6 +627,14 @@
 a list of properties, a list of child nodes, and an end token. Every
 child node is a full node structure itself as defined above.
 
+NOTE: The above definition requires that all property definitions for
+a particular node MUST precede any subnode definitions for that node.
+Although the structure would not be ambiguous if properties and
+subnodes were intermingled, the kernel parser requires that the
+properties come first (up until at least 2.6.22).  Any tools
+manipulating a flattened tree must take care to preserve this
+constraint.
+
 4) Device tree "strings" block
 
 In order to save space, property names, which are generally redundant,
@@ -1782,6 +1791,33 @@
  		partition-names = "fs\0firmware";
  	};
 
+   k) Global Utilities Block
+
+   The global utilities block controls power management, I/O device
+   enabling, power-on-reset configuration monitoring, general-purpose
+   I/O signal configuration, alternate function selection for multiplexed
+   signals, and clock control.
+
+   Required properties:
+
+    - compatible : Should define the compatible device type for
+      global-utilities.
+    - reg : Offset and length of the register set for the device.
+
+  Recommended properties:
+
+    - fsl,has-rstcr : Indicates that the global utilities register set
+      contains a functioning "reset control register" (i.e. the board
+      is wired to reset upon setting the HRESET_REQ bit in this register).
+
+    Example:
+
+	global-utilities@e0000 {	/* global utilities block */
+		compatible = "fsl,mpc8548-guts";
+		reg = <e0000 1000>;
+		fsl,has-rstcr;
+	};
+
    More devices will be defined as this spec matures.
 
 VII - Specifying interrupt information for devices
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 7c701b8..c931d61 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -385,7 +385,7 @@
 		/* not all RTCs support periodic IRQs */
 		if (errno == ENOTTY) {
 			fprintf(stderr, "\nNo periodic IRQ support\n");
-			return 0;
+			goto done;
 		}
 		perror("RTC_IRQP_READ ioctl");
 		exit(errno);
diff --git a/Documentation/sound/oss/AD1816 b/Documentation/sound/oss/AD1816
deleted file mode 100644
index 14bd8f2..0000000
--- a/Documentation/sound/oss/AD1816
+++ /dev/null
@@ -1,84 +0,0 @@
-Documentation for the AD1816(A) sound driver
-============================================
-
-Installation:
--------------
-
-To get your AD1816(A) based sound card work, you'll have to enable support for
-experimental code ("Prompt for development and/or incomplete code/drivers")
-and isapnp ("Plug and Play support", "ISA Plug and Play support"). Enable
-"Sound card support", "OSS modules support" and "Support for AD1816(A) based
-cards (EXPERIMENTAL)" in the sound configuration menu, too. Now build, install
-and reboot the new kernel as usual.
-
-Features:
----------
-
-List of features supported by this driver:
-- full-duplex support
-- supported audio formats: unsigned 8bit, signed 16bit little endian, 
-                           signed 16bit big endian, µ-law, A-law
-- supported channels: mono and stereo
-- supported recording sources: Master, CD, Line, Line1, Line2, Mic
-- supports phat 3d stereo circuit (Line 3)
-
-
-Supported cards:
-----------------
-
-The following cards are known to work with this driver:
-- Terratec Base 1 
-- Terratec Base 64 
-- HP Kayak 
-- Acer FX-3D
-- SY-1816 
-- Highscreen Sound-Boostar 32 Wave 3D
-- Highscreen Sound-Boostar 16 
-- AVM Apex Pro card 
-- (Aztech SC-16 3D) 
-- (Newcom SC-16 3D) 
-- (Terratec EWS64S) 
-
-Cards listed in brackets are not supported reliable. If you have such a card 
-you should add the extra parameter:
-  options=1
-when loading the ad1816 module via modprobe. 
-
-
-Troubleshooting:
-----------------
-
-First of all you should check, if the driver has been loaded
-properly.
-
-If loading of the driver succeeds, but playback/capture fails, check
-if you used the correct values for irq, dma and dma2 when loading the module.
-If one of them is wrong you usually get the following error message:
-
-Nov  6 17:06:13 tek01 kernel: Sound: DMA (output) timed out - IRQ/DRQ config error?
-
-If playback/capture is too fast or to slow, you should have a look at
-the clock chip of your sound card. The AD1816 was designed for a 33MHz
-oscillator, however most sound card manufacturer use slightly
-different oscillators as they are cheaper than 33MHz oscillators. If
-you have such a card you have to adjust the ad1816_clockfreq parameter
-above. For example: For a card using a 32.875MHz oscillator use
-ad1816_clockfreq=32875 instead of ad1816_clockfreq=33000.
-
-
-Updates, bugfixes and bugreports:
---------------------------------
-
-As the driver is still experimental and under development, you should
-watch out for updates.  Updates of the driver are available on the
-Internet from one of my home pages:
-  http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
-or:
-  http://www.tu-darmstadt.de/~tek01/projects/linux.html
-
-Bugreports, bugfixes and related questions should be sent via E-Mail to:
-  tek@rbg.informatik.tu-darmstadt.de
-
-Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
-Christoph Hellwig <hch@infradead.org>
-	Last modified: 2000/09/20
diff --git a/Documentation/sound/oss/NM256 b/Documentation/sound/oss/NM256
deleted file mode 100644
index b503217..0000000
--- a/Documentation/sound/oss/NM256
+++ /dev/null
@@ -1,280 +0,0 @@
-=======================================================
-Documentation for the NeoMagic 256AV/256ZX sound driver
-=======================================================
-
-You're looking at version 1.1 of the driver.  (Woohoo!) It has been
-successfully tested against the following laptop models:
-
-	Sony Z505S/Z505SX/Z505DX/Z505RX
-	Sony F150, F160, F180, F250, F270, F280, PCG-F26
-	Dell Latitude CPi, CPt (various submodels)
-
-There are a few caveats, which is why you should read the entirety of
-this document first.
-
-This driver was developed without any support or assistance from
-NeoMagic.  There is no warranty, expressed, implied, or otherwise.  It
-is free software in the public domain; feel free to use it, sell it,
-give it to your best friends, even claim that you wrote it (but why?!)
-but don't go whining to me, NeoMagic, Sony, Dell, or anyone else
-when it blows up your computer.
-
-Version 1.1 contains a change to try and detect non-AC97 versions of
-the hardware, and not install itself appropriately.  It should also
-reinitialize the hardware on an APM resume event, assuming that APM
-was configured into your kernel.
-
-============
-Installation
-============
-
-Enable the sound drivers, the OSS sound drivers, and then the NM256
-driver.  The NM256 driver *must* be configured as a module (it won't
-give you any other choice).
-
-Next, do the usual "make modules" and "make modules_install".
-Finally, insmod the soundcore, sound and nm256 modules.
-
-When the nm256 driver module is loaded, you should see a couple of
-confirmation messages in the kernel logfile indicating that it found
-the device (the device does *not* use any I/O ports or DMA channels).
-Now try playing a wav file, futz with the CD-ROM if you have one, etc.
-
-The NM256 is entirely a PCI-based device, and all the necessary
-information is automatically obtained from the card.  It can only be
-configured as a module in a vain attempt to prevent people from
-hurting themselves.  It works correctly if it shares an IRQ with
-another device (it normally shares IRQ 9 with the builtin eepro100
-ethernet on the Sony Z505 laptops). 
-
-It does not run the card in any sort of compatibility mode. It will
-not work on laptops that have the SB16-compatible, AD1848-compatible
-or CS4232-compatible codec/mixer; you will want to use the appropriate
-compatible OSS driver with these chipsets.  I cannot provide any
-assistance with machines using the SB16, AD1848 or CS4232 compatible
-versions.  (The driver now attempts to detect the mixer version, and
-will refuse to load if it believes the hardware is not
-AC97-compatible.)
-
-The sound support is very basic, but it does include simultaneous
-playback and record capability.  The mixer support is also quite
-simple, although this is in keeping with the rather limited
-functionality of the chipset.
-
-There is no hardware synthesizer available, as the Losedows OPL-3 and
-MIDI support is done via hardware emulation.
-
-Only three recording devices are available on the Sony: the
-microphone, the CD-ROM input, and the volume device (which corresponds
-to the stereo output).  (Other devices may be available on other
-models of laptops.)  The Z505 series does not have a builtin CD-ROM,
-so of course the CD-ROM input doesn't work.  It does work on laptops
-with a builtin CD-ROM drive.
-
-The mixer device does not appear to have any tone controls, at least
-on the Z505 series.  The mixer module checks for tone controls in the
-AC97 mixer, and will enable them if they are available.
-
-==============
-Known problems
-==============
-
-  * There are known problems with PCMCIA cards and the eepro100 ethernet 
-    driver on the Z505S/Z505SX/Z505DX.  Keep reading.
-
-  * There are also potential problems with using a virtual X display, and
-    also problems loading the module after the X server has been started. 
-    Keep reading.
-
-  * The volume control isn't anywhere near linear.  Sorry.  This will be
-    fixed eventually, when I get sufficiently annoyed with it.  (I doubt
-    it will ever be fixed now, since I've never gotten sufficiently
-    annoyed with it and nobody else seems to care.)
-
-  * There are reports that the CD-ROM volume is very low.  Since I do not
-    have a CD-ROM equipped laptop, I cannot test this (it's kinda hard to
-    do remotely).
-
-  * Only 8 fixed-rate speeds are supported.  This is mainly a chipset
-    limitation.  It may be possible to support other speeds in the future.
-
-  * There is no support for the telephone mixer/codec.  There is support
-    for a phonein/phoneout device in the mixer driver;  whether or not 
-    it does anything is anyone's guess.  (Reports on this would be
-    appreciated.  You'll have to figure out how to get the phone to
-    go off-hook before it'll work, tho.)
-
-  * This driver was not written with any cooperation or support from
-    NeoMagic.  If you have any questions about this, see their website
-    for their official stance on supporting open source drivers.
-
-============
-Video memory
-============
-
-The NeoMagic sound engine uses a portion of the display memory to hold
-the sound buffer.  (Crazy, eh?)  The NeoMagic video BIOS sets up a
-special pointer at the top of video RAM to indicate where the top of
-the audio buffer should be placed.
-
-At the present time XFree86 is apparently not aware of this.  It will
-thus write over either the pointer or the sound buffer with abandon.
-(Accelerated-X seems to do a better job here.)
-
-This implies a few things:
-
-  * Sometimes the NM256 driver has to guess at where the buffer 
-    should be placed, especially if the module is loaded after the
-    X server is started.  It's usually correct, but it will consistently
-    fail on the Sony F250.
-
-  * Virtual screens greater than 1024x768x16 under XFree86 are
-    problematic on laptops with only 2.5MB of screen RAM. This
-    includes all of the 256AV-equipped laptops.  (Virtual displays
-    may or may not work on the 256ZX, which has at least 4MB of
-    video RAM.)
-
-If you start having problems with random noise being output either
-constantly (this is the usual symptom on the F250), or when windows
-are moved around (this is the usual symptom when using a virtual
-screen), the best fix is to
-
-  * Don't use a virtual frame buffer.
-  * Make sure you load the NM256 module before the X server is
-    started.
-
-On the F250, it is possible to force the driver to load properly even
-after the XFree86 server is started by doing:
-
-	insmod nm256 buffertop=0x25a800
-
-This forces the audio buffers to the correct offset in screen RAM.
-
-One user has reported a similar problem on the Sony F270, although
-others apparently aren't seeing any problems.  His suggested command
-is
-
-	insmod nm256 buffertop=0x272800
-
-=================
-Official WWW site
-=================
-
-The official site for the NM256 driver is:
-
-	http://www.uglx.org/sony.html
-
-You should always be able to get the latest version of the driver there,
-and the driver will be supported for the foreseeable future.
-
-==============
-Z505RX and IDE
-==============
-
-There appears to be a problem with the IDE chipset on the Z505RX; one
-of the symptoms is that sound playback periodically hangs (when the
-disk is accessed).  The user reporting the problem also reported that
-enabling all of the IDE chipset workarounds in the kernel solved the
-problem, tho obviously only one of them should be needed--if someone
-can give me more details I would appreciate it.
-
-==============================
-Z505S/Z505SX on-board Ethernet
-==============================
-
-If you're using the on-board Ethernet Pro/100 ethernet support on the Z505
-series, I strongly encourage you to download the latest eepro100 driver from
-Donald Becker's site:
-
-	ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/test/eepro100.c
-
-There was a reported problem on the Z505SX that if the ethernet
-interface is disabled and reenabled while the sound driver is loaded,
-the machine would lock up.  I have included a workaround that is
-working satisfactorily.  However, you may occasionally see a message
-about "Releasing interrupts, over 1000 bad interrupts" which indicates
-that the workaround is doing its job.
-
-==================================
-PCMCIA and the Z505S/Z505SX/Z505DX
-==================================
-
-There is also a known problem with the Sony Z505S and Z505SX hanging
-if a PCMCIA card is inserted while the ethernet driver is loaded, or
-in some cases if the laptop is suspended.  This is caused by tons of
-spurious IRQ 9s, probably generated from the PCMCIA or ACPI bridges.
-
-There is currently no fix for the problem that works in every case.
-The only known workarounds are to disable the ethernet interface
-before inserting or removing a PCMCIA card, or with some cards
-disabling the PCMCIA card before ejecting it will also help the
-problem with the laptop hanging when the card is ejected.
-
-One user has reported that setting the tcic's cs_irq to some value
-other than 9 (like 11) fixed the problem.  This doesn't work on my
-Z505S, however--changing the value causes the cardmgr to stop seeing
-card insertions and removals, cards don't seem to work correctly, and
-I still get hangs if a card is inserted when the kernel is booted.
-
-Using the latest ethernet driver and pcmcia package allows me to
-insert an Adaptec 1480A SlimScsi card without the laptop hanging,
-although I still have to shut down the card before ejecting or
-powering down the laptop.  However, similar experiments with a DE-660
-ethernet card still result in hangs when the card is inserted.  I am
-beginning to think that the interrupts are CardBus-related, since the
-Adaptec card is a CardBus card, and the DE-660 is not; however, I
-don't have any other CardBus cards to test with.
-
-======
-Thanks
-======
-
-First, I want to thank everyone (except NeoMagic of course) for their
-generous support and encouragement.  I'd like to list everyone's name
-here that replied during the development phase, but the list is
-amazingly long.
-
-I will be rather unfair and single out a few people, however:
-
-	Justin Maurer, for being the first random net.person to try it,
-	and for letting me login to his Z505SX to get it working there
-
-	Edi Weitz for trying out several different versions, and giving
-	me a lot of useful feedback
-
-	Greg Rumple for letting me login remotely to get the driver 
-	functional on the 256ZX, for his assistance on tracking
-	down all sorts of random stuff, and for trying out Accel-X
-
-	Zach Brown, for the initial AC97 mixer interface design
-
-	Jeff Garzik, for various helpful suggestions on the AC97
-	interface
-
-	"Mr. Bumpy" for feedback on the Z505RX
-
-	Bill Nottingham, for generous assistance in getting the mixer ID
-	code working
-
-=================
-Previous versions
-=================
-
-Versions prior to 0.3 (aka `noname') had problems with weird artifacts
-in the output and failed to set the recording rate properly.  These
-problems have long since been fixed.
-
-Versions prior to 0.5 had problems with clicks in the output when
-anything other than 16-bit stereo sound was being played, and also had
-periodic clicks when recording.
-
-Version 0.7 first incorporated support for the NM256ZX chipset, which
-is found on some Dell Latitude laptops (the CPt, and apparently
-some CPi models as well).  It also included the generic AC97
-mixer module.
-
-Version 0.75 renamed all the functions and files with slightly more
-generic names.
-
-Note that previous versions of this document claimed that recording was
-8-bit only; it actually has been working for 16-bits all along.
diff --git a/Documentation/sound/oss/OPL3-SA2 b/Documentation/sound/oss/OPL3-SA2
deleted file mode 100644
index d8b6d2b..0000000
--- a/Documentation/sound/oss/OPL3-SA2
+++ /dev/null
@@ -1,210 +0,0 @@
-Documentation for the OPL3-SA2, SA3, and SAx driver (opl3sa2.o)
----------------------------------------------------------------
-
-Scott Murray, scott@spiteful.org
-January 7, 2001
-
-NOTE: All trade-marked terms mentioned below are properties of their
-      respective owners.
-
-
-Supported Devices
------------------
-
-This driver is for PnP soundcards based on the following Yamaha audio
-controller chipsets:
-
-YMF711 aka OPL3-SA2
-YMF715 and YMF719 aka OPL3-SA3
-
-Up until recently (December 2000), I'd thought the 719 to be a
-different chipset, the OPL3-SAx.  After an email exhange with
-Yamaha, however, it turns out that the 719 is just a re-badged
-715, and the chipsets are identical.  The chipset detection code
-has been updated to reflect this.
-
-Anyways, all of these chipsets implement the following devices:
-
-OPL3 FM synthesizer
-Soundblaster Pro
-Microsoft/Windows Sound System
-MPU401 MIDI interface
-
-Note that this driver uses the MSS device, and to my knowledge these
-chipsets enforce an either/or situation with the Soundblaster Pro
-device and the MSS device.  Since the MSS device has better
-capabilities, I have implemented the driver to use it.
-
-
-Mixer Channels
---------------
-
-Older versions of this driver (pre-December 2000) had two mixers,
-an OPL3-SA2 or SA3 mixer and a MSS mixer.  The OPL3-SA[23] mixer
-device contained a superset of mixer channels consisting of its own
-channels and all of the MSS mixer channels.  To simplify the driver
-considerably, and to partition functionality better, the OPL3-SA[23]
-mixer device now contains has its own specific mixer channels.  They
-are:
-
-Volume     - Hardware master volume control
-Bass       - SA3 only, now supports left and right channels
-Treble     - SA3 only, now supports left and right channels
-Microphone - Hardware microphone input volume control
-Digital1   - Yamaha 3D enhancement "Wide" mixer
-
-All other mixer channels (e.g. "PCM", "CD", etc.) now have to be
-controlled via the "MS Sound System (CS4231)" mixer.  To facilitate
-this, the mixer device creation order has been switched so that
-the MSS mixer is created first.  This allows accessing the majority
-of the useful mixer channels even via single mixer-aware tools
-such as "aumix".
-
-
-Plug 'n Play
-------------
-
-In previous kernels (2.2.x), some configuration was required to
-get the driver to talk to the card.  Being the new millennium and
-all, the 2.4.x kernels now support auto-configuration if ISA PnP
-support is configured in.  Theoretically, the driver even supports
-having more than one card in this case.
-
-With the addition of PnP support to the driver, two new parameters
-have been added to control it:
-
-isapnp   - set to 0 to disable ISA PnP card detection
-
-multiple - set to 0 to disable multiple PnP card detection
-
-
-Optional Parameters
--------------------
-
-Recent (December 2000) additions to the driver (based on a patch
-provided by Peter Englmaier) are two new parameters:
-
-ymode -    Set Yamaha 3D enhancement mode:
-           0 = Desktop/Normal  5-12 cm speakers
-           1 = Notebook PC (1) 3 cm speakers
-           2 = Notebook PC (2) 1.5 cm speakers
-           3 = Hi-Fi           16-38 cm speakers
-
-loopback - Set A/D input source. Useful for echo cancellation:
-           0 = Mic Right channel (default)
-           1 = Mono output loopback
-
-The ymode parameter has been tested and does work.  The loopback
-parameter, however, is untested.  Any feedback on its usefulness
-would be appreciated.
-
-
-Manual Configuration
---------------------
-
-If for some reason you decide not to compile ISA PnP support into
-your kernel, or disabled the driver's usage of it by setting the
-isapnp parameter as discussed above, then you will need to do some
-manual configuration.  There are two ways of doing this.  The most
-common is to use the isapnptools package to initialize the card, and
-use the kernel module form of the sound subsystem and sound drivers.
-Alternatively, some BIOS's allow manual configuration of installed
-PnP devices in a BIOS menu, which should allow using the non-modular
-sound drivers, i.e. built into the kernel.
-
-I personally use isapnp and modules, and do not have access to a PnP
-BIOS machine to test.  If you have such a beast, configuring the
-driver to be built into the kernel should just work (thanks to work
-done by David Luyer <luyer@ucs.uwa.edu.au>).  You will still need
-to specify settings, which can be done by adding:
-
-opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>
-
-to the kernel command line.  For example:
-
-opl3sa2=0x370,5,0,1,0x530,0x330
-
-If you are instead using the isapnp tools (as most people have been
-before Linux 2.4.x), follow the directions in their documentation to
-produce a configuration file.  Here is the relevant excerpt I used to
-use for my SA3 card from my isapnp.conf:
-
-(CONFIGURE YMH0800/-1 (LD 0
-
-# NOTE: IO 0 is for the unused SoundBlaster part of the chipset.
-(IO 0 (BASE 0x0220))
-(IO 1 (BASE 0x0530))
-(IO 2 (BASE 0x0388))
-(IO 3 (BASE 0x0330))
-(IO 4 (BASE 0x0370))
-(INT 0 (IRQ 5 (MODE +E)))
-(DMA 0 (CHANNEL 0))
-(DMA 1 (CHANNEL 1))
-
-Here, note that:
-
-Port  Acceptable Range  Purpose
-----  ----------------  -------
-IO 0  0x0220 - 0x0280   SB base address, unused.
-IO 1  0x0530 - 0x0F48   MSS base address
-IO 2  0x0388 - 0x03F8   OPL3 base address
-IO 3  0x0300 - 0x0334   MPU base address
-IO 4  0x0100 - 0x0FFE   card's own base address for its control I/O ports
-
-The IRQ and DMA values can be any that are considered acceptable for a
-MSS.  Assuming you've got isapnp all happy, then you should be able to
-do something like the following (which matches up with the isapnp
-configuration above):
-
-modprobe mpu401
-modprobe ad1848
-modprobe opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=5 dma=0 dma2=1
-modprobe opl3 io=0x388
-
-See the section "Automatic Module Loading" below for how to set up
-/etc/modprobe.conf to automate this.
-
-An important thing to remember that the opl3sa2 module's io argument is
-for it's own control port, which handles the card's master mixer for
-volume (on all cards), and bass and treble (on SA3 cards).
-
-
-Troubleshooting
----------------
-
-If all goes well and you see no error messages, you should be able to
-start using the sound capabilities of your system.  If you get an
-error message while trying to insert the opl3sa2 module, then make
-sure that the values of the various arguments match what you specified
-in your isapnp configuration file, and that there is no conflict with
-another device for an I/O port or interrupt.  Checking the contents of
-/proc/ioports and /proc/interrupts can be useful to see if you're
-butting heads with another device.
-
-If you still cannot get the module to load, look at the contents of
-your system log file, usually /var/log/messages.  If you see the
-message "opl3sa2: Unknown Yamaha audio controller version", then you
-have a different chipset version than I've encountered so far.  Look
-for all messages in the log file that start with "opl3sa2: " and see
-if they provide any clues.  If you do not see the chipset version
-message, and none of the other messages present in the system log are
-helpful, email me some details and I'll try my best to help.
-
-
-Automatic Module Loading
-------------------------
-
-Lastly, if you're using modules and want to set up automatic module
-loading with kmod, the kernel module loader, here is the section I
-currently use in my modprobe.conf file:
-
-# Sound
-alias sound-slot-0 opl3sa2
-options opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=7 dma=0 dma2=3
-options opl3 io=0x388
-
-That's all it currently takes to get an OPL3-SA3 card working on my
-system.  Once again, if you have any other problems, email me at the
-address listed above.
-
-Scott
diff --git a/Documentation/sound/oss/VIA-chipset b/Documentation/sound/oss/VIA-chipset
deleted file mode 100644
index 3786523..0000000
--- a/Documentation/sound/oss/VIA-chipset
+++ /dev/null
@@ -1,43 +0,0 @@
-Running sound cards on VIA chipsets
-
-o	There are problems with VIA chipsets and sound cards that appear to
-	lock the hardware solidly. Test programs under DOS have verified the
-	problem exists on at least some (but apparently not all) VIA boards
-
-o	VIA have so far failed to bother to answer support mail on the subject
-	so if you are a VIA engineer feeling aggrieved as you read this 
-	document go chase your own people. If there is a workaround please
-	let us know so we can implement it.
-
-
-Certain patterns of ISA DMA access used for most PC sound cards cause the
-VIA chipsets to lock up. From the collected reports this appears to cover a
-wide range of boards. Some also lock up with sound cards under Win* as well.
-
-Linux implements a workaround providing your chipset is PCI and you compiled
-with PCI Quirks enabled. If so you will see a message
-	"Activating ISA DMA bug workarounds"
-
-during booting. If you have a VIA PCI chipset that hangs when you use the
-sound and is not generating this message even with PCI quirks enabled
-please report the information to the linux-kernel list (see REPORTING-BUGS).
-
-If you are one of the tiny number of unfortunates with a 486 ISA/VLB VIA
-chipset board you need to do the following to build a special kernel for
-your board
-
-	edit linux/include/asm-i386/dma.h
-
-change
-
-#define isa_dma_bridge_buggy 	(0)
-
-to
-
-#define isa_dma_bridge_buggy 	(1)
-
-and rebuild a kernel without PCI quirk support.
-
-
-Other than this particular glitch the VIA [M]VP* chipsets appear to work
-perfectly with Linux.
diff --git a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx
deleted file mode 100644
index b544327..0000000
--- a/Documentation/sound/oss/cs46xx
+++ /dev/null
@@ -1,138 +0,0 @@
-
-Documentation for the Cirrus Logic/Crystal SoundFusion cs46xx/cs4280 audio 
-controller chips (2001/05/11)
-
-The cs46xx audio driver supports the DSP line of Cirrus controllers. 
-Specifically, the cs4610, cs4612, cs4614, cs4622, cs4624, cs4630 and the cs4280
-products.  This driver uses the generic ac97_codec driver for AC97 codec
-support.  
-
-
-Features:
-
-Full Duplex Playback/Capture supported from 8k-48k.
-16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
-
-APM/PM - 2.2.x PM is enabled and functional. APM can also
-be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
-definition.
-
-DMA playback buffer size is configurable from 16k (defaultorder=2) up to 2Meg 
-(defaultorder=11).  DMA capture buffer size is fixed at a single 4k page as
-two 2k fragments.
-
-MMAP seems to work well with QuakeIII, and test XMMS plugin.
-
-Myth2 works, but the polling logic is not fully correct, but is functional.
-
-The 2.4.4-ac6 gameport code in the cs461x joystick driver has been tested 
-with a Microsoft Sidewinder joystick (cs461x.o and sidewinder.o).  This 
-audio driver must be loaded prior to the joystick driver to enable the
-DSP task image supporting the joystick device.
-
-
-Limitations:
-
-SPDIF is currently not supported.
-
-Primary codec support only.  No secondary codec support is implemented.
-
-
-
-NOTES:
-
-Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
-and has been tested.
-Module parameter hercules_egpio_disable set to 1, will force a 0 to EGPIODR
-to disable the external amplifier.
-
-VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
-the external amplifier for the "back" speakers, since we do not
-support the secondary codec then this external amp is not
-turned on.  The primary codec external amplifier is supported but
-note that the AC97 EAPD bit is inverted logic (amp_voyetra()).
-
-DMA buffer size - there are issues with many of the Linux applications
-concerning the optimal buffer size.  Several applications request a 
-certain fragment size and number and then do not verify that the driver
-has the ability to support the requested configuration.  
-SNDCTL_DSP_SETFRAGMENT ioctl is used to request a fragment size and
-number of fragments.  Some applications exit if an error is returned
-on this particular ioctl. Therefore, in alignment with the other OSS audio 
-drivers, no error is returned when a SETFRAGs IOCTL is received, but the 
-values passed from the app are not used in any buffer calculation 
-(ossfragshift/ossmaxfrags are not used).
-Use the "defaultorder=N" module parameter to change the buffer size if
-you have an application that requires a specific number of fragments
-or a specific buffer size (see below).
-
-Debug Interface
----------------
-There is an ioctl debug interface to allow runtime modification of the 
-debug print levels.  This debug interface code can be disabled from the 
-compilation process with commenting the following define:
-#define CSDEBUG_INTERFACE 1
-There is also a debug print methodolgy to select printf statements from
-different areas of the driver.  A debug print level is also used to allow
-additional printfs to be active.  Comment out the following line in the
-driver to disable compilation of the CS_DBGOUT print statements:
-#define CSDEBUG 1
- 
-Please see the definitions for cs_debuglevel and cs_debugmask for additional
-information on the debug levels and sections.
-
-There is also a csdbg executable to allow runtime manipulation of these 
-parameters.  for a copy email: twoller@crystal.cirrus.com
-
-
-
-MODULE_PARMS definitions
-------------------------
-module_param(defaultorder, ulong, 0);
-defaultorder=N
-where N is a value from 1 to 12
-The buffer order determines the size of the dma buffer for the driver.
-under Linux, a smaller buffer allows more responsiveness from many of the 
-applications (e.g. games).  A larger buffer allows some of the apps (esound) 
-to not underrun the dma buffer as easily.  As default, use 32k (order=3)
-rather than 64k as some of the games work more responsively.
-(2^N) * PAGE_SIZE = allocated buffer size
-
-module_param(cs_debuglevel, ulong, 0644);
-module_param(cs_debugmask, ulong, 0644);
-cs_debuglevel=N
-cs_debugmask=0xMMMMMMMM
-where N is a value from 0 (no debug printfs), to 9 (maximum)
-0xMMMMMMMM is a debug mask corresponding to the CS_xxx bits (see driver source).
-
-module_param(hercules_egpio_disable, ulong, 0);
-hercules_egpio_disable=N
-where N is a 0 (enable egpio), or a 1 (disable egpio support)
-
-module_param(initdelay, ulong, 0);
-initdelay=N
-This value is used to determine the millescond delay during the initialization
-code prior to powering up the PLL.  On laptops this value can be used to
-assist with errors on resume, mostly with IBM laptops.  Basically, if the 
-system is booted under battery power then the mdelay()/udelay() functions fail to 
-properly delay the required time.  Also, if the system is booted under AC power
-and then the power removed, the mdelay()/udelay() functions will not delay properly.
- 
-module_param(powerdown, ulong, 0);
-powerdown=N
-where N is 0 (disable any powerdown of the internal blocks) or 1 (enable powerdown)
-
-
-module_param(external_amp, bool, 0);
-external_amp=1
-if N is set to 1, then force enabling the EAPD support in the primary AC97 codec.
-override the detection logic and force the external amp bit in the AC97 0x26 register
-to be reset (0).  EAPD should be 0 for powerup, and 1 for powerdown.  The VTB Santa Cruz
-card has inverted logic, so there is a special function for these cards.
-
-module_param(thinkpad, bool, 0);
-thinkpad=1
-if N is set to 1, then force enabling the clkrun functionality.
-Currently, when the part is being used, then clkrun is disabled for the entire system,
-but re-enabled when the driver is released or there is no outstanding open count.
-
diff --git a/Documentation/spi/spi-lm70llp b/Documentation/spi/spi-lm70llp
new file mode 100644
index 0000000..154bd02
--- /dev/null
+++ b/Documentation/spi/spi-lm70llp
@@ -0,0 +1,69 @@
+spi_lm70llp :  LM70-LLP parport-to-SPI adapter
+==============================================
+
+Supported board/chip:
+  * National Semiconductor LM70 LLP evaluation board
+    Datasheet: http://www.national.com/pf/LM/LM70.html
+
+Author:
+        Kaiwan N Billimoria <kaiwan@designergraphix.com>
+
+Description
+-----------
+This driver provides glue code connecting a National Semiconductor LM70 LLP
+temperature sensor evaluation board to the kernel's SPI core subsystem.
+
+In effect, this driver turns the parallel port interface on the eval board
+into a SPI bus with a single device, which will be driven by the generic
+LM70 driver (drivers/hwmon/lm70.c).
+
+The hardware interfacing on the LM70 LLP eval board is as follows:
+
+   Parallel                 LM70 LLP
+     Port      Direction   JP2 Header
+   ----------- --------- ----------------
+      D0     2      -         -
+      D1     3     -->      V+   5
+      D2     4     -->      V+   5
+      D3     5     -->      V+   5
+      D4     6     -->      V+   5
+      D5     7     -->      nCS  8
+      D6     8     -->      SCLK 3
+      D7     9     -->      SI/O 5
+     GND    25      -       GND  7
+    Select  13     <--      SI/O 1
+   ----------- --------- ----------------
+
+Note that since the LM70 uses a "3-wire" variant of SPI, the SI/SO pin
+is connected to both pin D7 (as Master Out) and Select (as Master In)
+using an arrangment that lets either the parport or the LM70 pull the
+pin low.  This can't be shared with true SPI devices, but other 3-wire
+devices might share the same SI/SO pin.
+
+The bitbanger routine in this driver (lm70_txrx) is called back from
+the bound "hwmon/lm70" protocol driver through its sysfs hook, using a
+spi_write_then_read() call.  It performs Mode 0 (SPI/Microwire) bitbanging.
+The lm70 driver then inteprets the resulting digital temperature value
+and exports it through sysfs.
+
+A "gotcha": National Semiconductor's LM70 LLP eval board circuit schematic
+shows that the SI/O line from the LM70 chip is connected to the base of a
+transistor Q1 (and also a pullup, and a zener diode to D7); while the
+collector is tied to VCC.
+
+Interpreting this circuit, when the LM70 SI/O line is High (or tristate
+and not grounded by the host via D7), the transistor conducts and switches
+the collector to zero, which is reflected on pin 13 of the DB25 parport
+connector.  When SI/O is Low (driven by the LM70 or the host) on the other
+hand, the transistor is cut off and the voltage tied to it's collector is
+reflected on pin 13 as a High level.
+
+So: the getmiso inline routine in this driver takes this fact into account,
+inverting the value read at pin 13.
+
+
+Thanks to
+---------
+o David Brownell for mentoring the SPI-side driver development.
+o Dr.Craig Hollabaugh for the (early) "manual" bitbanging driver version.
+o Nadir Billimoria for help interpreting the circuit schematic.
diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt
index a661d68..471e753 100644
--- a/Documentation/spinlocks.txt
+++ b/Documentation/spinlocks.txt
@@ -1,7 +1,12 @@
-UPDATE March 21 2005 Amit Gud <gud@eth.net>
+SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and
+are hence deprecated.
 
-Macros SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated and will be
-removed soon. So for any new code dynamic initialization should be used:
+Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or
+__SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate for static
+initialization.
+
+Dynamic initialization, when necessary, may be performed as
+demonstrated below.
 
    spinlock_t xxx_lock;
    rwlock_t xxx_rw_lock;
@@ -15,12 +20,9 @@
 
    module_init(xxx_init);
 
-Reasons for deprecation
-  - it hurts automatic lock validators
-  - it becomes intrusive for the realtime preemption patches
-
-Following discussion is still valid, however, with the dynamic initialization
-of spinlocks instead of static.
+The following discussion is still valid, however, with the dynamic
+initialization of spinlocks or with DEFINE_SPINLOCK, etc., used
+instead of SPIN_LOCK_UNLOCKED.
 
 -----------------------
 
diff --git a/Documentation/sysctl/ctl_unnumbered.txt b/Documentation/sysctl/ctl_unnumbered.txt
new file mode 100644
index 0000000..23003a8
--- /dev/null
+++ b/Documentation/sysctl/ctl_unnumbered.txt
@@ -0,0 +1,22 @@
+
+Except for a few extremely rare exceptions user space applications do not use
+the binary sysctl interface.  Instead everyone uses /proc/sys/...  with
+readable ascii names.
+
+Recently the kernel has started supporting setting the binary sysctl value to
+CTL_UNNUMBERED so we no longer need to assign a binary sysctl path to allow
+sysctls to show up in /proc/sys.
+
+Assigning binary sysctl numbers is an endless source of conflicts in sysctl.h,
+breaking of the user space ABI (because of those conflicts), and maintenance
+problems.  A complete pass through all of the sysctl users revealed multiple
+instances where the sysctl binary interface was broken and had gone undetected
+for years.
+
+So please do not add new binary sysctl numbers.  They are unneeded and
+problematic.
+
+If you really need a new binary sysctl number please first merge your sysctl
+into the kernel and then as a separate patch allocate a binary sysctl number.
+
+(ebiederm@xmission.com, June 2007)
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 8cfca17..a0ccc5b 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -32,12 +32,14 @@
 - min_slab_ratio
 - panic_on_oom
 - mmap_min_address
+- numa_zonelist_order
 
 ==============================================================
 
 dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
 dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
-block_dump, swap_token_timeout, drop-caches:
+block_dump, swap_token_timeout, drop-caches,
+hugepages_treat_as_movable:
 
 See Documentation/filesystems/proc.txt
 
@@ -231,3 +233,47 @@
 vast majority of applications to work correctly and provide defense in depth
 against future potential kernel bugs.
 
+==============================================================
+
+numa_zonelist_order
+
+This sysctl is only for NUMA.
+'where the memory is allocated from' is controlled by zonelists.
+(This documentation ignores ZONE_HIGHMEM/ZONE_DMA32 for simple explanation.
+ you may be able to read ZONE_DMA as ZONE_DMA32...)
+
+In non-NUMA case, a zonelist for GFP_KERNEL is ordered as following.
+ZONE_NORMAL -> ZONE_DMA
+This means that a memory allocation request for GFP_KERNEL will
+get memory from ZONE_DMA only when ZONE_NORMAL is not available.
+
+In NUMA case, you can think of following 2 types of order.
+Assume 2 node NUMA and below is zonelist of Node(0)'s GFP_KERNEL
+
+(A) Node(0) ZONE_NORMAL -> Node(0) ZONE_DMA -> Node(1) ZONE_NORMAL
+(B) Node(0) ZONE_NORMAL -> Node(1) ZONE_NORMAL -> Node(0) ZONE_DMA.
+
+Type(A) offers the best locality for processes on Node(0), but ZONE_DMA
+will be used before ZONE_NORMAL exhaustion. This increases possibility of
+out-of-memory(OOM) of ZONE_DMA because ZONE_DMA is tend to be small.
+
+Type(B) cannot offer the best locality but is more robust against OOM of
+the DMA zone.
+
+Type(A) is called as "Node" order. Type (B) is "Zone" order.
+
+"Node order" orders the zonelists by node, then by zone within each node.
+Specify "[Nn]ode" for zone order
+
+"Zone Order" orders the zonelists by zone type, then by node within each
+zone.  Specify "[Zz]one"for zode order.
+
+Specify "[Dd]efault" to request automatic configuration.  Autoconfiguration
+will select "node" order in following case.
+(1) if the DMA zone does not exist or
+(2) if the DMA zone comprises greater than 50% of the available memory or
+(3) if any node's DMA zone comprises greater than 60% of its local memory and
+    the amount of local memory is big enough.
+
+Otherwise, "zone" order will be selected. Default order is recommended unless
+this is causing problems for your system/application.
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 687104b..51ccc48 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -77,8 +77,9 @@
 call, then it is required that system administrator mount a file system of
 type hugetlbfs:
 
-	mount none /mnt/huge -t hugetlbfs <uid=value> <gid=value> <mode=value>
-		 <size=value> <nr_inodes=value>
+  mount -t hugetlbfs \
+	-o uid=<value>,gid=<value>,mode=<value>,size=<value>,nr_inodes=<value> \
+	none /mnt/huge
 
 This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
 /mnt/huge.  Any files created on /mnt/huge uses hugepages.  The uid and gid
@@ -88,11 +89,10 @@
 By default the value 0755 is picked. The size option sets the maximum value of
 memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
 rounded down to HPAGE_SIZE.  The option nr_inodes sets the maximum number of
-inodes that /mnt/huge can use.  If the size or nr_inodes options are not
+inodes that /mnt/huge can use.  If the size or nr_inodes option is not
 provided on command line then no limits are set.  For size and nr_inodes
 options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
-example, size=2K has the same meaning as size=2048. An example is given at
-the end of this document.
+example, size=2K has the same meaning as size=2048.
 
 read and write system calls are not supported on files that reside on hugetlb
 file systems.
diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt
index 1523320..d17f324 100644
--- a/Documentation/vm/slub.txt
+++ b/Documentation/vm/slub.txt
@@ -41,6 +41,8 @@
 	P		Poisoning (object and padding)
 	U		User tracking (free and alloc)
 	T		Trace (please only use on single slabs)
+	-		Switch all debugging off (useful if the kernel is
+			configured with CONFIG_SLUB_DEBUG_ON)
 
 F.e. in order to boot just with sanity checks and red zoning one would specify:
 
@@ -125,13 +127,20 @@
 
 Here is a sample of slub debug output:
 
-*** SLUB kmalloc-8: Redzone Active@0xc90f6d20 slab 0xc528c530 offset=3360 flags=0x400000c3 inuse=61 freelist=0xc90f6d58
-  Bytes b4 0xc90f6d10:  00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
-    Object 0xc90f6d20:  31 30 31 39 2e 30 30 35                         1019.005
-   Redzone 0xc90f6d28:  00 cc cc cc                                     .
-FreePointer 0xc90f6d2c -> 0xc90f6d58
-Last alloc: get_modalias+0x61/0xf5 jiffies_ago=53 cpu=1 pid=554
-Filler 0xc90f6d50:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
+====================================================================
+BUG kmalloc-8: Redzone overwritten
+--------------------------------------------------------------------
+
+INFO: 0xc90f6d28-0xc90f6d2b. First byte 0x00 instead of 0xcc
+INFO: Slab 0xc528c530 flags=0x400000c3 inuse=61 fp=0xc90f6d58
+INFO: Object 0xc90f6d20 @offset=3360 fp=0xc90f6d58
+INFO: Allocated in get_modalias+0x61/0xf5 age=53 cpu=1 pid=554
+
+Bytes b4 0xc90f6d10:  00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
+  Object 0xc90f6d20:  31 30 31 39 2e 30 30 35                         1019.005
+ Redzone 0xc90f6d28:  00 cc cc cc                                     .
+ Padding 0xc90f6d50:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
+
   [<c010523d>] dump_trace+0x63/0x1eb
   [<c01053df>] show_trace_log_lvl+0x1a/0x2f
   [<c010601d>] show_trace+0x12/0x14
@@ -153,74 +162,108 @@
   [<c0104112>] sysenter_past_esp+0x5f/0x99
   [<b7f7b410>] 0xb7f7b410
   =======================
-@@@ SLUB kmalloc-8: Restoring redzone (0xcc) from 0xc90f6d28-0xc90f6d2b
 
+FIX kmalloc-8: Restoring Redzone 0xc90f6d28-0xc90f6d2b=0xcc
 
+If SLUB encounters a corrupted object (full detection requires the kernel
+to be booted with slub_debug) then the following output will be dumped
+into the syslog:
 
-If SLUB encounters a corrupted object then it will perform the following
-actions:
-
-1. Isolation and report of the issue
+1. Description of the problem encountered
 
 This will be a message in the system log starting with
 
-*** SLUB <slab cache affected>: <What went wrong>@<object address>
-offset=<offset of object into slab> flags=<slabflags>
-inuse=<objects in use in this slab> freelist=<first free object in slab>
+===============================================
+BUG <slab cache affected>: <What went wrong>
+-----------------------------------------------
 
-2. Report on how the problem was dealt with in order to ensure the continued
-operation of the system.
+INFO: <corruption start>-<corruption_end> <more info>
+INFO: Slab <address> <slab information>
+INFO: Object <address> <object information>
+INFO: Allocated in <kernel function> age=<jiffies since alloc> cpu=<allocated by
+	cpu> pid=<pid of the process>
+INFO: Freed in <kernel function> age=<jiffies since free> cpu=<freed by cpu>
+	 pid=<pid of the process>
 
-These are messages in the system log beginning with
+(Object allocation / free information is only available if SLAB_STORE_USER is
+set for the slab. slub_debug sets that option)
 
-@@@ SLUB <slab cache affected>: <corrective action taken>
+2. The object contents if an object was involved.
 
-
-In the above sample SLUB found that the Redzone of an active object has
-been overwritten. Here a string of 8 characters was written into a slab that
-has the length of 8 characters. However, a 8 character string needs a
-terminating 0. That zero has overwritten the first byte of the Redzone field.
-After reporting the details of the issue encountered the @@@ SLUB message
-tell us that SLUB has restored the redzone to its proper value and then
-system operations continue.
-
-Various types of lines can follow the @@@ SLUB line:
+Various types of lines can follow the BUG SLUB line:
 
 Bytes b4 <address> : <bytes>
-	Show a few bytes before the object where the problem was detected.
+	Shows a few bytes before the object where the problem was detected.
 	Can be useful if the corruption does not stop with the start of the
 	object.
 
 Object <address> : <bytes>
 	The bytes of the object. If the object is inactive then the bytes
-	typically contain poisoning values. Any non-poison value shows a
+	typically contain poison values. Any non-poison value shows a
 	corruption by a write after free.
 
 Redzone <address> : <bytes>
-	The redzone following the object. The redzone is used to detect
+	The Redzone following the object. The Redzone is used to detect
 	writes after the object. All bytes should always have the same
 	value. If there is any deviation then it is due to a write after
 	the object boundary.
 
-Freepointer
-	The pointer to the next free object in the slab. May become
-	corrupted if overwriting continues after the red zone.
+	(Redzone information is only available if SLAB_RED_ZONE is set.
+	slub_debug sets that option)
 
-Last alloc:
-Last free:
-	Shows the address from which the object was allocated/freed last.
-	We note the pid, the time and the CPU that did so. This is usually
-	the most useful information to figure out where things went wrong.
-	Here get_modalias() did an kmalloc(8) instead of a kmalloc(9).
-
-Filler <address> : <bytes>
+Padding <address> : <bytes>
 	Unused data to fill up the space in order to get the next object
 	properly aligned. In the debug case we make sure that there are
-	at least 4 bytes of filler. This allow for the detection of writes
+	at least 4 bytes of padding. This allows the detection of writes
 	before the object.
 
-Following the filler will be a stackdump. That stackdump describes the
-location where the error was detected. The cause of the corruption is more
-likely to be found by looking at the information about the last alloc / free.
+3. A stackdump
 
-Christoph Lameter, <clameter@sgi.com>, May 23, 2007
+The stackdump describes the location where the error was detected. The cause
+of the corruption is may be more likely found by looking at the function that
+allocated or freed the object.
+
+4. Report on how the problem was dealt with in order to ensure the continued
+operation of the system.
+
+These are messages in the system log beginning with
+
+FIX <slab cache affected>: <corrective action taken>
+
+In the above sample SLUB found that the Redzone of an active object has
+been overwritten. Here a string of 8 characters was written into a slab that
+has the length of 8 characters. However, a 8 character string needs a
+terminating 0. That zero has overwritten the first byte of the Redzone field.
+After reporting the details of the issue encountered the FIX SLUB message
+tell us that SLUB has restored the Redzone to its proper value and then
+system operations continue.
+
+Emergency operations:
+---------------------
+
+Minimal debugging (sanity checks alone) can be enabled by booting with
+
+	slub_debug=F
+
+This will be generally be enough to enable the resiliency features of slub
+which will keep the system running even if a bad kernel component will
+keep corrupting objects. This may be important for production systems.
+Performance will be impacted by the sanity checks and there will be a
+continual stream of error messages to the syslog but no additional memory
+will be used (unlike full debugging).
+
+No guarantees. The kernel component still needs to be fixed. Performance
+may be optimized further by locating the slab that experiences corruption
+and enabling debugging only for that cache
+
+I.e.
+
+	slub_debug=F,dentry
+
+If the corruption occurs by writing after the end of the object then it
+may be advisable to enable a Redzone to avoid corrupting the beginning
+of other objects.
+
+	slub_debug=FZ,dentry
+
+Christoph Lameter, <clameter@sgi.com>, May 30, 2007
diff --git a/MAINTAINERS b/MAINTAINERS
index 3914269..5abec14 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -194,13 +194,6 @@
 L:	linux-acenic@sunsite.dk
 S:	Maintained
 
-ACI MIXER DRIVER
-P:	Robert Siemer
-M:	Robert.Siemer@gmx.de
-L:	linux-sound@vger.kernel.org
-W:	http://www.stud.uni-karlsruhe.de/~uh1b/
-S:	Maintained
-
 IPS SCSI RAID DRIVER
 P:	Adaptec OEM Raid Solutions
 M:	aacraid@adaptec.com
@@ -272,21 +265,6 @@
 W:	http://acpi.sourceforge.net/
 S:	Supported
 
-AD1816 SOUND DRIVER
-P:	Thorsten Knabe
-M:	Thorsten Knabe <linux@thorsten-knabe.de>
-W:	http://linux.thorsten-knabe.de
-S:	Maintained
-
-AD1889 SOUND DRIVER
-P:	Kyle McMartin
-M:	kyle@parisc-linux.org
-P:	Thibaut Varene
-M:	T-Bone@parisc-linux.org
-W:	http://wiki.parisc-linux.org/AD1889
-L:	parisc-linux@lists.parisc-linux.org
-S:	Maintained
-
 ADM1025 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
@@ -1276,6 +1254,12 @@
 L:	netdev@vger.kernel.org
 S:	Maintained
 
+DMA GENERIC MEMCPY SUBSYSTEM
+P:	Shannon Nelson
+M:	shannon.nelson@intel.com
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 DOCBOOK FOR DOCUMENTATION
 P:	Randy Dunlap
 M:	rdunlap@xenotime.net
@@ -1398,13 +1382,6 @@
 L:	general@lists.openfabrics.org
 S:	Supported
 
-EMU10K1 SOUND DRIVER
-P:	James Courtier-Dutton
-M:	James@superbug.demon.co.uk
-L:	emu10k1-devel@lists.sourceforge.net
-W:	http://sourceforge.net/projects/emu10k1/
-S:	Maintained
-
 EMULEX LPFC FC SCSI DRIVER
 P:	James Smart
 M:	james.smart@emulex.com
@@ -1900,6 +1877,12 @@
 M:	tigran@aivazian.fsnet.co.uk
 S:	Maintained
 
+INTEL I/OAT DMA DRIVER
+P:	Shannon Nelson
+M:	shannon.nelson@intel.com
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+
 INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
 P:	Deepak Saxena
 M:	dsaxena@plexity.net
@@ -2297,6 +2280,14 @@
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
+M32R ARCHITECTURE
+P:	Hirokazu Takata
+M:	takata@linux-m32r.org
+L:	linux-m32r@ml.linux-m32r.org
+L:	linux-m32r-ja@ml.linux-m32r.org (in Japanese)
+W:	http://www.linux-m32r.org/
+S:	Maintained
+
 M68K ARCHITECTURE
 P:	Geert Uytterhoeven
 M:	geert@linux-m68k.org
@@ -2622,12 +2613,6 @@
 W:	http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
 S:	Maintained
 
-NON-IDE/NON-SCSI CDROM DRIVERS [GENERAL] (come on, crew - mark your responsibility)
-P:	Eberhard Moenkeberg
-M:	emoenke@gwdg.de
-L:	linux-kernel@vger.kernel.org
-S:	Maintained
-
 NTFS FILESYSTEM
 P:	Anton Altaparmakov
 M:	aia21@cantab.net
@@ -2710,12 +2695,6 @@
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
-OPL3-SA2, SA3, and SAx DRIVER
-P:	Zwane Mwaikambo
-M:	zwane@arm.linux.org.uk
-L:	linux-sound@vger.kernel.org
-S:	Maintained
-
 OPROFILE
 P:	Philippe Elie
 M:	phil.el@wanadoo.fr
@@ -3120,12 +3099,6 @@
 W:	http://www.mihu.de/linux/saa7146
 S:	Maintained
 
-SBPCD CDROM DRIVER
-P:	Eberhard Moenkeberg
-M:	emoenke@gwdg.de
-L:	linux-kernel@vger.kernel.org
-S:	Maintained
-
 SC1200 WDT DRIVER
 P:	Zwane Mwaikambo
 M:	zwane@arm.linux.org.uk
diff --git a/Makefile b/Makefile
index de4f8f7..ddbfcac 100644
--- a/Makefile
+++ b/Makefile
@@ -313,7 +313,8 @@
 CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-                   -fno-strict-aliasing -fno-common
+		   -fno-strict-aliasing -fno-common \
+		   -Werror-implicit-function-declaration
 AFLAGS          := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 0cd0605..83a7818 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -315,9 +315,7 @@
 	/* When I and D space are separate, this will have to be fixed.  */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		tmp = data;
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
-		ret = (copied == sizeof(tmp)) ? 0 : -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the specified register */
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 80cfb75..b287314 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -65,7 +65,7 @@
 };
 
 /* Set to a secondary's cpuid when it comes online.  */
-static int smp_secondary_alive __initdata = 0;
+static int smp_secondary_alive __devinitdata = 0;
 
 /* Which cpus ids came online.  */
 cpumask_t cpu_online_map;
@@ -173,7 +173,7 @@
 }
 
 /* Wait until hwrpb->txrdy is clear for cpu.  Return -1 on timeout.  */
-static int __init
+static int __devinit
 wait_for_txrdy (unsigned long cpumask)
 {
 	unsigned long timeout;
@@ -358,7 +358,7 @@
 /*
  * Bring one cpu online.
  */
-static int __init
+static int __devinit
 smp_boot_one_cpu(int cpuid)
 {
 	struct task_struct *idle;
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 930cedc..783f4e5 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -289,7 +289,7 @@
 	return srmcons_driver;
 }
 
-static int __init
+static int
 srm_console_setup(struct console *co, char *options)
 {
 	return 0;
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 0bcb968..922143e 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -420,7 +420,7 @@
 		io7_clear_errors(io7);
 }
 
-static void
+static void __init
 marvel_init_rtc(void)
 {
 	init_rtc_irq();
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 4748e14..1dd50d0 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -144,7 +144,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+void __init
 common_init_rtc(void)
 {
 	unsigned char x;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index d6e665d..ec0f05e 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -184,6 +184,7 @@
 #endif
 	printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
 	dik_show_regs(regs, r9_15);
+	add_taint(TAINT_DIE);
 	dik_show_trace((unsigned long *)(regs+1));
 	dik_show_code((unsigned int *)regs->pc);
 
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
index ab3761c..8698e07 100644
--- a/arch/alpha/lib/checksum.c
+++ b/arch/alpha/lib/checksum.c
@@ -69,6 +69,7 @@
 	result = (result & 0xffffffff) + (result >> 32);
 	return (__force __wsum)result;
 }
+EXPORT_SYMBOL(csum_tcpudp_nofold);
 
 /*
  * Do a 64-bit checksum on an arbitrary memory area..
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 6f2f46c..78c9f1a 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -657,7 +657,6 @@
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	switch (request) {
@@ -666,12 +665,7 @@
 		 */
 		case PTRACE_PEEKTEXT:
 		case PTRACE_PEEKDATA:
-			ret = access_process_vm(child, addr, &tmp,
-						sizeof(unsigned long), 0);
-			if (ret == sizeof(unsigned long))
-				ret = put_user(tmp, (unsigned long __user *) data);
-			else
-				ret = -EIO;
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
 
 		case PTRACE_PEEKUSR:
@@ -683,12 +677,7 @@
 		 */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = access_process_vm(child, addr, &data,
-						sizeof(unsigned long), 1);
-			if (ret == sizeof(unsigned long))
-				ret = 0;
-			else
-				ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR:
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 237f499..f2114bc 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -249,6 +249,7 @@
 	bust_spinlocks(1);
 	__die(str, err, thread, regs);
 	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (in_interrupt())
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index e18a41e..dde0899 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -23,6 +23,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/mtd/physmap.h>
 
@@ -83,6 +84,13 @@
 	.pullup_pin	= AT91_PIN_PA24,
 };
 
+static struct i2c_board_info __initdata csb337_i2c_devices[] = {
+	{ I2C_BOARD_INFO("rtc-ds1307", 0x68),
+	  .type = "ds1307",
+	},
+};
+
+
 static struct at91_cf_data __initdata csb337_cf_data = {
 	/*
 	 * connector P4 on the CSB 337 mates to
@@ -161,6 +169,8 @@
 	at91_add_device_udc(&csb337_udc_data);
 	/* I2C */
 	at91_add_device_i2c();
+	i2c_register_board_info(0, csb337_i2c_devices,
+			ARRAY_SIZE(csb337_i2c_devices));
 	/* Compact Flash */
 	at91_set_gpio_input(AT91_PIN_PB22, 1);		/* IOIS16 */
 	at91_add_device_cf(&csb337_cf_data);
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 390a97d..1873bd8 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -25,6 +25,7 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 #include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <asm/hardware.h>
@@ -199,6 +200,12 @@
 	.resource	= &n2100_uart_resource,
 };
 
+static struct i2c_board_info __initdata n2100_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
+		.type = "rs5c372b",
+	},
+};
 
 /*
  * Pull PCA9532 GPIO #8 low to power off the machine.
@@ -248,6 +255,9 @@
 	platform_device_register(&iop3xx_dma_0_channel);
 	platform_device_register(&iop3xx_dma_1_channel);
 
+	i2c_register_board_info(0, n2100_i2c_devices,
+		ARRAY_SIZE(n2100_i2c_devices));
+
 	pm_power_off = n2100_power_off;
 
 	init_timer(&power_button_poll_timer);
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 20688bc..9044f33 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -17,6 +17,9 @@
 	bool
 	default y
 
+config NO_DMA
+	def_bool y
+
 config ARCH_ACORN
         bool
         default y
diff --git a/arch/arm26/defconfig b/arch/arm26/defconfig
index c4a8970..2b7d44b 100644
--- a/arch/arm26/defconfig
+++ b/arch/arm26/defconfig
@@ -248,7 +248,6 @@
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index 4169279..0fefb869 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -531,7 +531,6 @@
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	switch (request) {
@@ -540,12 +539,7 @@
 		 */
 		case PTRACE_PEEKTEXT:
 		case PTRACE_PEEKDATA:
-			ret = access_process_vm(child, addr, &tmp,
-						sizeof(unsigned long), 0);
-			if (ret == sizeof(unsigned long))
-				ret = put_user(tmp, (unsigned long *) data);
-			else
-				ret = -EIO;
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
 
 		case PTRACE_PEEKUSR:
@@ -557,12 +551,7 @@
 		 */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = access_process_vm(child, addr, &data,
-						sizeof(unsigned long), 1);
-			if (ret == sizeof(unsigned long))
-				ret = 0;
-			else
-				ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR:
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
index d594fb5..2911e2e 100644
--- a/arch/arm26/kernel/traps.c
+++ b/arch/arm26/kernel/traps.c
@@ -185,6 +185,7 @@
 	printk("Internal error: %s: %x\n", str, err);
 	printk("CPU: %d\n", smp_processor_id());
 	show_regs(regs);
+	add_taint(TAINT_DIE);
 	printk("Process %s (pid: %d, stack limit = 0x%p)\n",
 		current->comm, current->pid, end_of_stack(tsk));
 
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index 562fac1..36e7ee3 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -33,9 +33,6 @@
 
 #include <asm/map.h>
 
-
-#define TABLE_SIZE	PTRS_PER_PTE * sizeof(pte_t))
-
 struct mmu_gather mmu_gathers[NR_CPUS];
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
index 3c36c2d..39060cb 100644
--- a/arch/avr32/kernel/ptrace.c
+++ b/arch/avr32/kernel/ptrace.c
@@ -153,7 +153,6 @@
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n",
@@ -166,11 +165,7 @@
 	/* Read the word at location addr in the child process */
 	case PTRACE_PEEKTEXT:
 	case PTRACE_PEEKDATA:
-		ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (ret == sizeof(tmp))
-			ret = put_user(tmp, (unsigned long __user *)data);
-		else
-			ret = -EIO;
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
 
 	case PTRACE_PEEKUSR:
@@ -181,11 +176,7 @@
 	/* Write the word in data at location addr */
 	case PTRACE_POKETEXT:
 	case PTRACE_POKEDATA:
-		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
-		if (ret == sizeof(data))
-			ret = 0;
-		else
-			ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR:
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index 86d1075..9a73ce7 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -56,6 +56,7 @@
 	show_regs_log_lvl(regs, KERN_EMERG);
 	show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
 	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (in_interrupt())
@@ -184,7 +185,7 @@
 	if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) {
 		enum bug_trap_type type;
 
-		type = report_bug(regs->pc);
+		type = report_bug(regs->pc, regs);
 		switch (type) {
 		case BUG_TRAP_TYPE_NONE:
 			break;
diff --git a/arch/cris/arch-v10/defconfig b/arch/cris/arch-v10/defconfig
index 2a3411ea..710c20b 100644
--- a/arch/cris/arch-v10/defconfig
+++ b/arch/cris/arch-v10/defconfig
@@ -429,7 +429,6 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index fd2129a..f4f9db69 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -83,19 +83,9 @@
 	switch (request) {
 		/* Read word at location address. */ 
 		case PTRACE_PEEKTEXT:
-		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,datap);
+		case PTRACE_PEEKDATA:
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
-		}
 
 		/* Read the word at location address in the USER area. */
 		case PTRACE_PEEKUSR: {
@@ -113,12 +103,7 @@
 		/* Write the word at location address. */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = 0;
-			
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				break;
-			
-			ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
  
  		/* Write the word at location address in the USER area. */
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index 1a071f1..e8914d4 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -267,10 +267,10 @@
 
 
 const struct file_operations cryptocop_fops = {
-	owner: THIS_MODULE,
-	open: cryptocop_open,
-	release: cryptocop_release,
-	ioctl: cryptocop_ioctl
+	.owner =	THIS_MODULE,
+	.open =		cryptocop_open,
+	.release =	cryptocop_release,
+	.ioctl =	cryptocop_ioctl
 };
 
 
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 5d6c527..e12f6cc 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -574,10 +574,10 @@
 }
 
 static const struct file_operations i2c_fops = {
-	owner:    THIS_MODULE,
-	ioctl:    i2c_ioctl,
-	open:     i2c_open,
-	release:  i2c_release,
+	.owner =    THIS_MODULE,
+	.ioctl =    i2c_ioctl,
+	.open =     i2c_open,
+	.release =  i2c_release,
 };
 
 int __init
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index 24b919b..fa8d500 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -51,10 +51,10 @@
 int pcf8563_release(struct inode *, struct file *);
 
 static const struct file_operations pcf8563_fops = {
-	owner: THIS_MODULE,
-	ioctl: pcf8563_ioctl,
-	open: pcf8563_open,
-	release: pcf8563_release,
+	.owner =	THIS_MODULE,
+	.ioctl =	pcf8563_ioctl,
+	.open =		pcf8563_open,
+	.release =	pcf8563_release,
 };
 
 unsigned char
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index d4d57b7..38ece0c 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -146,12 +146,7 @@
 		/* Write the word at location address. */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = 0;
-
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				break;
-
-			ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
  		/* Write the word at location address in the USER area. */
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 43dc08e..275673c 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1492,6 +1492,10 @@
 	.long sys_move_pages
 	.long sys_getcpu
 	.long sys_epoll_pwait
+	.long sys_utimensat		/* 320 */
+	.long sys_signalfd
+	.long sys_timerfd
+	.long sys_eventfd
 
 
 syscall_table_size = (. - sys_call_table)
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index 1e7a101..e89cad1 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -647,17 +647,11 @@
 }
 #endif
 
-#ifdef CONFIG_GDBSTUB_CONSOLE
-
-static kdev_t gdbstub_console_dev(struct console *con)
-{
-	return MKDEV(1,3); /* /dev/null */
-}
+#ifdef CONFIG_GDB_CONSOLE
 
 static struct console gdbstub_console = {
 	.name	= "gdb",
 	.write	= gdbstub_console_write,	/* in break.S */
-	.device	= gdbstub_console_dev,
 	.flags	= CON_PRINTBUFFER,
 	.index	= -1,
 };
@@ -2021,7 +2015,7 @@
 	ptr = mem2hex(gdbstub_banner, ptr, sizeof(gdbstub_banner) - 1, 0);
 	gdbstub_send_packet(output_buffer);
 #endif
-#if defined(CONFIG_GDBSTUB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined(CONFIG_GDB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
 	register_console(&gdbstub_console);
 #endif
 
@@ -2031,7 +2025,7 @@
 /*
  * register the console at a more appropriate time
  */
-#if defined (CONFIG_GDBSTUB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined (CONFIG_GDB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
 static int __init gdbstub_postinit(void)
 {
 	printk("registering console\n");
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index ce88fb9..709e9bd 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -112,20 +112,12 @@
 	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: {
-		int copied;
-
+	case PTRACE_PEEKDATA:
 		ret = -EIO;
 		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
 			break;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (copied != sizeof(tmp))
-			break;
-
-		ret = put_user(tmp,(unsigned long *) data);
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 		/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -176,9 +168,7 @@
 		ret = -EIO;
 		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
 			break;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
-			break;
-		ret = 0;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index aa3c795..c1c32e4 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -60,10 +60,6 @@
 static void __init setup_uclinux_memory(void);
 #endif
 
-#ifdef CONFIG_CONSOLE
-extern struct consw *conswitchp;
-#endif
-
 #ifdef CONFIG_MB93090_MB00
 static char __initdata mb93090_banner[] = "FJ/RH FR-V Linux";
 static char __initdata mb93090_version[] = UTS_RELEASE;
@@ -795,13 +791,6 @@
 #endif
 #endif
 
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
-	/* we need to initialize the Flashrom device here since we might
-	 * do things with flash early on in the boot
-	 */
-	flash_probe();
-#endif
-
 	/* deal with the command line - RedBoot may have passed one to the kernel */
 	memcpy(command_line, boot_command_line, sizeof(command_line));
 	*cmdline_p = &command_line[0];
@@ -837,11 +826,6 @@
 #endif
 #endif
 
-#ifdef CONFIG_BLK_DEV_BLKMEM
-	ROOT_DEV = MKDEV(BLKMEM_MAJOR,0);
-#endif
-	/*rom_length = (unsigned long)&_flashend - (unsigned long)&_romvec;*/
-
 #ifdef CONFIG_MMU
 	setup_linux_memory();
 #else
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 618dbad..e35f74e 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -68,6 +68,9 @@
 config NO_IOPORT
 	def_bool y
 
+config NO_DMA
+	def_bool y
+
 config ISA
 	bool
 	default y
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile
index b2d896a..53b5c1e 100644
--- a/arch/h8300/Makefile
+++ b/arch/h8300/Makefile
@@ -61,10 +61,11 @@
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
-vmlinux.srec vmlinux.bin: vmlinux
+vmlinux.srec vmlinux.bin zImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 define archhelp
-  echo  'vmlinux.bin  - Create raw binary'
-  echo  'vmlinux.srec - Create srec binary'
+  @echo  'vmlinux.bin  - Create raw binary'
+  @echo  'vmlinux.srec - Create srec binary'
+  @echo  'zImage       - Compressed kernel image'
 endef
diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile
index 71aac82..d6189e0 100644
--- a/arch/h8300/boot/compressed/Makefile
+++ b/arch/h8300/boot/compressed/Makefile
@@ -15,10 +15,10 @@
 # in order to suppress error message.
 #
 CONFIG_MEMORY_START     ?= 0x00400000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00400000
+CONFIG_BOOT_LINK_OFFSET ?= 0x00140000
 IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
 
-LDFLAGS_vmlinux := -T $(obj)/vmlinux.lds
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S
index b8e90d1..985a81a 100644
--- a/arch/h8300/boot/compressed/head.S
+++ b/arch/h8300/boot/compressed/head.S
@@ -4,7 +4,7 @@
  *  Copyright (C) 2006 Yoshinori Sato
  */
 
-.h8300h
+	.h8300h
 #include <linux/linkage.h>
 
 #define SRAM_START 0xff4000
diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds
new file mode 100644
index 0000000..65e2a0d
--- /dev/null
+++ b/arch/h8300/boot/compressed/vmlinux.lds
@@ -0,0 +1,32 @@
+SECTIONS
+{
+        .text :
+        {
+        __stext = . ;
+	__text = .;
+	       *(.text.startup)
+	       *(.text)
+        __etext = . ;
+        }
+
+	.rodata :
+	{
+		*(.rodata)
+	}
+        .data :
+
+        {
+        __sdata = . ;
+        ___data_start = . ;
+                *(.data.*)
+	}
+        .bss :
+        {
+        . = ALIGN(0x4) ;
+        __sbss = . ;
+                *(.bss*)
+        . = ALIGN(0x4) ;
+        __ebss = . ;
+        __end = . ;
+        }
+}
diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr
new file mode 100644
index 0000000..a0f6962
--- /dev/null
+++ b/arch/h8300/boot/compressed/vmlinux.scr
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  .data : {
+	_input_len = .;
+	LONG(_input_data_end - _input_data) _input_data = .;
+	*(.data)
+	_input_data_end = .;
+	}
+}
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index ccc1a7f..874f6ae 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -6,6 +6,7 @@
 
 obj-y := process.o traps.o ptrace.o irq.o \
 	 sys_h8300.o time.o semaphore.o signal.o \
-         setup.o gpio.o init_task.o syscalls.o
+         setup.o gpio.o init_task.o syscalls.o \
+	 entry.o
 
 obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o 
diff --git a/arch/h8300/platform/h8s/entry.S b/arch/h8300/kernel/entry.S
similarity index 62%
rename from arch/h8300/platform/h8s/entry.S
rename to arch/h8300/kernel/entry.S
index f3d6b8e..ca74316 100644
--- a/arch/h8300/platform/h8s/entry.S
+++ b/arch/h8300/kernel/entry.S
@@ -1,11 +1,10 @@
 /* -*- mode: asm -*-
  *
- *  linux/arch/h8300/platform/h8s/entry.S
+ *  linux/arch/h8300/platform/h8300h/entry.S
  *
  *  Yoshinori Sato <ysato@users.sourceforge.jp>
+ *  David McCullough <davidm@snapgear.com>
  *
- *	fairly heavy changes to fix syscall args and signal processing
- *	by David McCullough <davidm@snapgear.com>
  */
 
 /*
@@ -23,13 +22,66 @@
 #include <asm/thread_info.h>
 #include <asm/errno.h>
 
+#if defined(CONFIG_CPU_H8300H)
+#define USERRET 8
+INTERRUPTS = 64
+	.h8300h
+	.macro	SHLL2 reg
+	shll.l	\reg
+	shll.l	\reg
+	.endm
+	.macro	SHLR2 reg
+	shlr.l	\reg
+	shlr.l	\reg
+	.endm
+	.macro	SAVEREGS
+	mov.l	er0,@-sp
+	mov.l	er1,@-sp
+	mov.l	er2,@-sp
+	mov.l	er3,@-sp
+	.endm
+	.macro	RESTOREREGS
+	mov.l	@sp+,er3
+	mov.l	@sp+,er2
+	.endm
+	.macro	SAVEEXR
+	.endm
+	.macro	RESTOREEXR
+	.endm
+#endif
+#if defined(CONFIG_CPU_H8S)
+#define USERRET 10
+#define USEREXR 8
+INTERRUPTS = 128
 	.h8300s
+	.macro	SHLL2 reg
+	shll.l	#2,\reg
+	.endm
+	.macro	SHLR2 reg
+	shlr.l	#2,\reg
+	.endm
+	.macro	SAVEREGS
+	stm.l	er0-er3,@-sp
+	.endm
+	.macro	RESTOREREGS
+	ldm.l	@sp+,er2-er3
+	.endm
+	.macro	SAVEEXR
+	mov.w	@(USEREXR:16,er0),r1
+	mov.w	r1,@(LEXR-LER3:16,sp)		/* copy EXR */
+	.endm
+	.macro	RESTOREEXR
+	mov.w	@(LEXR-LER1:16,sp),r1		/* restore EXR */
+	mov.b	r1l,r1h
+	mov.w	r1,@(USEREXR:16,er0)
+	.endm
+#endif
+
 
 /* CPU context save/restore macros. */
-	
+
 	.macro	SAVE_ALL
 	mov.l	er0,@-sp
-
 	stc	ccr,r0l				/* check kernel mode */
 	btst	#4,r0l
 	bne	5f
@@ -39,42 +91,38 @@
 	mov.l	@sp,er0				/* restore saved er0 */
 	orc	#0x10,ccr			/* switch kernel stack */
 	mov.l	@SYMBOL_NAME(sw_ksp),sp
-	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */ 
-	stm.l	er0-er3,@-sp
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(10:16,er0),er1		/* copy the RET addr */
-	mov.l	er1,@(LRET-LER3:16,sp)
-	mov.w	@(8:16,er0),r1
-	mov.w	r1,@(LEXR-LER3:16,sp)		/* copy EXR */
+	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */
+	SAVEREGS
+	mov.l   @SYMBOL_NAME(sw_usp),er0
+	mov.l   @(USERRET:16,er0),er1           /* copy the RET addr */
+	mov.l   er1,@(LRET-LER3:16,sp)
+	SAVEEXR
 
-	mov.w	e1,r1				/* e1 highbyte = ccr */
-	and	#0xef,r1h			/* mask mode? flag */
-	sub.w	r0,r0
-	mov.b	r1h,r0l
-	mov.w	r0,@(LCCR-LER3:16,sp)		/* copy ccr */
 	mov.l	@(LORIG-LER3:16,sp),er0
 	mov.l	er0,@(LER0-LER3:16,sp)		/* copy ER0 */
+	mov.w	e1,r1				/* e1 highbyte = ccr */
+	and	#0xef,r1h			/* mask mode? flag */
 	bra	6f
 5:
 	/* kernel mode */
 	mov.l	@sp,er0				/* restore saved er0 */
 	subs	#2,sp				/* set dummy ccr */
-	stm.l	er0-er3,@-sp
+	SAVEREGS
 	mov.w	@(LRET-LER3:16,sp),r1		/* copy old ccr */
+6:
 	mov.b	r1h,r1l
 	mov.b	#0,r1h
-	mov.w	r1,@(LCCR-LER3:16,sp)
-6:	
+	mov.w	r1,@(LCCR-LER3:16,sp)		/* set ccr */
 	mov.l	er6,@-sp			/* syscall arg #6 */
 	mov.l	er5,@-sp			/* syscall arg #5 */
 	mov.l	er4,@-sp			/* syscall arg #4 */
-	.endm
+	.endm					/* r1 = ccr */
 
 	.macro	RESTORE_ALL
 	mov.l	@sp+,er4
 	mov.l	@sp+,er5
 	mov.l	@sp+,er6
-	ldm.l	@sp+,er2-er3
+	RESTOREREGS
 	mov.w	@(LCCR-LER1:16,sp),r0		/* check kernel mode */
 	btst	#4,r0l
 	bne	7f
@@ -83,18 +131,16 @@
 	mov.l	@SYMBOL_NAME(sw_usp),er0
 	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
 	mov.l	er1,@er0
-	mov.w	@(LEXR-LER1:16,sp),r1		/* restore EXR */
-	mov.b	r1l,r1h
-	mov.w	r1,@(8:16,er0)
+	RESTOREEXR
 	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
 	mov.b	r1l,r1h
 	mov.b	@(LRET+1-LER1:16,sp),r1l
 	mov.w	r1,e1
 	mov.w	@(LRET+2-LER1:16,sp),r1
-	mov.l	er1,@(10:16,er0)
+	mov.l	er1,@(USERRET:16,er0)
 
 	mov.l	@sp+,er1
-	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */ 
+	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */
 	mov.l	sp,@SYMBOL_NAME(sw_ksp)
 	andc	#0xef,ccr			/* switch to user mode */
 	mov.l	er0,sp
@@ -108,7 +154,7 @@
 	adds	#4,sp				/* remove the sw created LVEC */
 	rte
 	.endm
-	
+
 .globl SYMBOL_NAME(system_call)
 .globl SYMBOL_NAME(ret_from_exception)
 .globl SYMBOL_NAME(ret_from_fork)
@@ -116,16 +162,25 @@
 .globl SYMBOL_NAME(interrupt_redirect_table)
 .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
 .globl SYMBOL_NAME(resume)
-.globl SYMBOL_NAME(trace_break)
 .globl SYMBOL_NAME(interrupt_entry)
-		
-INTERRUPTS = 128
+.globl SYMBOL_NAME(trace_break)
+
 #if defined(CONFIG_ROMKERNEL)
 	.section .int_redirect,"ax"
 SYMBOL_NAME_LABEL(interrupt_redirect_table)
+#if defined(CONFIG_CPU_H8300H)
 	.rept	7
 	.long	0
 	.endr
+#endif
+#if defined(CONFIG_CPU_H8S)
+	.rept	5
+	.long	0
+	.endr
+	jmp	@SYMBOL_NAME(trace_break)
+	.long	0
+#endif
+
 	jsr	@SYMBOL_NAME(interrupt_entry)	/* NMI */
 	jmp	@SYMBOL_NAME(system_call)	/* TRAPA #0 (System call) */
 	.long	0
@@ -141,20 +196,20 @@
 SYMBOL_NAME_LABEL(interrupt_redirect_table)
 	.space	4
 #endif
-	
+
 	.section .text
 	.align	2
 SYMBOL_NAME_LABEL(interrupt_entry)
 	SAVE_ALL
-	mov.w	@(LCCR,sp),r0
-	btst	#4,r0l
+	mov.l	sp,er0
+	add.l	#LVEC,er0
+	btst	#4,r1l
 	bne	1f
+	/* user LVEC */
 	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(4:16,er0),er0
-	bra	2f
+	adds	#4,er0
 1:
-	mov.l	@(LVEC:16,sp),er0
-2:
+	mov.l	@er0,er0			/* LVEC address */
 #if defined(CONFIG_ROMKERNEL)
 	sub.l	#SYMBOL_NAME(interrupt_redirect_table),er0
 #endif
@@ -162,69 +217,62 @@
 	mov.l	@SYMBOL_NAME(interrupt_redirect_table),er1
 	sub.l	er1,er0
 #endif
-	shlr.l	#2,er0
+	SHLR2	er0
 	dec.l	#1,er0
 	mov.l	sp,er1
 	subs	#4,er1				/* adjust ret_pc */
-	jsr	@SYMBOL_NAME(process_int)
-	mov.l	@SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
-	beq	1f
-	jsr	@SYMBOL_NAME(do_softirq)
-1:
-	jmp	@SYMBOL_NAME(ret_from_exception)
+	jsr	@SYMBOL_NAME(do_IRQ)
+	jmp	@SYMBOL_NAME(ret_from_interrupt)
 
 SYMBOL_NAME_LABEL(system_call)
 	subs	#4,sp				/* dummy LVEC */
 	SAVE_ALL
+	andc	#0x7f,ccr
 	mov.l	er0,er4
-	mov.l	#-ENOSYS,er0
-	mov.l	er0,@(LER0:16,sp)
 
 	/* save top of frame */
 	mov.l	sp,er0
 	jsr	@SYMBOL_NAME(set_esp0)
-	cmp.l	#NR_syscalls,er4
-	bcc	SYMBOL_NAME(ret_from_exception):16
-	shll.l	#2,er4
-	mov.l	#SYMBOL_NAME(sys_call_table),er0
-	add.l	er4,er0
-	mov.l	@er0,er0
-	mov.l	er0,er4
-	beq	SYMBOL_NAME(ret_from_exception):16	
 	mov.l	sp,er2
 	and.w	#0xe000,r2
-	mov.b	@((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
+	mov.b	@((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
 	btst	#(TIF_SYSCALL_TRACE & 7),r2l
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	andc	#0x7f,ccr
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)			/* save the return value */
-#if defined(CONFIG_SYSCALL_PRINT)
-	jsr	@SYMBOL_NAME(syscall_print)
-#endif
-	bra	SYMBOL_NAME(ret_from_exception):8
+	beq	1f
+	jsr	@SYMBOL_NAME(do_syscall_trace)
 1:
-	jsr	SYMBOL_NAME(syscall_trace)
+	cmp.l	#NR_syscalls,er4
+	bcc	badsys
+	SHLL2	er4
+	mov.l	#SYMBOL_NAME(sys_call_table),er0
+	add.l	er4,er0
+	mov.l	@er0,er4
+	beq	SYMBOL_NAME(ret_from_exception):16
 	mov.l	@(LER1:16,sp),er0
 	mov.l	@(LER2:16,sp),er1
 	mov.l	@(LER3:16,sp),er2
 	jsr	@er4
 	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-	jsr	@SYMBOL_NAME(syscall_trace)
-	bra	SYMBOL_NAME(ret_from_exception):8
+	mov.l	sp,er2
+	and.w	#0xe000,r2
+	mov.b	@((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
+	btst	#(TIF_SYSCALL_TRACE & 7),r2l
+	beq	2f
+	jsr	@SYMBOL_NAME(do_syscall_trace)
+2:
+#if defined(CONFIG_SYSCALL_PRINT)
+	jsr	@SYMBOL_NAME(syscall_print)
+#endif
+	orc	#0x80,ccr
+	bra	resume_userspace
 
-SYMBOL_NAME_LABEL(ret_from_fork)
-	mov.l	er2,er0
-	jsr	@SYMBOL_NAME(schedule_tail)
-	bra	SYMBOL_NAME(ret_from_exception):8
+badsys:
+	mov.l	#-ENOSYS,er0
+	mov.l	er0,@(LER0:16,sp)
+	bra	resume_userspace
 
-SYMBOL_NAME_LABEL(reschedule)
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	jsr	@SYMBOL_NAME(schedule)
+#if !defined(CONFIG_PREEMPT)
+#define resume_kernel restore_all
+#endif
 
 SYMBOL_NAME_LABEL(ret_from_exception)
 #if defined(CONFIG_PREEMPT)
@@ -232,58 +280,68 @@
 #endif
 SYMBOL_NAME_LABEL(ret_from_interrupt)
 	mov.b	@(LCCR+1:16,sp),r0l
-	btst	#4,r0l			/* check if returning to kernel */
-	bne	done:8			/* if so, skip resched, signals */
+	btst	#4,r0l
+	bne	resume_kernel:8		/* return from kernel */
+resume_userspace:
 	andc	#0x7f,ccr
 	mov.l	sp,er4
-	and.w	#0xe000,r4
+	and.w	#0xe000,r4		/* er4 <- current thread info */
 	mov.l	@(TI_FLAGS:16,er4),er1
 	and.l	#_TIF_WORK_MASK,er1
-	beq	done:8
-1:
-	mov.l	@(TI_FLAGS:16,er4),er1
+	beq	restore_all:8
+work_pending:
 	btst	#TIF_NEED_RESCHED,r1l
-	bne	SYMBOL_NAME(reschedule):16
+	bne	work_resched:8
+	/* work notifysig */
 	mov.l	sp,er0
-	subs	#4,er0			/* adjust retpc */
-	mov.l	er2,er1
-	jsr	@SYMBOL_NAME(do_signal)
-#if defined(CONFIG_PREEMPT)
-	bra	done:8			/* userspace thoru */
-3:
-	btst	#4,r0l
-	beq	done:8			/* userspace thoru */
-4:
-	mov.l	@(TI_PRE_COUNT:16,er4),er1
-	bne	done:8
-	mov.l	@(TI_FLAGS:16,er4),er1
-	btst	#TIF_NEED_RESCHED,r1l
-	beq	done:8
-	mov.b	r0l,r0l
-	bpl	done:8			/* interrupt off (exception path?) */
-	mov.l	#PREEMPT_ACTIVE,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	andc	#0x7f,ccr
+	subs	#4,er0			/* er0: pt_regs */
+	jsr	@SYMBOL_NAME(do_notify_resume)
+	bra	restore_all:8
+work_resched:
+	mov.l	sp,er0
+	jsr	@SYMBOL_NAME(set_esp0)
 	jsr	@SYMBOL_NAME(schedule)
-	sub.l	er1,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	orc	#0x80,ccr
-	bra	4b:8
-#endif
-done:
+	bra	resume_userspace:8
+restore_all:
 	RESTORE_ALL			/* Does RTE */
 
+#if defined(CONFIG_PREEMPT)
+resume_kernel:
+	mov.l	@(TI_PRE_COUNT:16,er4),er0
+	bne	restore_all:8
+need_resched:
+	mov.l	@(TI_FLAGS:16,er4),er0
+	btst	#TIF_NEED_RESCHED,r0l
+	beq	restore_all:8
+	mov.b	@(LCCR+1:16,sp),r0l	/* Interrupt Enabled? */
+	bmi	restore_all:8
+	mov.l	#PREEMPT_ACTIVE,er0
+	mov.l	er0,@(TI_PRE_COUNT:16,er4)
+	andc	#0x7f,ccr
+	mov.l	sp,er0
+	jsr	@SYMBOL_NAME(set_esp0)
+	jsr	@SYMBOL_NAME(schedule)
+	orc	#0x80,ccr
+	bra	need_resched:8
+#endif
+
+SYMBOL_NAME_LABEL(ret_from_fork)
+	mov.l	er2,er0
+	jsr	@SYMBOL_NAME(schedule_tail)
+	jmp	@SYMBOL_NAME(ret_from_exception)
+
 SYMBOL_NAME_LABEL(resume)
 	/*
-	 *	er0 = prev
-	 *	er1 = next
-	 *	return last in er2
+	 * Beware - when entering resume, offset of tss is in d1,
+	 * prev (the current task) is in a0, next (the new task)
+	 * is in a1 and d2.b is non-zero if the mm structure is
+	 * shared between the tasks, so don't change these
+	 * registers until their contents are no longer needed.
 	 */
 
 	/* save sr */
 	sub.w	r3,r3
 	stc	ccr,r3l
-	stc	exr,r3h
 	mov.w	r3,@(THREAD_CCR+2:16,er0)
 
 	/* disable interrupts */
@@ -291,41 +349,45 @@
 	mov.l	@SYMBOL_NAME(sw_usp),er3
 	mov.l	er3,@(THREAD_USP:16,er0)
 	mov.l	sp,@(THREAD_KSP:16,er0)
-	
+
 	/* Skip address space switching if they are the same. */
 	/* FIXME: what did we hack out of here, this does nothing! */
 
 	mov.l	@(THREAD_USP:16,er1),er0
 	mov.l	er0,@SYMBOL_NAME(sw_usp)
 	mov.l	@(THREAD_KSP:16,er1),sp
-			
+
 	/* restore status register */
 	mov.w	@(THREAD_CCR+2:16,er1),r3
 
 	ldc	r3l,ccr
-	ldc	r3h,exr
-
 	rts
 
 SYMBOL_NAME_LABEL(trace_break)
-	subs	#4,sp			/* dummy LVEC */
+	subs	#4,sp
 	SAVE_ALL
 	sub.l	er1,er1
 	dec.l	#1,er1
-	mov.l	er1,@(LORIG,sp)	
+	mov.l	er1,@(LORIG,sp)
 	mov.l	sp,er0
 	jsr	@SYMBOL_NAME(set_esp0)
 	mov.l	@SYMBOL_NAME(sw_usp),er0
 	mov.l	@er0,er1
+	mov.w	@(-2:16,er1),r2
+	cmp.w	#0x5730,r2
+	beq	1f
 	subs	#2,er1
-	mov.l	er1,@er0	
+	mov.l	er1,@er0
+1:
 	and.w	#0xff,e1
 	mov.l	er1,er0
 	jsr	@SYMBOL_NAME(trace_trap)
-	jmp	@SYMBOL_NAME(ret_from_exception)	
+	jmp	@SYMBOL_NAME(ret_from_exception)
 
 	.section	.bss
 SYMBOL_NAME_LABEL(sw_ksp)
-	.space	4	
+	.space	4
 SYMBOL_NAME_LABEL(sw_usp)
-	.space	4	
+	.space	4
+
+	.end
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
deleted file mode 100644
index 3e4f479..0000000
--- a/arch/h8300/kernel/ints.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * linux/arch/h8300/kernel/ints.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c
- *
- * 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 1996 Roman Zippel
- * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/bootmem.h>
-#include <linux/hardirq.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/traps.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/errno.h>
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-typedef struct irq_handler {
-	irqreturn_t (*handler)(int, void *, struct pt_regs *);
-	int         flags;
-	int         count;
-	void	    *dev_id;
-	const char  *devname;
-} irq_handler_t;
-
-static irq_handler_t *irq_list[NR_IRQS];
-static int use_kmalloc;
-
-extern unsigned long *interrupt_redirect_table;
-extern const int h8300_saved_vectors[];
-extern const unsigned long h8300_trap_table[];
-int h8300_enable_irq_pin(unsigned int irq);
-void h8300_disable_irq_pin(unsigned int irq);
-
-#define CPU_VECTOR ((unsigned long *)0x000000)
-#define ADDR_MASK (0xffffff)
-
-#if defined(CONFIG_RAMKERNEL)
-static unsigned long __init *get_vector_address(void)
-{
-	unsigned long *rom_vector = CPU_VECTOR;
-	unsigned long base,tmp;
-	int vec_no;
-
-	base = rom_vector[EXT_IRQ0] & ADDR_MASK;
-	
-	/* check romvector format */
-	for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
-		if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
-			return NULL;
-	}
-
-	/* ramvector base address */
-	base -= EXT_IRQ0*4;
-
-	/* writerble check */
-	tmp = ~(*(volatile unsigned long *)base);
-	(*(volatile unsigned long *)base) = tmp;
-	if ((*(volatile unsigned long *)base) != tmp)
-		return NULL;
-	return (unsigned long *)base;
-}
-#endif
-
-void __init init_IRQ(void)
-{
-#if defined(CONFIG_RAMKERNEL)
-	int i;
-	unsigned long *ramvec,*ramvec_p;
-	const unsigned long *trap_entry;
-	const int *saved_vector;
-
-	ramvec = get_vector_address();
-	if (ramvec == NULL)
-		panic("interrupt vector serup failed.");
-	else
-		printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
-
-	/* create redirect table */
-	ramvec_p = ramvec;
-	trap_entry = h8300_trap_table;
-	saved_vector = h8300_saved_vectors;
-	for ( i = 0; i < NR_IRQS; i++) {
-		if (i == *saved_vector) {
-			ramvec_p++;
-			saved_vector++;
-		} else {
-			if ( i < NR_TRAPS ) {
-				if (*trap_entry)
-					*ramvec_p = VECTOR(*trap_entry);
-				ramvec_p++;
-				trap_entry++;
-			} else
-				*ramvec_p++ = REDIRECT(interrupt_entry);
-		}
-	}
-	interrupt_redirect_table = ramvec;
-#ifdef DUMP_VECTOR
-	ramvec_p = ramvec;
-	for (i = 0; i < NR_IRQS; i++) {
-		if ((i % 8) == 0)
-			printk(KERN_DEBUG "\n%p: ",ramvec_p);
-		printk(KERN_DEBUG "%p ",*ramvec_p);
-		ramvec_p++;
-	}
-	printk(KERN_DEBUG "\n");
-#endif
-#endif
-}
-
-int request_irq(unsigned int irq, 
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                unsigned long flags, const char *devname, void *dev_id)
-{
-	irq_handler_t *irq_handle;
-	if (irq < 0 || irq >= NR_IRQS) {
-		printk(KERN_ERR "Incorrect IRQ %d from %s\n", irq, devname);
-		return -EINVAL;
-	}
-
-	if (irq_list[irq] || (h8300_enable_irq_pin(irq) == -EBUSY))
-		return -EBUSY;
-
-	if (use_kmalloc)
-		irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
-	else {
-		/* use bootmem allocater */
-		irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
-		irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000);
-	}
-
-	if (irq_handle == NULL)
-		return -ENOMEM;
-
-	irq_handle->handler = handler;
-	irq_handle->flags   = flags;
-	irq_handle->count   = 0;
-	irq_handle->dev_id  = dev_id;
-	irq_handle->devname = devname;
-	irq_list[irq] = irq_handle;
-
-	if (irq_handle->flags & IRQF_SAMPLE_RANDOM)
-		rand_initialize_irq(irq);
-
-	enable_irq(irq);
-	return 0;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq >= NR_IRQS)
-		return;
-
-	if (!irq_list[irq] || irq_list[irq]->dev_id != dev_id)
-		printk(KERN_WARNING "Removing probably wrong IRQ %d from %s\n",
-		       irq, irq_list[irq]->devname);
-	disable_irq(irq);
-	h8300_disable_irq_pin(irq);
-	if (((unsigned long)irq_list[irq] & 0x80000000) == 0) {
-		kfree(irq_list[irq]);
-		irq_list[irq] = NULL;
-	}
-}
-
-EXPORT_SYMBOL(free_irq);
-
-/*
- * Do we need these probe functions on the m68k?
- */
-unsigned long probe_irq_on (void)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off (unsigned long irqs)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-void enable_irq(unsigned int irq)
-{
-	if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
-		IER_REGS |= 1 << (irq - EXT_IRQ0);
-}
-
-void disable_irq(unsigned int irq)
-{
-	if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
-		IER_REGS &= ~(1 << (irq - EXT_IRQ0));
-}
-
-asmlinkage void process_int(int irq, struct pt_regs *fp)
-{
-	irq_enter();
-	h8300_clear_isr(irq);
-	if (irq >= NR_TRAPS && irq < NR_IRQS) {
-		if (irq_list[irq]) {
-			irq_list[irq]->handler(irq, irq_list[irq]->dev_id, fp);
-			irq_list[irq]->count++;
-			if (irq_list[irq]->flags & IRQF_SAMPLE_RANDOM)
-				add_interrupt_randomness(irq);
-		}
-	} else {
-		BUG();
-	}
-	irq_exit();
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v;
-
-	if ((i < NR_IRQS) && (irq_list[i]!=NULL)) {
-		seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
-		seq_printf(p, "%s\n", irq_list[i]->devname);
-	}
-
-	return 0;
-}
-
-void init_irq_proc(void)
-{
-}
-
-static int __init enable_kmalloc(void)
-{
-	use_kmalloc = 1;
-	return 0;
-}
-core_initcall(enable_kmalloc);
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 8f2411d..d32bbf0 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -111,10 +111,7 @@
       /* when 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;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -219,7 +216,7 @@
 	return ret;
 }
 
-asmlinkage void syscall_trace(void)
+asmlinkage void do_syscall_trace(void)
 {
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return;
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 0295560..62ea12d 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -547,3 +547,9 @@
 	}
 	return 0;
 }
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
+{
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		do_signal(regs, NULL);
+}
diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile
index b24ea08..c509636 100644
--- a/arch/h8300/platform/h8300h/Makefile
+++ b/arch/h8300/platform/h8300h/Makefile
@@ -4,4 +4,4 @@
 # Reuse any files we can from the H8/300H
 #
 
-obj-y := entry.o irq_pin.o ptrace_h8300h.o
+obj-y := irq_pin.o ptrace_h8300h.o
diff --git a/arch/h8300/platform/h8300h/entry.S b/arch/h8300/platform/h8300h/entry.S
deleted file mode 100644
index f86ac3b..0000000
--- a/arch/h8300/platform/h8300h/entry.S
+++ /dev/null
@@ -1,332 +0,0 @@
-/* -*- mode: asm -*-
- *
- *  linux/arch/h8300/platform/h8300h/entry.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *  David McCullough <davidm@snapgear.com>
- *
- */
-
-/*
- *  entry.S
- *  include exception/interrupt gateway
- *          system call entry
- */
-
-#include <linux/sys.h>
-#include <asm/unistd.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/errno.h>
-
-	.h8300h
-
-/* CPU context save/restore macros. */
-	
-	.macro	SAVE_ALL
-	mov.l	er0,@-sp
-
-	stc	ccr,r0l				/* check kernel mode */
-	btst	#4,r0l
-	bne	5f
-
-	mov.l	sp,@SYMBOL_NAME(sw_usp)		/* user mode */
-	mov.l	@sp,er0
-	orc	#0x10,ccr
-	mov.l	@SYMBOL_NAME(sw_ksp),sp
-	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */ 
-	mov.l	er0,@-sp
-	mov.l	er1,@-sp
-	mov.l   @SYMBOL_NAME(sw_usp),er0
-	mov.l   @(8:16,er0),er1                 /* copy the RET addr */
-	mov.l   er1,@(LRET-LER1:16,sp)
-
-	mov.w	e1,r1				/* e1 highbyte = ccr */
-	and	#0xef,r1h			/* mask mode? flag */
-	sub.w	r0,r0
-	mov.b	r1h,r0l
-	mov.w	r0,@(LCCR-LER1:16,sp)		/* copy ccr */
-	mov.l	@(LORIG-LER1:16,sp),er0
-	mov.l	er0,@(LER0-LER1:16,sp)		/* copy ER0 */
-	bra	6f
-5:
-	mov.l	@sp,er0				/* kernel mode */
-	subs	#2,sp				/* dummy ccr */
-	mov.l	er0,@-sp
-	mov.l	er1,@-sp
-	mov.w	@(LRET-LER1:16,sp),r1		/* copy old ccr */
-	mov.b	r1h,r1l
-	mov.b	#0,r1h
-	mov.w	r1,@(LCCR-LER1:16,sp)		/* set ccr */
-6:
-	mov.l	er2,@-sp
-	mov.l	er3,@-sp
-	mov.l	er6,@-sp			/* syscall arg #6 */
-	mov.l	er5,@-sp			/* syscall arg #5 */
-	mov.l	er4,@-sp			/* syscall arg #4 */
-	.endm
-
-	.macro	RESTORE_ALL
-	mov.l	@sp+,er4
-	mov.l	@sp+,er5
-	mov.l	@sp+,er6
-	mov.l	@sp+,er3
-	mov.l	@sp+,er2
-	mov.w	@(LCCR-LER1:16,sp),r0		/* check kernel mode */
-	btst	#4,r0l
-	bne	7f
-
-	orc	#0x80,ccr
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
-	mov.l	er1,@er0
-	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
-	mov.b	r1l,r1h
-	mov.b	@(LRET+1-LER1:16,sp),r1l
-	mov.w	r1,e1
-	mov.w	@(LRET+2-LER1:16,sp),r1
-	mov.l	er1,@(8:16,er0)
-
-	mov.l	@sp+,er1
-	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */ 
-	mov.l	sp,@SYMBOL_NAME(sw_ksp)
-	mov.l	er0,sp
-	bra	8f
-7:
-	mov.l	@sp+,er1
-	adds	#4,sp
-	adds	#2,sp
-8:
-	mov.l	@sp+,er0
-	adds	#4,sp				/* remove the sw created LVEC */
-	rte
-	.endm
-	
-.globl SYMBOL_NAME(system_call)
-.globl SYMBOL_NAME(ret_from_exception)
-.globl SYMBOL_NAME(ret_from_fork)
-.globl SYMBOL_NAME(ret_from_interrupt)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
-.globl SYMBOL_NAME(resume)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-.globl SYMBOL_NAME(interrupt_entry)
-.globl SYMBOL_NAME(system_call)
-.globl SYMBOL_NAME(trace_break)
-
-#if defined(CONFIG_ROMKERNEL)
-INTERRUPTS = 64		
-	.section .int_redirect,"ax"
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
-	.rept	7
-	.long	0
-	.endr
-	jsr	@SYMBOL_NAME(interrupt_entry)	/* NMI */
-	jmp	@SYMBOL_NAME(system_call)	/* TRAPA #0 (System call) */
-	.long	0
-	.long	0
-	jmp	@SYMBOL_NAME(trace_break)	/* TRAPA #3 (breakpoint) */
-	.rept	INTERRUPTS-12
-	jsr	@SYMBOL_NAME(interrupt_entry)
-	.endr
-#endif
-#if defined(CONFIG_RAMKERNEL)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-	.section .bss
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
-	.space	4
-#endif
-
-	.section .text
-	.align	2
-SYMBOL_NAME_LABEL(interrupt_entry)
-	SAVE_ALL
-	mov.w	@(LCCR,sp),r0
-	btst	#4,r0l
-	bne	1f
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(4:16,er0),er0
-	bra	2f
-1:
-	mov.l	@(LVEC,sp),er0
-2:
-#if defined(CONFIG_ROMKERNEL)
-	sub.l	#SYMBOL_NAME(interrupt_redirect_table),er0
-#endif
-#if defined(CONFIG_RAMKERNEL)
-	mov.l	@SYMBOL_NAME(interrupt_redirect_table),er1
-	sub.l	er1,er0
-#endif
-	shlr.l	er0
-	shlr.l	er0
-	dec.l	#1,er0
-	mov.l	sp,er1
-	subs	#4,er1				/* adjust ret_pc */
-	jsr	@SYMBOL_NAME(do_IRQ)
-	mov.l	@SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
-	beq	1f
-	jsr	@SYMBOL_NAME(do_softirq)
-1:
-	jmp	@SYMBOL_NAME(ret_from_interrupt)
-	
-SYMBOL_NAME_LABEL(system_call)
-	subs	#4,sp				/* dummy LVEC */
-	SAVE_ALL
-	mov.w	@(LCCR:16,sp),r1
-	bset	#4,r1l
-	ldc	r1l,ccr
-	mov.l	er0,er4
-	mov.l	#-ENOSYS,er0
-	mov.l	er0,@(LER0:16,sp)
-
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	cmp.l	#NR_syscalls,er4
-	bcc	SYMBOL_NAME(ret_from_exception):16
-	shll.l	er4
-	shll.l	er4
-	mov.l	#SYMBOL_NAME(sys_call_table),er0
-	add.l	er4,er0
-	mov.l	@er0,er4
-	beq	SYMBOL_NAME(ret_from_exception):16	
-	mov.l	sp,er2
-	and.w	#0xe000,r2
-	mov.b	@((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
-	btst	#(TIF_SYSCALL_TRACE & 7),r2l
-	bne	1f
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-#if defined(CONFIG_SYSCALL_PRINT)
-	jsr	@SYMBOL_NAME(syscall_print)
-#endif
-	bra	SYMBOL_NAME(ret_from_exception):8
-1:
-	jsr	SYMBOL_NAME(syscall_trace)
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-	jsr	@SYMBOL_NAME(syscall_trace)
-	bra	SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(ret_from_fork)
-	mov.l	er2,er0
-	jsr	@SYMBOL_NAME(schedule_tail)
-	bra	SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(reschedule)
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	jsr	@SYMBOL_NAME(schedule)
-
-SYMBOL_NAME_LABEL(ret_from_exception)
-#if defined(CONFIG_PREEMPT)
-	orc	#0x80,ccr
-#endif
-SYMBOL_NAME_LABEL(ret_from_interrupt)
-	mov.b	@(LCCR+1:16,sp),r0l
-	btst	#4,r0l			/* check if returning to kernel */
-	bne	done:8			/* if so, skip resched, signals */
-	andc	#0x7f,ccr
-	mov.l	sp,er4
-	and.w	#0xe000,r4
-	mov.l	@(TI_FLAGS:16,er4),er1
-	and.l	#_TIF_WORK_MASK,er1
-	beq	done:8
-1:
-	mov.l	@(TI_FLAGS:16,er4),er1
-	btst	#TIF_NEED_RESCHED,r1l
-	bne	SYMBOL_NAME(reschedule):16
-	mov.l	sp,er0
-	subs	#4,er0			/* adjust retpc */
-	mov.l	er2,er1
-	jsr	@SYMBOL_NAME(do_signal)
-#if defined(CONFIG_PREEMPT)
-	bra	done:8			/* userspace thoru */
-3:
-	btst	#4,r0l
-	beq	done:8			/* userspace thoru */
-4:
-	mov.l	@(TI_PRE_COUNT:16,er4),er1
-	bne	done:8
-	mov.l	@(TI_FLAGS:16,er4),er1
-	btst	#TIF_NEED_RESCHED,r1l
-	beq	done:8
-	mov.b	r0l,r0l
-	bpl	done:8			/* interrupt off (exception path?) */
-	mov.l	#PREEMPT_ACTIVE,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	andc	#0x7f,ccr
-	jsr	@SYMBOL_NAME(schedule)
-	sub.l	er1,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	orc	#0x80,ccr
-	bra	4b:8
-#endif
-done:
-	RESTORE_ALL			/* Does RTE */
-
-SYMBOL_NAME_LABEL(resume)
-	/*
-	 * Beware - when entering resume, offset of tss is in d1,
-	 * prev (the current task) is in a0, next (the new task)
-	 * is in a1 and d2.b is non-zero if the mm structure is
-	 * shared between the tasks, so don't change these
-	 * registers until their contents are no longer needed.
-	 */
-
-	/* save sr */
-	sub.w	r3,r3
-	stc	ccr,r3l
-	mov.w	r3,@(THREAD_CCR+2:16,er0)
-
-	/* disable interrupts */
-	orc	#0x80,ccr
-	mov.l	@SYMBOL_NAME(sw_usp),er3
-	mov.l	er3,@(THREAD_USP:16,er0)
-	mov.l	sp,@(THREAD_KSP:16,er0)
-
-	/* Skip address space switching if they are the same. */
-	/* FIXME: what did we hack out of here, this does nothing! */
-
-	mov.l	@(THREAD_USP:16,er1),er0
-	mov.l	er0,@SYMBOL_NAME(sw_usp)
-	mov.l	@(THREAD_KSP:16,er1),sp
-			
-	/* restore status register */
-	mov.w	@(THREAD_CCR+2:16,er1),r3
-
-	ldc	r3l,ccr
-	rts
-	
-SYMBOL_NAME_LABEL(trace_break)
-	subs	#4,sp
-	SAVE_ALL
-	sub.l	er1,er1
-	dec.l	#1,er1
-	mov.l	er1,@(LORIG,sp)	
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@er0,er1
-	subs	#2,er1
-	mov.l	er1,@er0	
-	and.w	#0xff,e1
-	mov.l	er1,er0
-	jsr	@SYMBOL_NAME(trace_trap)
-	jmp	@SYMBOL_NAME(ret_from_exception)	
-
-	.section	.bss
-SYMBOL_NAME_LABEL(sw_ksp)
-	.space	4	
-SYMBOL_NAME_LABEL(sw_usp)
-	.space	4	
diff --git a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile
index 0847b15..bf12418 100644
--- a/arch/h8300/platform/h8s/Makefile
+++ b/arch/h8300/platform/h8s/Makefile
@@ -4,4 +4,4 @@
 # Reuse any files we can from the H8S
 #
 
-obj-y := entry.o ints_h8s.o ptrace_h8s.o
+obj-y := ints_h8s.o ptrace_h8s.o
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index b1b2b30..c7c9c2a 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -1212,21 +1212,26 @@
 
 source "fs/Kconfig"
 
-menu "Instrumentation Support"
+menuconfig INSTRUMENTATION
+	bool "Instrumentation Support"
 	depends on EXPERIMENTAL
+	default y
+
+if INSTRUMENTATION
 
 source "arch/i386/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on KALLSYMS && MODULES
 	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".
-endmenu
+
+endif # INSTRUMENTATION
 
 source "arch/i386/Kconfig.debug"
 
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index bd28f9f..181cc29 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -108,6 +108,7 @@
 # must be linked after kernel/
 drivers-$(CONFIG_OPROFILE)		+= arch/i386/oprofile/
 drivers-$(CONFIG_PM)			+= arch/i386/power/
+drivers-$(CONFIG_FB)                    += arch/i386/video/
 
 CFLAGS += $(mflags-y)
 AFLAGS += $(mflags-y)
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 4112afe..47001d5 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -222,6 +222,7 @@
 #include <linux/capability.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
+#include <linux/freezer.h>
 #include <linux/smp.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
@@ -2311,7 +2312,6 @@
 		remove_proc_entry("apm", NULL);
 		return err;
 	}
-	kapmd_task->flags |= PF_NOFREEZE;
 	wake_up_process(kapmd_task);
 
 	if (num_online_cpus() > 1 && !smp ) {
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index f74dfc4..8271466 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -168,6 +168,12 @@
 .section .init.text,"ax",@progbits
 #endif
 
+	/* Do an early initialization of the fixmap area */
+	movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
+	movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax
+	addl $0x007, %eax			/* 0x007 = PRESENT+RW+USER */
+	movl %eax, 4092(%edx)
+
 #ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
 	cld
@@ -507,6 +513,8 @@
 .section ".bss.page_aligned","w"
 ENTRY(swapper_pg_dir)
 	.fill 1024,4,0
+ENTRY(swapper_pg_pmd)
+	.fill 1024,4,0
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
 
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 7f8b7af..21db8f5 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -667,6 +667,7 @@
 		set_pending_irq(i, cpumask_of_cpu(0));
 	}
 
+	set_freezable();
 	for ( ; ; ) {
 		time_remaining = schedule_timeout_interruptible(time_remaining);
 		try_to_freeze();
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index fba121f..03b7f55 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -295,7 +295,7 @@
 	last_irq_sums [NR_CPUS],
 	alert_counter [NR_CPUS];
 
-void touch_nmi_watchdog (void)
+void touch_nmi_watchdog(void)
 {
 	if (nmi_watchdog > 0) {
 		unsigned cpu;
@@ -304,8 +304,10 @@
 		 * Just reset the alert counters, (other CPUs might be
 		 * spinning on locks we hold):
 		 */
-		for_each_present_cpu (cpu)
-			alert_counter[cpu] = 0;
+		for_each_present_cpu(cpu) {
+			if (alert_counter[cpu])
+				alert_counter[cpu] = 0;
+		}
 	}
 
 	/*
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 06dfa65..6c49acb 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -538,8 +538,31 @@
 	return 1;
 }
 
-static noinline void __switch_to_xtra(struct task_struct *next_p,
-				    struct tss_struct *tss)
+#ifdef CONFIG_SECCOMP
+void hard_disable_TSC(void)
+{
+	write_cr4(read_cr4() | X86_CR4_TSD);
+}
+void disable_TSC(void)
+{
+	preempt_disable();
+	if (!test_and_set_thread_flag(TIF_NOTSC))
+		/*
+		 * Must flip the CPU state synchronously with
+		 * TIF_NOTSC in the current running context.
+		 */
+		hard_disable_TSC();
+	preempt_enable();
+}
+void hard_enable_TSC(void)
+{
+	write_cr4(read_cr4() & ~X86_CR4_TSD);
+}
+#endif /* CONFIG_SECCOMP */
+
+static noinline void
+__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+		 struct tss_struct *tss)
 {
 	struct thread_struct *next;
 
@@ -555,6 +578,17 @@
 		set_debugreg(next->debugreg[7], 7);
 	}
 
+#ifdef CONFIG_SECCOMP
+	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+		/* prev and next are different */
+		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
+			hard_disable_TSC();
+		else
+			hard_enable_TSC();
+	}
+#endif
+
 	if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
 		/*
 		 * Disable the bitmap via an invalid offset. We still cache
@@ -586,33 +620,6 @@
 }
 
 /*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
-			       struct task_struct *next_p)
-{
-	struct thread_info *prev, *next;
-
-	/*
-	 * gcc should eliminate the ->thread_info dereference if
-	 * has_secure_computing returns 0 at compile time (SECCOMP=n).
-	 */
-	prev = task_thread_info(prev_p);
-	next = task_thread_info(next_p);
-
-	if (has_secure_computing(prev) || has_secure_computing(next)) {
-		/* slow path here */
-		if (has_secure_computing(prev) &&
-		    !has_secure_computing(next)) {
-			write_cr4(read_cr4() & ~X86_CR4_TSD);
-		} else if (!has_secure_computing(prev) &&
-			   has_secure_computing(next))
-			write_cr4(read_cr4() | X86_CR4_TSD);
-	}
-}
-
-/*
  *	switch_to(x,yn) should switch tasks from x to y.
  *
  * We fsave/fwait so that an exception goes off at the right time
@@ -689,11 +696,9 @@
 	/*
 	 * Now maybe handle debug registers and/or IO bitmaps
 	 */
-	if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)
-	    || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)))
-		__switch_to_xtra(next_p, tss);
-
-	disable_tsc(prev_p, next_p);
+	if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
+		     task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
+		__switch_to_xtra(prev_p, next_p, tss);
 
 	/*
 	 * Leave lazy mode, flushing any hypercalls made here.
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 0c0ceec..1c075f5 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -358,17 +358,9 @@
 	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, datap);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -395,10 +387,7 @@
 	/* when 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;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 90da057..18c1c28 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -390,7 +390,7 @@
 		unsigned long esp;
 		unsigned short ss;
 
-		report_bug(regs->eip);
+		report_bug(regs->eip, regs);
 
 		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
@@ -433,6 +433,7 @@
 
 	bust_spinlocks(0);
 	die.lock_owner = -1;
+	add_taint(TAINT_DIE);
 	spin_unlock_irqrestore(&die.lock, flags);
 
 	if (!regs)
diff --git a/arch/i386/video/Makefile b/arch/i386/video/Makefile
new file mode 100644
index 0000000..2c447c9
--- /dev/null
+++ b/arch/i386/video/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_FB)               += fbdev.o
diff --git a/arch/i386/video/fbdev.c b/arch/i386/video/fbdev.c
new file mode 100644
index 0000000..48fb38d
--- /dev/null
+++ b/arch/i386/video/fbdev.c
@@ -0,0 +1,32 @@
+/*
+ * arch/i386/video/fbdev.c - i386 Framebuffer
+ *
+ * Copyright (C) 2007 Antonino Daplas <adaplas@gmail.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
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/pci.h>
+
+int fb_is_primary_device(struct fb_info *info)
+{
+	struct device *device = info->device;
+	struct pci_dev *pci_dev = NULL;
+	struct resource *res = NULL;
+	int retval = 0;
+
+	if (device)
+		pci_dev = to_pci_dev(device);
+
+	if (pci_dev)
+		res = &pci_dev->resource[PCI_ROM_RESOURCE];
+
+	if (res && res->flags & IORESOURCE_ROM_SHADOW)
+		retval = 1;
+
+	return retval;
+}
+EXPORT_SYMBOL(fb_is_primary_device);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index db9ddff..616c96e 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -582,8 +582,8 @@
 source "arch/ia64/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on KALLSYMS && MODULES
 	help
 	  Kprobes allows you to trap at almost any kernel address and
 	  execute a callback function.  register_kprobe() establishes
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index c1dca22..cd4adf5 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -34,6 +34,7 @@
 #include <linux/efi.h>
 #include <linux/nodemask.h>
 #include <linux/bitops.h>         /* hweight64() */
+#include <linux/crash_dump.h>
 
 #include <asm/delay.h>		/* ia64_get_itc() */
 #include <asm/io.h>
@@ -43,6 +44,8 @@
 
 #include <asm/acpi-ext.h>
 
+extern int swiotlb_late_init_with_default_size (size_t size);
+
 #define PFX "IOC: "
 
 /*
@@ -2026,11 +2029,24 @@
 	if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
 		return 0;
 
+#if defined(CONFIG_IA64_GENERIC) && defined(CONFIG_CRASH_DUMP)
+	/* If we are booting a kdump kernel, the sba_iommu will
+	 * cause devices that were not shutdown properly to MCA
+	 * as soon as they are turned back on.  Our only option for
+	 * a successful kdump kernel boot is to use the swiotlb.
+	 */
+	if (elfcorehdr_addr < ELFCORE_ADDR_MAX) {
+		if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
+			panic("Unable to initialize software I/O TLB:"
+				  " Try machvec=dig boot option");
+		machvec_init("dig");
+		return 0;
+	}
+#endif
+
 	acpi_bus_register_driver(&acpi_sba_ioc_driver);
 	if (!ioc_list) {
 #ifdef CONFIG_IA64_GENERIC
-		extern int swiotlb_late_init_with_default_size (size_t size);
-
 		/*
 		 * If we didn't find something sba_iommu can claim, we
 		 * need to setup the swiotlb and switch to the dig machvec.
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c
index 300acd9..1189d03 100644
--- a/arch/ia64/hp/sim/boot/fw-emu.c
+++ b/arch/ia64/hp/sim/boot/fw-emu.c
@@ -329,11 +329,6 @@
 	strcpy(sal_systab->product_id, "HP-simulator");
 #endif
 
-#ifdef CONFIG_IA64_SDV
-	strcpy(sal_systab->oem_id, "Intel");
-	strcpy(sal_systab->product_id, "SDV");
-#endif
-
 	/* fill in an entry point: */
 	sal_ed->type = SAL_DESC_ENTRY_POINT;
 	sal_ed->pal_proc = __pa(pal_desc[0]);
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 324ea75..ef252df 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -36,10 +36,6 @@
 #include <asm/hw_irq.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_KDB
-# include <linux/kdb.h>
-#endif
-
 #undef SIMSERIAL_DEBUG	/* define this to get some debug information */
 
 #define KEYBOARD_INTR	3	/* must match with simulator! */
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index c05bda6..6f4d3d0 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -261,7 +261,7 @@
 }
 
 static unsigned long
-elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
 {
 	unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
 
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 99b665e..06efd1f 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -304,7 +304,7 @@
 	data8 sys_ni_syscall	/* init_module */
 	data8 sys_ni_syscall	/* delete_module */
 	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
-	data8 sys_quotactl
+	data8 sys32_quotactl
 	data8 sys_getpgid
 	data8 sys_fchdir
 	data8 sys_ni_syscall	/* sys_bdflush */
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 75ec347..73ca86d 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -28,6 +28,7 @@
 #include <linux/time.h>
 #include <linux/efi.h>
 #include <linux/kexec.h>
+#include <linux/mm.h>
 
 #include <asm/io.h>
 #include <asm/kregs.h>
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 8589e84..3f926c2 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -247,6 +247,9 @@
 .time_redo:
 	.pred.rel.mutex p8,p9,p10
 	ld4.acq r28 = [r29]	// xtime_lock.sequence. Must come first for locking purposes
+	;;
+	and r28 = ~1,r28	// Make sequence even to force retry if odd
+	;;
 (p8)	mov r2 = ar.itc		// CPU_TIMER. 36 clocks latency!!!
 	add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20
 (p9)	ld8 r2 = [r30]		// readq(ti->address). Could also have latency issues..
@@ -284,7 +287,6 @@
 (p15)	ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET
 (p7)	cmp.ne p7,p0 = r25,r3	// if cmpxchg not successful redo
 	// simulate tbit.nz.or p7,p0 = r28,0
-	and r28 = ~1,r28	// Make sequence even to force retry if odd
 	getf.sig r2 = f8
 	mf
 	add r8 = r8,r18		// Add time interpolator offset
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 188fb73..4d9864c 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -390,10 +390,6 @@
 	if (!efi_setup_pcdp_console(cmdline))
 		earlycons++;
 #endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-	if (!early_serial_console_init(cmdline))
-		earlycons++;
-#endif
 
 	return (earlycons) ? 0 : -1;
 }
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 15ad85d..3aeaf15 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -69,6 +69,7 @@
 
 	bust_spinlocks(0);
 	die.lock_owner = -1;
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die.lock);
 
 	if (panic_on_oops)
diff --git a/arch/ia64/lib/checksum.c b/arch/ia64/lib/checksum.c
index 4411d9b..9fc9550 100644
--- a/arch/ia64/lib/checksum.c
+++ b/arch/ia64/lib/checksum.c
@@ -60,6 +60,7 @@
 	result = (result & 0xffffffff) + (result >> 32);
 	return (__force __wsum)result;
 }
+EXPORT_SYMBOL(csum_tcpudp_nofold);
 
 extern unsigned long do_csum (const unsigned char *, long);
 
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 6da9854..df8d5be 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -750,9 +750,10 @@
 			goto error;
 		} else
 		if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
+			int cpuobj_index = 0;
+
 			memset(p, 0, a.sz);
 			for (i = 0; i < nobj; i++) {
-				int cpuobj_index = 0;
 				if (!SN_HWPERF_IS_NODE(objs + i))
 					continue;
 				node = sn_hwperf_obj_to_cnode(objs + i);
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index c3bb8a7..8ccf3e4 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -31,6 +31,9 @@
 config NO_IOPORT
 	def_bool y
 
+config NO_DMA
+	def_bool y
+
 source "init/Kconfig"
 
 
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 5f02b31..57a92ef 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -595,7 +595,6 @@
 static int
 do_ptrace(long request, struct task_struct *child, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	switch (request) {
@@ -604,11 +603,7 @@
 	 */
 	case PTRACE_PEEKTEXT:
 	case PTRACE_PEEKDATA:
-		ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (ret == sizeof(tmp))
-			ret = put_user(tmp,(unsigned long __user *) data);
-		else
-			ret = -EIO;
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
 
 	/*
@@ -624,15 +619,9 @@
 	 */
 	case PTRACE_POKETEXT:
 	case PTRACE_POKEDATA:
-		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
-		if (ret == sizeof(data)) {
-			ret = 0;
-			if (request == PTRACE_POKETEXT) {
-				invalidate_cache();
-			}
-		} else {
-			ret = -EIO;
-		}
+		ret = generic_ptrace_pokedata(child, addr, data);
+		if (ret == 0 && request == PTRACE_POKETEXT)
+			invalidate_cache();
 		break;
 
 	/*
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index cdba9fd..2cf0690 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -128,10 +128,7 @@
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT:	/* read word at location addr. */
 	case PTRACE_PEEKDATA:
-		i = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (i != sizeof(tmp))
-			goto out_eio;
-		ret = put_user(tmp, (unsigned long *)data);
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
 
 	/* read the word at location addr in the USER area. */
@@ -160,8 +157,7 @@
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT:	/* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
-			goto out_eio;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR:	/* write the word at location addr in the USER area */
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index a27a4fa..4e2752a 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -1170,6 +1170,7 @@
 	console_verbose();
 	printk("%s: %08x\n",str,nr);
 	show_registers(fp);
+	add_taint(TAINT_DIE);
 	do_exit(SIGSEGV);
 }
 
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index cf6bb51..6216f12 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -422,3 +422,4 @@
 	    );
     return(sum);
 }
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 941955d..846f975 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -377,7 +377,7 @@
 	fp = ((struct switch_stack *)p->thread.ksp)->a6;
 	do {
 		if (fp < stack_page+sizeof(struct thread_info) ||
-		    fp >= 8184+stack_page)
+		    fp >= THREAD_SIZE-8+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
 		if (!in_sched_functions(pc))
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index f54b6a3..ef70ca0 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -106,17 +106,9 @@
 	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 *) data);
+		case PTRACE_PEEKDATA:
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
-		}
 
 		/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
@@ -159,10 +151,7 @@
 		/* when 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;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 8133b10..80f4e9d 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -1,8 +1,8 @@
 /*
  *  linux/arch/m68knommu/kernel/setup.c
  *
- *  Copyright (C) 1999-2004  Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@lineo.ca>
+ *  Copyright (C) 1999-2007  Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uClinux.org>
  *  Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
  *  Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
  *  Copyright (C) 1995       Hamish Macdonald
@@ -20,17 +20,13 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/fs.h>
 #include <linux/fb.h>
 #include <linux/module.h>
 #include <linux/console.h>
-#include <linux/genhd.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/major.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 #include <linux/init.h>
 
 #include <asm/setup.h>
@@ -46,34 +42,19 @@
 
 char __initdata command_line[COMMAND_LINE_SIZE];
 
-/* setup some dummy routines */
-static void dummy_waitbut(void)
-{
-}
+void (*mach_trap_init)(void);
 
-void (*mach_sched_init) (irq_handler_t handler);
-void (*mach_tick)( void );
-/* machine dependent keyboard functions */
-int (*mach_keyb_init) (void);
-int (*mach_kbdrate) (struct kbd_repeat *);
-void (*mach_kbd_leds) (unsigned int);
-/* machine dependent irq functions */
-void (*mach_init_IRQ) (void);
-irq_handler_t mach_default_handler;
-int (*mach_get_irq_list) (struct seq_file *, void *);
-void (*mach_process_int) (int irq, struct pt_regs *fp);
-void (*mach_trap_init) (void);
 /* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
-void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
-int (*mach_hwclk) (int, struct rtc_time*);
-int (*mach_set_clock_mmss) (unsigned long);
-void (*mach_mksound)( unsigned int count, unsigned int ticks );
-void (*mach_reset)( void );
-void (*waitbut)(void) = dummy_waitbut;
-void (*mach_debug_init)(void);
-void (*mach_halt)( void );
-void (*mach_power_off)( void );
+void (*mach_sched_init)(irq_handler_t handler);
+void (*mach_tick)(void);
+void (*mach_gettod)(int*, int*, int*, int*, int*, int*);
+int (*mach_set_clock_mmss)(unsigned long);
+unsigned long (*mach_gettimeoffset)(void);
+
+/* machine dependent reboot functions */
+void (*mach_reset)(void);
+void (*mach_halt)(void);
+void (*mach_power_off)(void);
 
 
 #ifdef CONFIG_M68000
@@ -134,13 +115,6 @@
 	#define	CPU "UNKNOWN"
 #endif
 
-/* (es) */
-/* note: why is this defined here?  the must be a better place to put this */
-#if defined( CONFIG_TELOS) || defined( CONFIG_UCDIMM ) || defined( CONFIG_UCSIMM ) || defined(CONFIG_DRAGEN2) || (defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ))
-#define CAT_ROMARRAY
-#endif
-/* (/es) */
-
 extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
 extern int _ramstart, _ramend;
 
@@ -148,15 +122,8 @@
 {
 	int bootmap_size;
 
-#if defined(CAT_ROMARRAY) && defined(DEBUG)
-	extern int __data_rom_start;
-	extern int __data_start;
-	int *romarray = (int *)((int) &__data_rom_start +
-			      (int)&_edata - (int)&__data_start);
-#endif
-
 	memory_start = PAGE_ALIGN(_ramstart);
-	memory_end = _ramend; /* by now the stack is part of the init task */
+	memory_end = _ramend;
 
 	init_mm.start_code = (unsigned long) &_stext;
 	init_mm.end_code = (unsigned long) &_etext;
@@ -220,11 +187,7 @@
 		(int) &_sbss, (int) &_ebss);
 	printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
 		"STACK=0x%06x-0x%06x\n",
-#ifdef CAT_ROMARRAY
-		(int) romarray, ((int) romarray) + romarray[2],
-#else
 		(int) &_ebss, (int) memory_start,
-#endif
 		(int) memory_start, (int) memory_end,
 		(int) memory_end, (int) _ramend);
 #endif
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index bed5f47..fde04e1 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -83,6 +83,7 @@
 	printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
 		current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
 	show_stack(NULL, (unsigned long *)fp);
+	add_taint(TAINT_DIE);
 	do_exit(SIGSEGV);
 }
 
diff --git a/arch/m68knommu/mm/memory.c b/arch/m68knommu/mm/memory.c
index 411e452..1a66b71 100644
--- a/arch/m68knommu/mm/memory.c
+++ b/arch/m68knommu/mm/memory.c
@@ -17,90 +17,14 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 
-#include <asm/setup.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
-#include <asm/traps.h>
-#include <asm/io.h>
 
 /*
- * cache_clear() semantics: Clear any cache entries for the area in question,
- * without writing back dirty entries first. This is useful if the data will
- * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
- * _physical_ address.
- */
-
-void cache_clear (unsigned long paddr, int len)
-{
-}
-
-
-/*
- *	Define cache invalidate functions. The ColdFire 5407 is really
- *	the only processor that needs to do some work here. Anything
- *	that has separate data and instruction caches will be a problem.
- */
-#ifdef CONFIG_M5407
-
-static __inline__ void cache_invalidate_lines(unsigned long paddr, int len)
-{
-	unsigned long	sset, eset;
-
-	sset = (paddr & 0x00000ff0);
-	eset = ((paddr + len) & 0x0000ff0) + 0x10;
-
-	__asm__ __volatile__ (
-		"nop\n\t"
-		"clrl	%%d0\n\t"
-		"1:\n\t"
-		"movel	%0,%%a0\n\t"
-		"addl	%%d0,%%a0\n\t"
-		"2:\n\t"
-		".word	0xf4e8\n\t"
-		"addl	#0x10,%%a0\n\t"
-		"cmpl	%1,%%a0\n\t"
-		"blt	2b\n\t"
-		"addql	#1,%%d0\n\t"
-		"cmpil	#4,%%d0\n\t"
-		"bne	1b"
-		: : "a" (sset), "a" (eset) : "d0", "a0" );
-}
-
-#else
-#define	cache_invalidate_lines(a,b)
-#endif
-
-
-/*
- * cache_push() semantics: Write back any dirty cache data in the given area,
- * and invalidate the range in the instruction cache. It needs not (but may)
- * invalidate those entries also in the data cache. The range is defined by a
- * _physical_ address.
- */
-
-void cache_push (unsigned long paddr, int len)
-{
-	cache_invalidate_lines(paddr, len);
-}
-
-
-/*
- * cache_push_v() semantics: Write back any dirty cache data in the given
- * area, and invalidate those entries at least in the instruction cache. This
- * is intended to be used after data has been written that can be executed as
- * code later. The range is defined by a _user_mode_ _virtual_ address  (or,
- * more exactly, the space is defined by the %sfc/%dfc register.)
- */
-
-void cache_push_v (unsigned long vaddr, int len)
-{
-	cache_invalidate_lines(vaddr, len);
-}
-
-/* Map some physical address range into the kernel address space. The
- * code is copied and adapted from map_chunk().
+ * Map some physical address range into the kernel address space.
+ * The code is copied and adapted from map_chunk().
  */
 
 unsigned long kernel_map(unsigned long paddr, unsigned long size,
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index b5a7b46..893e7bc 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -174,17 +174,9 @@
 	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);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* Read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -313,11 +305,7 @@
 	/* when 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;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 37c562c..ce277cb 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -326,6 +326,7 @@
 #endif /* CONFIG_MIPS_MT_SMTC */
 	printk("%s[#%d]:\n", str, ++die_counter);
 	show_registers(regs);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (in_interrupt())
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
index bdaac34..89f2923 100644
--- a/arch/mips/sibyte/bcm1480/setup.c
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -31,6 +31,7 @@
 unsigned int sb1_pass;
 unsigned int soc_pass;
 unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
 unsigned int periph_rev;
 unsigned int zbbus_mhz;
 
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index f4a6169..2d5c6d8 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -31,6 +31,7 @@
 unsigned int sb1_pass;
 unsigned int soc_pass;
 unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
 unsigned int periph_rev;
 unsigned int zbbus_mhz;
 EXPORT_SYMBOL(zbbus_mhz);
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 8a0db37..26ec774 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -87,10 +87,9 @@
 	switch (request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
-		int copied;
-
 #ifdef CONFIG_64BIT
 		if (__is_compat_task(child)) {
+			int copied;
 			unsigned int tmp;
 
 			addr &= 0xffffffffL;
@@ -105,15 +104,7 @@
 		}
 		else
 #endif
-		{
-			unsigned long tmp;
-
-			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-			ret = -EIO;
-			if (copied != sizeof(tmp))
-				goto out_tsk;
-			ret = put_user(tmp,(unsigned long *) data);
-		}
+			ret = generic_ptrace_peekdata(child, addr, data);
 		goto out_tsk;
 	}
 
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index c3ec9f1..bbf029a 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -264,6 +264,7 @@
 
 	show_regs(regs);
 	dump_stack();
+	add_taint(TAINT_DIE);
 
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
@@ -302,7 +303,7 @@
 	if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) {
 		/* check if a BUG() or WARN() trapped here.  */
 		enum bug_trap_type tt;
-		tt = report_bug(regs->iaoq[0] & ~3);
+		tt = report_bug(regs->iaoq[0] & ~3, regs);
 		if (tt == BUG_TRAP_TYPE_WARN) {
 			regs->iaoq[0] += 4;
 			regs->iaoq[1] += 4;
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 3221677..cf780cb 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -242,7 +242,7 @@
 #ifdef CONFIG_KALLSYMS
 		/* Handle some frequent special cases.... */
 		{
-			char symname[KSYM_NAME_LEN+1];
+			char symname[KSYM_NAME_LEN];
 			char *modname;
 
 			kallsyms_lookup(info->ip, NULL, NULL, &modname,
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6beee32..d860b64 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -4,17 +4,7 @@
 
 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 PPC_PM_NEEDS_RTC_LIB
-	bool
-	select RTC_LIB
-	default y if PM
+source "arch/powerpc/platforms/Kconfig.cputype"
 
 config PPC32
 	bool
@@ -66,6 +56,9 @@
 	bool
 	default y
 
+config ARCH_NO_VIRT_TO_BUS
+	def_bool PPC64
+
 config PPC
 	bool
 	default y
@@ -132,123 +125,6 @@
 	depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
 	default y
 
-menu "Processor support"
-choice
-	prompt "Processor Type"
-	depends on PPC32
-	default 6xx
-
-config CLASSIC32
-	bool "52xx/6xx/7xx/74xx"
-	select PPC_FPU
-	select 6xx
-	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).
-
-	  This option is the catch-all for 6xx types, including some of the
-	  embedded versions.  Unless there is see an option for the specific
-	  chip family you are using, you want this option.
-	  
-	  You do not want this if you are building a kernel for a 64 bit
-	  IBM RS/6000 or an Apple G5, choose 6xx.
-	  
-	  If unsure, select this option
-	  
-	  Note that the kernel runs in 32-bit mode even on 64-bit chips.
-
-config PPC_82xx
-	bool "Freescale 82xx"
-	select 6xx
-	select PPC_FPU
-
-config PPC_83xx
-	bool "Freescale 83xx"
-	select 6xx
-	select FSL_SOC
-	select 83xx
-	select PPC_FPU
-	select WANT_DEVICE_TREE
-
-config PPC_85xx
-	bool "Freescale 85xx"
-	select E500
-	select FSL_SOC
-	select 85xx
-	select WANT_DEVICE_TREE
-
-config PPC_86xx
-	bool "Freescale 86xx"
-	select 6xx
-	select FSL_SOC
-	select FSL_PCIE
-	select PPC_FPU
-	select ALTIVEC
-	help
-	  The Freescale E600 SoCs have 74xx cores.
-
-config PPC_8xx
-	bool "Freescale 8xx"
-	select FSL_SOC
-	select 8xx
-
-config 40x
-	bool "AMCC 40x"
-	select PPC_DCR_NATIVE
-
-config 44x
-	bool "AMCC 44x"
-	select PPC_DCR_NATIVE
-	select WANT_DEVICE_TREE
-
-config E200
-	bool "Freescale e200"
-
-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 6xx
-	bool
-
-# this is temp to handle compat with arch=ppc
-config 8xx
-	bool
-
-# this is temp to handle compat with arch=ppc
-config 83xx
-	bool
-
-# this is temp to handle compat with arch=ppc
-config 85xx
-	bool
-
-config E500
-	bool
-
-config PPC_FPU
-	bool
-	default y if PPC64
-
 config PPC_DCR_NATIVE
 	bool
 	default n
@@ -267,134 +143,6 @@
 	depends on PPC64 # not supported on 32 bits yet
 	default n
 
-config 4xx
-	bool
-	depends on 40x || 44x
-	default y
-
-config BOOKE
-	bool
-	depends on E200 || E500 || 44x
-	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
-	select RESOURCES_64BIT
-	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 CLASSIC32 || 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
-	default y
-	---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 PPC_MM_SLICES
-	bool
-	default y if HUGETLB_PAGE
-	default n
-
-config VIRT_CPU_ACCOUNTING
-	bool "Deterministic task and CPU time accounting"
-	depends on PPC64
-	default y
-	help
-	  Select this option to enable more accurate task and CPU time
-	  accounting.  This is done by reading a CPU counter on each
-	  kernel entry and exit and on transitions within the kernel
-	  between system, softirq and hardirq state, so there is a
-	  small performance impact.  This also enables accounting of
-	  stolen time on logically-partitioned systems running on
-	  IBM POWER5-based machines.
-
-	  If in doubt, say Y here.
-
-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-128)"
-	range 2 128
-	depends on SMP
-	default "32" if PPC64
-	default "4"
-
-config NOT_COHERENT_CACHE
-	bool
-	depends on 4xx || 8xx || E200
-	default y
-
-config CONFIG_CHECK_CACHE_COHERENCY
-	bool
-endmenu
-
 source "init/Kconfig"
 
 source "arch/powerpc/platforms/Kconfig"
@@ -674,10 +422,6 @@
 config FSL_SOC
 	bool
 
-config FSL_PCIE
-	bool
-	depends on PPC_86xx
-
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 config MCA
 	bool
@@ -685,10 +429,10 @@
 config PCI
 	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
 		|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
-		|| MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
-	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
+		|| PPC_PS3
+	default y if !40x && !CPM2 && !8xx && !PPC_83xx \
 		&& !PPC_85xx && !PPC_86xx
-	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
+	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
 	select ARCH_SUPPORTS_MSI
 	help
@@ -896,8 +640,8 @@
 source "arch/powerpc/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on !BOOKE && !4xx && KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on !BOOKE && !4xx && KALLSYMS && MODULES
 	help
 	  Kprobes allows you to trap at almost any kernel address and
 	  execute a callback function.  register_kprobe() establishes
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index fbafd96..187a39a 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -148,7 +148,7 @@
 
 CPPFLAGS_vmlinux.lds	:= -Upowerpc
 
-BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage
+BOOT_TARGETS = zImage zImage.initrd uImage
 
 PHONY += $(BOOT_TARGETS)
 
diff --git a/arch/powerpc/boot/44x.c b/arch/powerpc/boot/44x.c
index d51377d..9f64e84 100644
--- a/arch/powerpc/boot/44x.c
+++ b/arch/powerpc/boot/44x.c
@@ -38,3 +38,48 @@
 
 	dt_fixup_memory(0, memsize);
 }
+
+#define SPRN_DBCR0		0x134
+#define   DBCR0_RST_SYSTEM	0x30000000
+
+void ibm44x_dbcr_reset(void)
+{
+	unsigned long tmp;
+
+	asm volatile (
+		"mfspr	%0,%1\n"
+		"oris	%0,%0,%2@h\n"
+		"mtspr	%1,%0"
+		: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
+		);
+
+}
+
+/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
+ * banks into the OPB address space */
+void ibm4xx_fixup_ebc_ranges(const char *ebc)
+{
+	void *devp;
+	u32 bxcr;
+	u32 ranges[EBC_NUM_BANKS*4];
+	u32 *p = ranges;
+	int i;
+
+	for (i = 0; i < EBC_NUM_BANKS; i++) {
+		mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
+		bxcr = mfdcr(DCRN_EBC0_CFGDATA);
+
+		if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
+			*p++ = i;
+			*p++ = 0;
+			*p++ = bxcr & EBC_BXCR_BAS;
+			*p++ = EBC_BXCR_BANK_SIZE(bxcr);
+		}
+	}
+
+	devp = finddevice(ebc);
+	if (! devp)
+		fatal("Couldn't locate EBC node %s\n\r", ebc);
+
+	setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
+}
diff --git a/arch/powerpc/boot/44x.h b/arch/powerpc/boot/44x.h
index 7b129ad..577982c 100644
--- a/arch/powerpc/boot/44x.h
+++ b/arch/powerpc/boot/44x.h
@@ -11,6 +11,9 @@
 #define _PPC_BOOT_44X_H_
 
 void ibm44x_fixup_memsize(void);
+void ibm4xx_fixup_ebc_ranges(const char *ebc);
+
+void ibm44x_dbcr_reset(void);
 void ebony_init(void *mac0, void *mac1);
 
 #endif /* _PPC_BOOT_44X_H_ */
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index ff27019..61a6f34 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -43,10 +43,11 @@
 
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
 		ns16550.c serial.c simple_alloc.c div64.S util.S \
-		gunzip_util.c elf_util.c $(zlib) devtree.c \
-		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
+		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
+		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
 src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
-		cuboot-ebony.c treeboot-ebony.c prpmc2800.c
+		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
+		ps3-head.S ps3-hvcall.S ps3.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -75,11 +76,11 @@
 $(obj)/empty.c:
 	@touch $@
 
-$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
+$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
 	@cp $< $@
 
 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
-		empty.c zImage.coff.lds zImage.lds
+		empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds
 
 quiet_cmd_bootcc = BOOTCC  $@
       cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -102,7 +103,7 @@
 
 targets		+= $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y		:= $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
-		   $(obj)/zImage.lds $(obj)/zImage.coff.lds
+		   $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
 
 wrapper		:=$(srctree)/$(src)/wrapper
 wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
@@ -132,7 +133,7 @@
 image-$(CONFIG_PPC_CHRP)		+= zImage.chrp
 image-$(CONFIG_PPC_EFIKA)		+= zImage.chrp
 image-$(CONFIG_PPC_PMAC)		+= zImage.pmac
-image-$(CONFIG_PPC_HOLLY)		+= zImage.holly-elf
+image-$(CONFIG_PPC_HOLLY)		+= zImage.holly
 image-$(CONFIG_PPC_PRPMC2800)		+= zImage.prpmc2800
 image-$(CONFIG_PPC_ISERIES)		+= zImage.iseries
 image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
@@ -157,55 +158,43 @@
 
 $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
 
-dts-  := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-))
-dts-y := $(patsubst zImage%, zImage.dts%, $(image-y))
-dts-y := $(filter-out $(image-y), $(dts-y))
-targets	+= $(image-y) $(dts-y)
-
-dts_initrd-  := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-))
-dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y))
-dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y))
-targets	+= $(image-y) $(dts_initrd-y)
-
-$(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz
+# If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an
+# empty string, define 'dts' to be path to the dts
+# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
+ifeq ($(CONFIG_WANT_DEVICE_TREE),y)
+ifneq ($(CONFIG_DEVICE_TREE),"")
+dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
+	,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
+endif
+endif
 
 # Don't put the ramdisk on the pattern rule; when its missing make will try
 # the pattern rule with less dependencies that also matches (even with the
 # hard dependency listed).
-$(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz
+$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts)
 	$(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz)
 
-$(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts)
+$(obj)/zImage.%: vmlinux $(wrapperbits) $(dts)
 	$(call if_changed,wrap,$*,$(dts))
 
-$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
-	$(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
-
-$(obj)/zImage.%: vmlinux $(wrapperbits)
-	$(call if_changed,wrap,$*)
+# This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
+# prefix
+$(obj)/vmlinux.strip: vmlinux
+	$(STRIP) -s -R .comment $< -o $@
 
 $(obj)/zImage.iseries: vmlinux
 	$(STRIP) -s -R .comment $< -o $@
 
-$(obj)/zImage.ps3: vmlinux
-	$(STRIP) -s -R .comment $< -o $@
+$(obj)/zImage.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
+	$(STRIP) -s -R .comment $< -o vmlinux.strip
+	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
 
-$(obj)/zImage.initrd.ps3: vmlinux
-	@echo "  WARNING zImage.initrd.ps3 not supported (yet)"
-
-$(obj)/zImage.holly-elf: vmlinux $(wrapperbits)
-	$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,)
-
-$(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz
-	$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz)
+$(obj)/zImage.initrd.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
+	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
 
 $(obj)/uImage: vmlinux $(wrapperbits)
 	$(call if_changed,wrap,uboot)
 
-# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
-dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
-	,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
-
 $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits)
 	$(call if_changed,wrap,cuboot-$*,$(dts))
 
@@ -215,22 +204,22 @@
 $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits)
 	$(call if_changed,wrap,treeboot-$*,$(dts))
 
+# If there isn't a platform selected then just strip the vmlinux.
+ifeq (,$(image-y))
+image-y := vmlinux.strip
+endif
+
 $(obj)/zImage:		$(addprefix $(obj)/, $(image-y))
 	@rm -f $@; ln $< $@
 $(obj)/zImage.initrd:	$(addprefix $(obj)/, $(initrd-y))
 	@rm -f $@; ln $< $@
-$(obj)/zImage.dts:	$(addprefix $(obj)/, $(dts-y))
-	@rm -f $@; ln $< $@
-$(obj)/zImage.dts_initrd:	$(addprefix $(obj)/, $(dts_initrd-y))
-	@rm -f $@; ln $< $@
-
 
 install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
 	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
 
 # anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
-	treeImage.* zImage.dts zImage.dts_initrd
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+	otheros.bld
 
 # clean up files cached by wrapper
 clean-kernel := vmlinux.strip vmlinux.bin
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c
index 9af554e..296025d 100644
--- a/arch/powerpc/boot/cuboot-83xx.c
+++ b/arch/powerpc/boot/cuboot-83xx.c
@@ -12,12 +12,12 @@
 
 #include "ops.h"
 #include "stdio.h"
+#include "cuboot.h"
 
 #define TARGET_83xx
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
 extern char _dtb_start[], _dtb_end[];
 
 static void platform_fixups(void)
@@ -52,16 +52,7 @@
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-	memcpy(&bd, (bd_t *)r3, sizeof(bd));
-	loader_info.initrd_addr = r4;
-	loader_info.initrd_size = r4 ? r5 - r4 : 0;
-	loader_info.cmdline = (char *)r6;
-	loader_info.cmdline_len = r7 - r6;
-
-	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+	CUBOOT_INIT();
 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c
index e256031..10f0f69 100644
--- a/arch/powerpc/boot/cuboot-85xx.c
+++ b/arch/powerpc/boot/cuboot-85xx.c
@@ -12,12 +12,12 @@
 
 #include "ops.h"
 #include "stdio.h"
+#include "cuboot.h"
 
 #define TARGET_85xx
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
 extern char _dtb_start[], _dtb_end[];
 
 static void platform_fixups(void)
@@ -53,16 +53,7 @@
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-	memcpy(&bd, (bd_t *)r3, sizeof(bd));
-	loader_info.initrd_addr = r4;
-	loader_info.initrd_size = r4 ? r5 - r4 : 0;
-	loader_info.cmdline = (char *)r6;
-	loader_info.cmdline_len = r7 - r6;
-
-	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+	CUBOOT_INIT();
 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
diff --git a/arch/powerpc/boot/cuboot-ebony.c b/arch/powerpc/boot/cuboot-ebony.c
index 4464c5f..c5f37ce 100644
--- a/arch/powerpc/boot/cuboot-ebony.c
+++ b/arch/powerpc/boot/cuboot-ebony.c
@@ -15,28 +15,16 @@
 #include "ops.h"
 #include "stdio.h"
 #include "44x.h"
+#include "cuboot.h"
 
 #define TARGET_44x
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
-
-BSS_STACK(4096);
 
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-	memcpy(&bd, (bd_t *)r3, sizeof(bd));
-	loader_info.initrd_addr = r4;
-	loader_info.initrd_size = r4 ? r5 : 0;
-	loader_info.cmdline = (char *)r6;
-	loader_info.cmdline_len = r7 - r6;
-
-	simple_alloc_init(_end, avail_ram, 32, 64);
-
+	CUBOOT_INIT();
 	ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
 }
diff --git a/arch/powerpc/boot/cuboot.c b/arch/powerpc/boot/cuboot.c
new file mode 100644
index 0000000..6579546
--- /dev/null
+++ b/arch/powerpc/boot/cuboot.c
@@ -0,0 +1,35 @@
+/*
+ * Compatibility for old (not device tree aware) U-Boot versions
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au>
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ * Copyright (c) 2007 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 version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "stdio.h"
+
+#include "ppcboot.h"
+
+extern char _end[];
+extern char _dtb_start[], _dtb_end[];
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+		 unsigned long r6, unsigned long r7,
+		 unsigned long end_of_ram)
+{
+	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
+
+	loader_info.initrd_addr = r4;
+	loader_info.initrd_size = r4 ? r5 - r4 : 0;
+	loader_info.cmdline = (char *)r6;
+	loader_info.cmdline_len = r7 - r6;
+
+	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+}
diff --git a/arch/powerpc/boot/cuboot.h b/arch/powerpc/boot/cuboot.h
new file mode 100644
index 0000000..cd2aa7f
--- /dev/null
+++ b/arch/powerpc/boot/cuboot.h
@@ -0,0 +1,14 @@
+#ifndef _PPC_BOOT_CUBOOT_H_
+#define _PPC_BOOT_CUBOOT_H_
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+		 unsigned long r6, unsigned long r7,
+		 unsigned long end_of_ram);
+
+#define CUBOOT_INIT() \
+	do { \
+		memcpy(&bd, (bd_t *)r3, sizeof(bd)); \
+		cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \
+	} while (0)
+
+#endif /* _PPC_BOOT_CUBOOT_H_ */
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h
index 877bc97..14b44aa 100644
--- a/arch/powerpc/boot/dcr.h
+++ b/arch/powerpc/boot/dcr.h
@@ -26,6 +26,43 @@
 #define			SDRAM_CONFIG_BANK_SIZE(reg)	\
 	(0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
 
+/* 440GP External Bus Controller (EBC) */
+#define DCRN_EBC0_CFGADDR				0x012
+#define DCRN_EBC0_CFGDATA				0x013
+#define   EBC_NUM_BANKS					  8
+#define   EBC_B0CR					  0x00
+#define   EBC_B1CR					  0x01
+#define   EBC_B2CR					  0x02
+#define   EBC_B3CR					  0x03
+#define   EBC_B4CR					  0x04
+#define   EBC_B5CR					  0x05
+#define   EBC_B6CR					  0x06
+#define   EBC_B7CR					  0x07
+#define   EBC_BXCR(n)					  (n)
+#define	    EBC_BXCR_BAS				    0xfff00000
+#define	    EBC_BXCR_BS				  	    0x000e0000
+#define	    EBC_BXCR_BANK_SIZE(reg) \
+	(0x100000 << (((reg) & EBC_BXCR_BS) >> 17))
+#define	    EBC_BXCR_BU				  	    0x00018000
+#define	      EBC_BXCR_BU_OFF			  	      0x00000000
+#define	      EBC_BXCR_BU_RO			  	      0x00008000
+#define	      EBC_BXCR_BU_WO			  	      0x00010000
+#define	      EBC_BXCR_BU_RW			  	      0x00018000
+#define	    EBC_BXCR_BW				  	    0x00006000
+#define   EBC_B0AP					  0x10
+#define   EBC_B1AP					  0x11
+#define   EBC_B2AP					  0x12
+#define   EBC_B3AP					  0x13
+#define   EBC_B4AP					  0x14
+#define   EBC_B5AP					  0x15
+#define   EBC_B6AP					  0x16
+#define   EBC_B7AP					  0x17
+#define   EBC_BXAP(n)					  (0x10+(n))
+#define   EBC_BEAR					  0x20
+#define   EBC_BESR					  0x21
+#define   EBC_CFG					  0x23
+#define   EBC_CID					  0x24
+
 /* 440GP Clock, PM, chip control */
 #define DCRN_CPC0_SR					0x0b0
 #define DCRN_CPC0_ER					0x0b1
diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
index 0ec02f4..c5f9961 100644
--- a/arch/powerpc/boot/dts/ebony.dts
+++ b/arch/powerpc/boot/dts/ebony.dts
@@ -31,8 +31,8 @@
 			reg = <0>;
 			clock-frequency = <0>; // Filled in by zImage
 			timebase-frequency = <0>; // Filled in by zImage
-			i-cache-line-size = <32>;
-			d-cache-line-size = <32>;
+			i-cache-line-size = <20>;
+			d-cache-line-size = <20>;
 			i-cache-size = <8000>; /* 32 kB */
 			d-cache-size = <8000>; /* 32 kB */
 			dcr-controller;
@@ -135,11 +135,9 @@
 				#address-cells = <2>;
 				#size-cells = <1>;
 				clock-frequency = <0>; // Filled in by zImage
-				ranges = <0 00000000 fff00000 100000
-					  1 00000000 48000000 100000
-					  2 00000000 ff800000 400000
-					  3 00000000 48200000 100000
-					  7 00000000 48300000 100000>;
+				// ranges property is supplied by zImage
+				// based on firmware's configuration of the
+				// EBC bridge
 				interrupts = <5 4>;
 				interrupt-parent = <&UIC1>;
 
diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts
index 254499b..80a4fab 100644
--- a/arch/powerpc/boot/dts/holly.dts
+++ b/arch/powerpc/boot/dts/holly.dts
@@ -46,7 +46,7 @@
 
   	tsi109@c0000000 {
 		device_type = "tsi-bridge";
-		compatible = "tsi-bridge";
+		compatible = "tsi109-bridge", "tsi108-bridge";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <00000000 c0000000 00010000>;
@@ -54,52 +54,55 @@
 
 		i2c@7000 {
 			device_type = "i2c";
-			compatible  = "tsi-i2c";
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			compatible  = "tsi109-i2c", "tsi108-i2c";
+			interrupt-parent = <&MPIC>;
 			interrupts = <e 2>;
 			reg = <7000 400>;
 		};
 
-		mdio@6000 {
+		MDIO: mdio@6000 {
 			device_type = "mdio";
-			compatible = "tsi-ethernet";
+			compatible = "tsi109-mdio", "tsi108-mdio";
+			reg = <6000 50>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 
-			PHY1: ethernet-phy@6000 {
-				device_type = "ethernet-phy";
-				compatible = "bcm54xx";
-				reg = <6000 50>;
-				phy-id = <1>;
+			PHY1: ethernet-phy@1 {
+				compatible = "bcm5461a";
+				reg = <1>;
+				txc-rxc-delay-disable;
 			};
 
-			PHY2: ethernet-phy@6400 {
-				device_type = "ethernet-phy";
-				compatible = "bcm54xx";
-				reg = <6000 50>;
-				phy-id = <2>;
+			PHY2: ethernet-phy@2 {
+				compatible = "bcm5461a";
+				reg = <2>;
+				txc-rxc-delay-disable;
 			};
 		};
 
 		ethernet@6200 {
 			device_type = "network";
-			compatible = "tsi-ethernet";
+			compatible = "tsi109-ethernet", "tsi108-ethernet";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <6000 200>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <10 2>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&PHY1>;
 		};
 
 		ethernet@6600 {
 			device_type = "network";
-			compatible = "tsi-ethernet";
+			compatible = "tsi109-ethernet", "tsi108-ethernet";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <6400 200>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <11 2>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&PHY2>;
 		};
 
@@ -110,7 +113,7 @@
 			virtual-reg = <c0007808>;
 			clock-frequency = <3F9C6000>;
 			current-speed = <1c200>;
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <c 2>;
 		};
 
@@ -121,7 +124,7 @@
 			virtual-reg = <c0007c08>;
 			clock-frequency = <3F9C6000>;
 			current-speed = <1c200>;
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <d 2>;
 		};
 
@@ -136,7 +139,7 @@
 
 		pci@1000 {
 			device_type = "pci";
-			compatible = "tsi109";
+			compatible = "tsi109-pci", "tsi108-pci";
 			#interrupt-cells = <1>;
 			#size-cells = <2>;
 			#address-cells = <3>;
@@ -150,7 +153,7 @@
 			ranges = <02000000 0 40000000 40000000 0 10000000
 				  01000000 0 00000000 7e000000 0 00010000>;
 			clock-frequency = <7f28154>;
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <17 2>;
 			interrupt-map-mask = <f800 0 0 7>;
 			/*----------------------------------------------------+
@@ -186,13 +189,12 @@
  				#address-cells = <0>;
  				#interrupt-cells = <2>;
  				interrupts = <17 2>;
-				interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+				interrupt-parent = <&MPIC>;
 			};
 		};
 	};
 
 	chosen {
 		linux,stdout-path = "/tsi109@c0000000/serial@7808";
-		bootargs = "console=ttyS0,115200";
 	};
 };
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index 765c306..0e3d314 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -45,7 +45,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		#interrupt-cells = <2>;
-		device_type = "tsi-bridge";
+		device_type = "tsi108-bridge";
 		ranges = <00000000 c0000000 00010000>;
 		reg = <c0000000 00010000>;
 		bus-frequency = <0>;
@@ -55,27 +55,26 @@
 			interrupts = <E 0>;
 			reg = <7000 400>;
 			device_type = "i2c";
-			compatible  = "tsi-i2c";
+			compatible  = "tsi108-i2c";
 		};
 
-		mdio@6000 {
+		MDIO: mdio@6000 {
 			device_type = "mdio";
-			compatible = "tsi-ethernet";
+			compatible = "tsi108-mdio";
+			reg = <6000 50>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 
-			phy8: ethernet-phy@6000 {
+			phy8: ethernet-phy@8 {
 				interrupt-parent = <&mpic>;
 				interrupts = <2 1>;
-				reg = <6000 50>;
-				phy-id = <8>;
-				device_type = "ethernet-phy";
+				reg = <8>;
 			};
 
-			phy9: ethernet-phy@6400 {
+			phy9: ethernet-phy@9 {
 				interrupt-parent = <&mpic>;
 				interrupts = <2 1>;
-				reg = <6000 50>;
-				phy-id = <9>;
-				device_type = "ethernet-phy";
+				reg = <9>;
 			};
 
 		};
@@ -83,12 +82,12 @@
 		ethernet@6200 {
 			#size-cells = <0>;
 			device_type = "network";
-			model = "TSI-ETH";
-			compatible = "tsi-ethernet";
+			compatible = "tsi108-ethernet";
 			reg = <6000 200>;
 			address = [ 00 06 D2 00 00 01 ];
 			interrupts = <10 2>;
 			interrupt-parent = <&mpic>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&phy8>;
 		};
 
@@ -96,12 +95,12 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			device_type = "network";
-			model = "TSI-ETH";
-			compatible = "tsi-ethernet";
+			compatible = "tsi108-ethernet";
 			reg = <6400 200>;
 			address = [ 00 06 D2 00 00 02 ];
 			interrupts = <11 2>;
 			interrupt-parent = <&mpic>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&phy9>;
 		};
 
@@ -135,7 +134,7 @@
                        	big-endian;
 		};
 		pci@1000 {
-			compatible = "tsi10x";
+			compatible = "tsi108-pci";
 			device_type = "pci";
 			#interrupt-cells = <1>;
 			#size-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
index 423eedc..1934b80 100644
--- a/arch/powerpc/boot/dts/mpc8272ads.dts
+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
@@ -14,12 +14,10 @@
        compatible = "MPC8260ADS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8272@0 {
                        device_type = "cpu";
@@ -32,12 +30,10 @@
                        bus-frequency = <0>;
                        clock-frequency = <0>;
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
-       interrupt-controller@f8200000 {
-               linux,phandle = <f8200000>;
+		pci_pic: interrupt-controller@f8200000 {
                #address-cells = <0>;
                #interrupt-cells = <2>;
                interrupt-controller;
@@ -47,15 +43,13 @@
        };
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 4000000 f4500000 00000020>;
        };
 
        chosen {
                name = "chosen";
                linux,platform = <0>;
-               interrupt-controller = <10c00>;
-               linux,phandle = <400>;
+		interrupt-controller = <&Cpm_pic>;
        };
 
        soc8272@f0000000 {
@@ -70,20 +64,17 @@
                        device_type = "mdio";
                        compatible = "fs_enet";
                        reg = <0 0>;
-                       linux,phandle = <24520>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <10c00>;
+			phy0:ethernet-phy@0 {
+				interrupt-parent = <&Cpm_pic>;
                                interrupts = <17 4>;
                                reg = <0>;
                                bitbang = [ 12 12 13 02 02 01 ];
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <10c00>;
+			phy1:ethernet-phy@1 {
+				interrupt-parent = <&Cpm_pic>;
                                interrupts = <17 4>;
                                bitbang = [ 12 12 13 02 02 01 ];
                                reg = <3>;
@@ -101,8 +92,8 @@
                        reg = <11300 20 8400 100 11380 30>;
                        mac-address = [ 00 11 2F 99 43 54 ];
                        interrupts = <20 2>;
-                       interrupt-parent = <10c00>;
-                       phy-handle = <2452000>;
+			interrupt-parent = <&Cpm_pic>;
+			phy-handle = <&Phy0>;
                        rx-clock = <13>;
                        tx-clock = <12>;
                };
@@ -115,14 +106,13 @@
                        reg = <11320 20 8500 100 113b0 30>;
                        mac-address = [ 00 11 2F 99 44 54 ];
                        interrupts = <21 2>;
-                       interrupt-parent = <10c00>;
-                       phy-handle = <2452001>;
+			interrupt-parent = <&Cpm_pic>;
+			phy-handle = <&Phy1>;
                        rx-clock = <17>;
                        tx-clock = <18>;
                };
 
                cpm@f0000000 {
-                       linux,phandle = <f0000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        #interrupt-cells = <2>;
@@ -142,7 +132,7 @@
                                reg = <11a00 20 8000 100>;
                                current-speed = <1c200>;
                                interrupts = <28 2>;
-                               interrupt-parent = <10c00>;
+				interrupt-parent = <&Cpm_pic>;
                                clock-setup = <0 00ffffff>;
                                rx-clock = <1>;
                                tx-clock = <1>;
@@ -156,15 +146,14 @@
                                reg = <11a60 20 8300 100>;
                                current-speed = <1c200>;
                                interrupts = <2b 2>;
-                               interrupt-parent = <10c00>;
+				interrupt-parent = <&Cpm_pic>;
                                clock-setup = <1b ffffff00>;
                                rx-clock = <4>;
                                tx-clock = <4>;
                        };
 
                };
-               interrupt-controller@10c00 {
-                       linux,phandle = <10c00>;
+			cpm_pic:interrupt-controller@10c00 {
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
                        interrupt-controller;
@@ -174,7 +163,6 @@
 		       compatible = "CPM2";
                };
                pci@0500 {
-                       linux,phandle = <0500>;
                        #interrupt-cells = <1>;
                        #size-cells = <2>;
                        #address-cells = <3>;
@@ -202,7 +190,7 @@
                                         c000 0 0 2 f8200000 43 8
                                         c000 0 0 3 f8200000 40 8
                                         c000 0 0 4 f8200000 41 8>;
-                       interrupt-parent = <10c00>;
+			interrupt-parent = <&Cpm_pic>;
                        interrupts = <14 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 40000000
@@ -216,7 +204,7 @@
                        compatible = "talitos";
                        reg = <30000 10000>;
                        interrupts = <b 2>;
-                       interrupt-parent = <10c00>;
+			interrupt-parent = <&Cpm_pic>;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <0000007e>;
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 112dd51..4fc0c4d 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -272,7 +272,13 @@
 			reg = <2200 200>;
 			interrupts = <22>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 04 9f 00 23 23 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <19>;
 			tx-clock = <1a>;
 			phy-handle = < &phy3 >;
@@ -287,7 +293,13 @@
 			reg = <3000 200>;
 			interrupts = <23>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 11 22 33 44 55 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <17>;
 			tx-clock = <18>;
 			phy-handle = < &phy4 >;
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index be4c357..447c03f 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -231,7 +231,13 @@
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 04 9f ef 03 02 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <20>;
 			tx-clock = <13>;
 			phy-handle = <&phy00>;
@@ -246,7 +252,13 @@
 			reg = <2200 200>;
 			interrupts = <22>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 04 9f ef 03 01 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <19>;
 			tx-clock = <1a>;
 			phy-handle = <&phy04>;
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index db0d003..ae9bca5 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -131,6 +131,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <20 8 21 8 22 8>;
@@ -145,6 +150,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 8 24 8 25 8>;
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index df773fa..310e877 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -136,6 +136,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <20 8 21 8 22 8>;
@@ -150,6 +155,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 8 24 8 25 8>;
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 38c8594..1e914f3 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -301,7 +301,13 @@
 			reg = <2000 200>;
 			interrupts = <20>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 04 9f 00 23 23 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <19>;
 			phy-handle = < &phy0 >;
@@ -317,7 +323,13 @@
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 11 22 33 44 55 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <14>;
 			phy-handle = < &phy1 >;
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index d91e81c..364a969 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8540-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,19 +81,19 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <37 1>;
+				interrupts = <7 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -106,9 +106,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			address = [ 00 E0 0C 00 73 00 ];
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -120,9 +125,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			address = [ 00 E0 0C 00 73 01 ];
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -134,9 +144,14 @@
 			model = "FEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			address = [ 00 E0 0C 00 73 02 ];
-			local-mac-address = [ 00 E0 0C 00 73 02 ];
-			interrupts = <19 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
@@ -146,7 +161,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -155,7 +170,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 		pci@8000 {
@@ -163,78 +178,78 @@
 			interrupt-map = <
 
 				/* IDSEL 0x02 */
-				1000 0 0 1 &mpic 31 1
-				1000 0 0 2 &mpic 32 1
-				1000 0 0 3 &mpic 33 1
-				1000 0 0 4 &mpic 34 1
+				1000 0 0 1 &mpic 1 1
+				1000 0 0 2 &mpic 2 1
+				1000 0 0 3 &mpic 3 1
+				1000 0 0 4 &mpic 4 1
 
 				/* IDSEL 0x03 */
-				1800 0 0 1 &mpic 34 1
-				1800 0 0 2 &mpic 31 1
-				1800 0 0 3 &mpic 32 1
-				1800 0 0 4 &mpic 33 1
+				1800 0 0 1 &mpic 4 1
+				1800 0 0 2 &mpic 1 1
+				1800 0 0 3 &mpic 2 1
+				1800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x04 */
-				2000 0 0 1 &mpic 33 1
-				2000 0 0 2 &mpic 34 1
-				2000 0 0 3 &mpic 31 1
-				2000 0 0 4 &mpic 32 1
+				2000 0 0 1 &mpic 3 1
+				2000 0 0 2 &mpic 4 1
+				2000 0 0 3 &mpic 1 1
+				2000 0 0 4 &mpic 2 1
 
 				/* IDSEL 0x05 */
-				2800 0 0 1 &mpic 32 1
-				2800 0 0 2 &mpic 33 1
-				2800 0 0 3 &mpic 34 1
-				2800 0 0 4 &mpic 31 1
+				2800 0 0 1 &mpic 2 1
+				2800 0 0 2 &mpic 3 1
+				2800 0 0 3 &mpic 4 1
+				2800 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x0c */
-				6000 0 0 1 &mpic 31 1
-				6000 0 0 2 &mpic 32 1
-				6000 0 0 3 &mpic 33 1
-				6000 0 0 4 &mpic 34 1
+				6000 0 0 1 &mpic 1 1
+				6000 0 0 2 &mpic 2 1
+				6000 0 0 3 &mpic 3 1
+				6000 0 0 4 &mpic 4 1
 
 				/* IDSEL 0x0d */
-				6800 0 0 1 &mpic 34 1
-				6800 0 0 2 &mpic 31 1
-				6800 0 0 3 &mpic 32 1
-				6800 0 0 4 &mpic 33 1
+				6800 0 0 1 &mpic 4 1
+				6800 0 0 2 &mpic 1 1
+				6800 0 0 3 &mpic 2 1
+				6800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x0e */
-				7000 0 0 1 &mpic 33 1
-				7000 0 0 2 &mpic 34 1
-				7000 0 0 3 &mpic 31 1
-				7000 0 0 4 &mpic 32 1
+				7000 0 0 1 &mpic 3 1
+				7000 0 0 2 &mpic 4 1
+				7000 0 0 3 &mpic 1 1
+				7000 0 0 4 &mpic 2 1
 
 				/* IDSEL 0x0f */
-				7800 0 0 1 &mpic 32 1
-				7800 0 0 2 &mpic 33 1
-				7800 0 0 3 &mpic 34 1
-				7800 0 0 4 &mpic 31 1
+				7800 0 0 1 &mpic 2 1
+				7800 0 0 2 &mpic 3 1
+				7800 0 0 3 &mpic 4 1
+				7800 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x12 */
-				9000 0 0 1 &mpic 31 1
-				9000 0 0 2 &mpic 32 1
-				9000 0 0 3 &mpic 33 1
-				9000 0 0 4 &mpic 34 1
+				9000 0 0 1 &mpic 1 1
+				9000 0 0 2 &mpic 2 1
+				9000 0 0 3 &mpic 3 1
+				9000 0 0 4 &mpic 4 1
 
 				/* IDSEL 0x13 */
-				9800 0 0 1 &mpic 34 1
-				9800 0 0 2 &mpic 31 1
-				9800 0 0 3 &mpic 32 1
-				9800 0 0 4 &mpic 33 1
+				9800 0 0 1 &mpic 4 1
+				9800 0 0 2 &mpic 1 1
+				9800 0 0 3 &mpic 2 1
+				9800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x14 */
-				a000 0 0 1 &mpic 33 1
-				a000 0 0 2 &mpic 34 1
-				a000 0 0 3 &mpic 31 1
-				a000 0 0 4 &mpic 32 1
+				a000 0 0 1 &mpic 3 1
+				a000 0 0 2 &mpic 4 1
+				a000 0 0 3 &mpic 1 1
+				a000 0 0 4 &mpic 2 1
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 32 1
-				a800 0 0 2 &mpic 33 1
-				a800 0 0 3 &mpic 34 1
-				a800 0 0 4 &mpic 31 1>;
+				a800 0 0 1 &mpic 2 1
+				a800 0 0 2 &mpic 3 1
+				a800 0 0 3 &mpic 4 1
+				a800 0 0 4 &mpic 1 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 4f2c3af..070206f 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8541-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,13 +81,13 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
@@ -100,8 +100,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -113,8 +113,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -124,7 +124,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -133,7 +133,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -142,49 +142,49 @@
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 &mpic 30 1
-				08000 0 0 2 &mpic 31 1
-				08000 0 0 3 &mpic 32 1
-				08000 0 0 4 &mpic 33 1
+				08000 0 0 1 &mpic 0 1
+				08000 0 0 2 &mpic 1 1
+				08000 0 0 3 &mpic 2 1
+				08000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 &mpic 30 1
-				08800 0 0 2 &mpic 31 1
-				08800 0 0 3 &mpic 32 1
-				08800 0 0 4 &mpic 33 1
+				08800 0 0 1 &mpic 0 1
+				08800 0 0 2 &mpic 1 1
+				08800 0 0 3 &mpic 2 1
+				08800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 &mpic 30 1
-				09000 0 0 2 &mpic 31 1
-				09000 0 0 3 &mpic 32 1
-				09000 0 0 4 &mpic 33 1
+				09000 0 0 1 &mpic 0 1
+				09000 0 0 2 &mpic 1 1
+				09000 0 0 3 &mpic 2 1
+				09000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 &mpic 31 1
-				09800 0 0 2 &mpic 32 1
-				09800 0 0 3 &mpic 33 1
-				09800 0 0 4 &mpic 30 1
+				09800 0 0 1 &mpic 1 1
+				09800 0 0 2 &mpic 2 1
+				09800 0 0 3 &mpic 3 1
+				09800 0 0 4 &mpic 0 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 &mpic 32 1
-				0a000 0 0 2 &mpic 33 1
-				0a000 0 0 3 &mpic 30 1
-				0a000 0 0 4 &mpic 31 1
+				0a000 0 0 1 &mpic 2 1
+				0a000 0 0 2 &mpic 3 1
+				0a000 0 0 3 &mpic 0 1
+				0a000 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 &mpic 33 1
-				0a800 0 0 2 &mpic 30 1
-				0a800 0 0 3 &mpic 31 1
-				0a800 0 0 4 &mpic 32 1
+				0a800 0 0 1 &mpic 3 1
+				0a800 0 0 2 &mpic 0 1
+				0a800 0 0 3 &mpic 1 1
+				0a800 0 0 4 &mpic 2 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 &mpic 30 1
-				19000 0 0 2 &mpic 31 1
-				19000 0 0 3 &mpic 32 1
-				19000 0 0 4 &mpic 33 1>;
+				19000 0 0 1 &mpic 0 1
+				19000 0 0 2 &mpic 1 1
+				19000 0 0 3 &mpic 2 1
+				19000 0 0 4 &mpic 3 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
@@ -216,12 +216,12 @@
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 3b 1
-				a800 0 0 2 &mpic 3b 1
-				a800 0 0 3 &mpic 3b 1
-				a800 0 0 4 &mpic 3b 1>;
+				a800 0 0 1 &mpic b 1
+				a800 0 0 2 &mpic b 1
+				a800 0 0 3 &mpic b 1
+				a800 0 0 4 &mpic b 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <09 2>;
+			interrupts = <19 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
 				  01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index 3033599..8285925 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8544-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,13 +81,13 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <3a 1>;
+				interrupts = <a 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <3a 1>;
+				interrupts = <a 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
@@ -101,7 +101,7 @@
 			compatible = "gianfar";
 			reg = <24000 1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -114,7 +114,7 @@
 			compatible = "gianfar";
 			reg = <26000 1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <f 2 10 2 11 2>;
+			interrupts = <1f 2 20 2 21 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -124,7 +124,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -133,7 +133,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index ad96381..9d0b84b 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8548-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <80000>;	// L2, 512K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,25 +81,25 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -112,8 +112,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -125,8 +125,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -139,8 +139,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 02 ];
-			interrupts = <f 2 10 2 11 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1f 2 20 2 21 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
 		};
@@ -152,8 +152,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <27000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 03 ];
-			interrupts = <15 2 16 2 17 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <25 2 26 2 27 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
@@ -164,7 +164,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -173,58 +173,64 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
+		global-utilities@e0000 {	//global utilities reg
+			compatible = "fsl,mpc8548-guts";
+			reg = <e0000 1000>;
+			fsl,has-rstcr;
+		};
+
 		pci1: pci@8000 {
 			interrupt-map-mask = <1f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 &mpic 30 1
-				08000 0 0 2 &mpic 31 1
-				08000 0 0 3 &mpic 32 1
-				08000 0 0 4 &mpic 33 1
+				08000 0 0 1 &mpic 0 1
+				08000 0 0 2 &mpic 1 1
+				08000 0 0 3 &mpic 2 1
+				08000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 &mpic 30 1
-				08800 0 0 2 &mpic 31 1
-				08800 0 0 3 &mpic 32 1
-				08800 0 0 4 &mpic 33 1
+				08800 0 0 1 &mpic 0 1
+				08800 0 0 2 &mpic 1 1
+				08800 0 0 3 &mpic 2 1
+				08800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 &mpic 30 1
-				09000 0 0 2 &mpic 31 1
-				09000 0 0 3 &mpic 32 1
-				09000 0 0 4 &mpic 33 1
+				09000 0 0 1 &mpic 0 1
+				09000 0 0 2 &mpic 1 1
+				09000 0 0 3 &mpic 2 1
+				09000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 &mpic 31 1
-				09800 0 0 2 &mpic 32 1
-				09800 0 0 3 &mpic 33 1
-				09800 0 0 4 &mpic 30 1
+				09800 0 0 1 &mpic 1 1
+				09800 0 0 2 &mpic 2 1
+				09800 0 0 3 &mpic 3 1
+				09800 0 0 4 &mpic 0 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 &mpic 32 1
-				0a000 0 0 2 &mpic 33 1
-				0a000 0 0 3 &mpic 30 1
-				0a000 0 0 4 &mpic 31 1
+				0a000 0 0 1 &mpic 2 1
+				0a000 0 0 2 &mpic 3 1
+				0a000 0 0 3 &mpic 0 1
+				0a000 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 &mpic 33 1
-				0a800 0 0 2 &mpic 30 1
-				0a800 0 0 3 &mpic 31 1
-				0a800 0 0 4 &mpic 32 1
+				0a800 0 0 1 &mpic 3 1
+				0a800 0 0 2 &mpic 0 1
+				0a800 0 0 3 &mpic 1 1
+				0a800 0 0 4 &mpic 2 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 &mpic 30 1
-				19000 0 0 2 &mpic 31 1
-				19000 0 0 3 &mpic 32 1
-				19000 0 0 4 &mpic 33 1>;
+				19000 0 0 1 &mpic 0 1
+				19000 0 0 2 &mpic 1 1
+				19000 0 0 3 &mpic 2 1
+				19000 0 0 4 &mpic 3 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
@@ -256,12 +262,12 @@
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 3b 1
-				a800 0 0 2 &mpic 3b 1
-				a800 0 0 3 &mpic 3b 1
-				a800 0 0 4 &mpic 3b 1>;
+				a800 0 0 1 &mpic b 1
+				a800 0 0 2 &mpic b 1
+				a800 0 0 3 &mpic b 1
+				a800 0 0 4 &mpic b 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <09 2>;
+			interrupts = <19 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
 				  01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 951ed92..17e45d9 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8555-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,13 +81,13 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
@@ -100,8 +100,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <0d 2 0e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -113,8 +113,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -124,7 +124,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -133,7 +133,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -142,49 +142,49 @@
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 &mpic 30 1
-				08000 0 0 2 &mpic 31 1
-				08000 0 0 3 &mpic 32 1
-				08000 0 0 4 &mpic 33 1
+				08000 0 0 1 &mpic 0 1
+				08000 0 0 2 &mpic 1 1
+				08000 0 0 3 &mpic 2 1
+				08000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 &mpic 30 1
-				08800 0 0 2 &mpic 31 1
-				08800 0 0 3 &mpic 32 1
-				08800 0 0 4 &mpic 33 1
+				08800 0 0 1 &mpic 0 1
+				08800 0 0 2 &mpic 1 1
+				08800 0 0 3 &mpic 2 1
+				08800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 &mpic 30 1
-				09000 0 0 2 &mpic 31 1
-				09000 0 0 3 &mpic 32 1
-				09000 0 0 4 &mpic 33 1
+				09000 0 0 1 &mpic 0 1
+				09000 0 0 2 &mpic 1 1
+				09000 0 0 3 &mpic 2 1
+				09000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 &mpic 31 1
-				09800 0 0 2 &mpic 32 1
-				09800 0 0 3 &mpic 33 1
-				09800 0 0 4 &mpic 30 1
+				09800 0 0 1 &mpic 1 1
+				09800 0 0 2 &mpic 2 1
+				09800 0 0 3 &mpic 3 1
+				09800 0 0 4 &mpic 0 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 &mpic 32 1
-				0a000 0 0 2 &mpic 33 1
-				0a000 0 0 3 &mpic 30 1
-				0a000 0 0 4 &mpic 31 1
+				0a000 0 0 1 &mpic 2 1
+				0a000 0 0 2 &mpic 3 1
+				0a000 0 0 3 &mpic 0 1
+				0a000 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 &mpic 33 1
-				0a800 0 0 2 &mpic 30 1
-				0a800 0 0 3 &mpic 31 1
-				0a800 0 0 4 &mpic 32 1
+				0a800 0 0 1 &mpic 3 1
+				0a800 0 0 2 &mpic 0 1
+				0a800 0 0 3 &mpic 1 1
+				0a800 0 0 4 &mpic 2 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 &mpic 30 1
-				19000 0 0 2 &mpic 31 1
-				19000 0 0 3 &mpic 32 1
-				19000 0 0 4 &mpic 33 1>;
+				19000 0 0 1 &mpic 0 1
+				19000 0 0 2 &mpic 1 1
+				19000 0 0 3 &mpic 2 1
+				19000 0 0 4 &mpic 3 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
@@ -216,12 +216,12 @@
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 3b 1
-				a800 0 0 2 &mpic 3b 1
-				a800 0 0 3 &mpic 3b 1
-				a800 0 0 4 &mpic 3b 1>;
+				a800 0 0 1 &mpic b 1
+				a800 0 0 2 &mpic b 1
+				a800 0 0 3 &mpic b 1
+				a800 0 0 4 &mpic b 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <09 2>;
+			interrupts = <19 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
 				  01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 8068215..21ccaaa 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8540-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,7 +61,7 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		mdio@24520 {
@@ -72,25 +72,25 @@
 			#size-cells = <0>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <37 1>;
+				interrupts = <7 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <37 1>;
+				interrupts = <7 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -101,8 +101,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			address = [ 00 00 0C 00 00 FD ];
-			interrupts = <d 2 e 2 12 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -114,8 +120,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			address = [ 00 00 0C 00 01 FD ];
-			interrupts = <13 2 14 2 18 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -132,79 +144,79 @@
 			interrupt-map = <
 
 					/* IDSEL 0x2 */
-					 1000 0 0 1 &mpic 31 1
-					 1000 0 0 2 &mpic 32 1
-					 1000 0 0 3 &mpic 33 1
-					 1000 0 0 4 &mpic 34 1
+					 1000 0 0 1 &mpic 1 1
+					 1000 0 0 2 &mpic 2 1
+					 1000 0 0 3 &mpic 3 1
+					 1000 0 0 4 &mpic 4 1
 
 					/* IDSEL 0x3 */
-					 1800 0 0 1 &mpic 34 1
-					 1800 0 0 2 &mpic 31 1
-					 1800 0 0 3 &mpic 32 1
-					 1800 0 0 4 &mpic 33 1
+					 1800 0 0 1 &mpic 4 1
+					 1800 0 0 2 &mpic 1 1
+					 1800 0 0 3 &mpic 2 1
+					 1800 0 0 4 &mpic 3 1
 
 					/* IDSEL 0x4 */
-					 2000 0 0 1 &mpic 33 1
-					 2000 0 0 2 &mpic 34 1
-					 2000 0 0 3 &mpic 31 1
-					 2000 0 0 4 &mpic 32 1
+					 2000 0 0 1 &mpic 3 1
+					 2000 0 0 2 &mpic 4 1
+					 2000 0 0 3 &mpic 1 1
+					 2000 0 0 4 &mpic 2 1
 
 					/* IDSEL 0x5  */
-					 2800 0 0 1 &mpic 32 1
-					 2800 0 0 2 &mpic 33 1
-					 2800 0 0 3 &mpic 34 1
-					 2800 0 0 4 &mpic 31 1
+					 2800 0 0 1 &mpic 2 1
+					 2800 0 0 2 &mpic 3 1
+					 2800 0 0 3 &mpic 4 1
+					 2800 0 0 4 &mpic 1 1
 
 					/* IDSEL 12 */
-					 6000 0 0 1 &mpic 31 1
-					 6000 0 0 2 &mpic 32 1
-					 6000 0 0 3 &mpic 33 1
-					 6000 0 0 4 &mpic 34 1
+					 6000 0 0 1 &mpic 1 1
+					 6000 0 0 2 &mpic 2 1
+					 6000 0 0 3 &mpic 3 1
+					 6000 0 0 4 &mpic 4 1
 
 					/* IDSEL 13 */
-					 6800 0 0 1 &mpic 34 1
-					 6800 0 0 2 &mpic 31 1
-					 6800 0 0 3 &mpic 32 1
-					 6800 0 0 4 &mpic 33 1
+					 6800 0 0 1 &mpic 4 1
+					 6800 0 0 2 &mpic 1 1
+					 6800 0 0 3 &mpic 2 1
+					 6800 0 0 4 &mpic 3 1
 
 					/* IDSEL 14*/
-					 7000 0 0 1 &mpic 33 1
-					 7000 0 0 2 &mpic 34 1
-					 7000 0 0 3 &mpic 31 1
-					 7000 0 0 4 &mpic 32 1
+					 7000 0 0 1 &mpic 3 1
+					 7000 0 0 2 &mpic 4 1
+					 7000 0 0 3 &mpic 1 1
+					 7000 0 0 4 &mpic 2 1
 
 					/* IDSEL 15 */
-					 7800 0 0 1 &mpic 32 1
-					 7800 0 0 2 &mpic 33 1
-					 7800 0 0 3 &mpic 34 1
-					 7800 0 0 4 &mpic 31 1
+					 7800 0 0 1 &mpic 2 1
+					 7800 0 0 2 &mpic 3 1
+					 7800 0 0 3 &mpic 4 1
+					 7800 0 0 4 &mpic 1 1
 
 					/* IDSEL 18 */
-					 9000 0 0 1 &mpic 31 1
-					 9000 0 0 2 &mpic 32 1
-					 9000 0 0 3 &mpic 33 1
-					 9000 0 0 4 &mpic 34 1
+					 9000 0 0 1 &mpic 1 1
+					 9000 0 0 2 &mpic 2 1
+					 9000 0 0 3 &mpic 3 1
+					 9000 0 0 4 &mpic 4 1
 
 					/* IDSEL 19 */
-					 9800 0 0 1 &mpic 34 1
-					 9800 0 0 2 &mpic 31 1
-					 9800 0 0 3 &mpic 32 1
-					 9800 0 0 4 &mpic 33 1
+					 9800 0 0 1 &mpic 4 1
+					 9800 0 0 2 &mpic 1 1
+					 9800 0 0 3 &mpic 2 1
+					 9800 0 0 4 &mpic 3 1
 
 					/* IDSEL 20 */
-					 a000 0 0 1 &mpic 33 1
-					 a000 0 0 2 &mpic 34 1
-					 a000 0 0 3 &mpic 31 1
-					 a000 0 0 4 &mpic 32 1
+					 a000 0 0 1 &mpic 3 1
+					 a000 0 0 2 &mpic 4 1
+					 a000 0 0 3 &mpic 1 1
+					 a000 0 0 4 &mpic 2 1
 
 					/* IDSEL 21 */
-					 a800 0 0 1 &mpic 32 1
-					 a800 0 0 2 &mpic 33 1
-					 a800 0 0 3 &mpic 34 1
-					 a800 0 0 4 &mpic 31 1>;
+					 a800 0 0 1 &mpic 2 1
+					 a800 0 0 2 &mpic 3 1
+					 a800 0 0 3 &mpic 4 1
+					 a800 0 0 4 &mpic 1 1>;
 
 			interrupt-parent = <&mpic>;
-			interrupts = <8 0>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 01000000>;
@@ -234,7 +246,7 @@
 				interrupt-controller;
 				#address-cells = <0>;
 				#interrupt-cells = <2>;
-				interrupts = <1e 0>;
+				interrupts = <2e 2>;
 				interrupt-parent = <&mpic>;
 				reg = <90c00 80>;
 				built-in;
@@ -275,7 +287,13 @@
 				model = "FCC";
 				device-id = <2>;
 				reg = <91320 20 88500 100 913a0 30>;
-				mac-address = [ 00 00 0C 00 02 FD ];
+				/*
+				 * mac-address is deprecated and will be removed
+				 * in 2.6.25.  Only recent versions of
+				 * U-Boot support local-mac-address, however.
+				 */
+				mac-address = [ 00 00 00 00 00 00 ];
+				local-mac-address = [ 00 00 00 00 00 00 ];
 				clock-setup = <ff00ffff 250000>;
 				rx-clock = <15>;
 				tx-clock = <16>;
@@ -290,7 +308,13 @@
 				model = "FCC";
 				device-id = <3>;
 				reg = <91340 20 88600 100 913d0 30>;
-				mac-address = [ 00 00 0C 00 03 FD ];
+				/*
+				 * mac-address is deprecated and will be removed
+				 * in 2.6.25.  Only recent versions of
+				 * U-Boot support local-mac-address, however.
+				 */
+				mac-address = [ 00 00 00 00 00 00 ];
+				local-mac-address = [ 00 00 00 00 00 00 ];
 				clock-setup = <ffff00ff 3700>;
 				rx-clock = <17>;
 				tx-clock = <18>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index a123ec9..6bb18f2 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -61,7 +61,7 @@
 			compatible = "fsl,8568-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -70,14 +70,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <80000>;	// L2, 512K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -86,7 +86,7 @@
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -99,25 +99,25 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -130,8 +130,14 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
 		};
@@ -143,8 +149,14 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			mac-address = [ 00 00 00 00 00 00];
-			interrupts = <13 2 14 2 18 2>;
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
@@ -154,7 +166,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -163,7 +175,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -172,7 +184,7 @@
 			model = "SEC2";
 			compatible = "talitos";
 			reg = <30000 f000>;
-			interrupts = <1d 2>;
+			interrupts = <2d 2>;
 			interrupt-parent = <&mpic>;
 			num-channels = <4>;
 			channel-fifo-len = <18>;
@@ -300,7 +312,13 @@
 			reg = <2000 200>;
 			interrupts = <20>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 04 9f 00 23 23 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <19>;
 			phy-handle = <&qe_phy0>;
@@ -316,7 +334,13 @@
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 11 22 33 44 55 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <14>;
 			phy-handle = <&qe_phy1>;
@@ -335,25 +359,25 @@
 			 * gianfar's MDIO bus */
 			qe_phy0: ethernet-phy@00 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			qe_phy1: ethernet-phy@01 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			qe_phy2: ethernet-phy@02 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			qe_phy3: ethernet-phy@03 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -367,7 +391,7 @@
 			reg = <80 80>;
 			built-in;
 			big-endian;
-			interrupts = <1e 2 1e 2>; //high:30 low:30
+			interrupts = <2e 2 2e 2>; //high:30 low:30
 			interrupt-parent = <&mpic>;
 		};
 
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index 260b264..db56a02 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -56,8 +56,12 @@
 		#size-cells = <1>;
 		#interrupt-cells = <2>;
 		device_type = "soc";
-		ranges = <0 f8000000 00100000>;
-		reg = <f8000000 00100000>;	// CCSRBAR 1M
+		ranges = <00001000 f8001000 000ff000
+			  80000000 80000000 20000000
+			  e2000000 e2000000 00100000
+			  a0000000 a0000000 20000000
+			  e3000000 e3000000 00100000>;
+		reg = <f8000000 00001000>;	// CCSRBAR
 		bus-frequency = <0>;
 
 		i2c@3000 {
@@ -86,25 +90,25 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -117,7 +121,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			mac-address = [ 00 E0 0C 00 73 00 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
@@ -130,7 +140,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			mac-address = [ 00 E0 0C 00 73 01 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
@@ -143,7 +159,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			mac-address = [ 00 E0 0C 00 02 FD ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1F 2 20 2 21 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
@@ -156,7 +178,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <27000 1000>;
-			mac-address = [ 00 E0 0C 00 03 FD ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <25 2 26 2 27 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
@@ -186,7 +214,7 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			reg = <8000 1000>;
-			bus-range = <0 fe>;
+			bus-range = <0 ff>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
 			clock-frequency = <1fca055>;
@@ -285,17 +313,84 @@
 				f800 0 0 3 &i8259 0 0
 				f800 0 0 4 &i8259 0 0
 				>;
-			i8259: i8259@4d0 {
-				clock-frequency = <0>;
-				interrupt-controller;
-				device_type = "interrupt-controller";
-				#address-cells = <0>;
-				#interrupt-cells = <2>;
-				built-in;
-				compatible = "chrp,iic";
-                	        big-endian;
-				interrupts = <49 2>;
-				interrupt-parent = <&mpic>;
+			uli1575@0 {
+				reg = <0 0 0 0 0>;
+				#size-cells = <2>;
+				#address-cells = <3>;
+				ranges = <02000000 0 80000000
+					  02000000 0 80000000
+					  0 20000000
+					  01000000 0 00000000
+					  01000000 0 00000000
+					  0 00100000>;
+
+				pci_bridge@0 {
+					reg = <0 0 0 0 0>;
+					#size-cells = <2>;
+					#address-cells = <3>;
+					ranges = <02000000 0 80000000
+						  02000000 0 80000000
+						  0 20000000
+						  01000000 0 00000000
+						  01000000 0 00000000
+						  0 00100000>;
+
+					isa@1e {
+						device_type = "isa";
+						#interrupt-cells = <2>;
+						#size-cells = <1>;
+						#address-cells = <2>;
+						reg = <f000 0 0 0 0>;
+						ranges = <1 0 01000000 0 0
+							  00001000>;
+						interrupt-parent = <&i8259>;
+
+						i8259: interrupt-controller@20 {
+							reg = <1 20 2
+							       1 a0 2
+							       1 4d0 2>;
+							clock-frequency = <0>;
+							interrupt-controller;
+							device_type = "interrupt-controller";
+							#address-cells = <0>;
+							#interrupt-cells = <2>;
+							built-in;
+							compatible = "chrp,iic";
+							interrupts = <9 2>;
+							interrupt-parent =
+								<&mpic>;
+						};
+
+						i8042@60 {
+							#size-cells = <0>;
+							#address-cells = <1>;
+							reg = <1 60 1 1 64 1>;
+							interrupts = <1 3 c 3>;
+							interrupt-parent =
+								<&i8259>;
+
+							keyboard@0 {
+								reg = <0>;
+								compatible = "pnpPNP,303";
+							};
+
+							mouse@1 {
+								reg = <1>;
+								compatible = "pnpPNP,f03";
+							};
+						};
+
+						rtc@70 {
+							compatible =
+								"pnpPNP,b00";
+							reg = <1 70 2>;
+						};
+
+						gpio@400 {
+							reg = <1 400 80>;
+						};
+					};
+				};
 			};
 
 		};
@@ -316,10 +411,10 @@
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 44 1
-				0000 0 0 2 &mpic 45 1
-				0000 0 0 3 &mpic 46 1
-				0000 0 0 4 &mpic 47 1
+				0000 0 0 1 &mpic 4 1
+				0000 0 0 2 &mpic 5 1
+				0000 0 0 3 &mpic 6 1
+				0000 0 0 4 &mpic 7 1
 				>;
 		};
 
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
index c0d06fd..e5e7726 100644
--- a/arch/powerpc/boot/dts/mpc866ads.dts
+++ b/arch/powerpc/boot/dts/mpc866ads.dts
@@ -15,12 +15,10 @@
 	compatible = "mpc8xx";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,866@0 {
 			device_type = "cpu";
@@ -34,14 +32,12 @@
 			clock-frequency = <0>;
 			32-bit;
 			interrupts = <f 2>;	// decrementer interrupt
-			interrupt-parent = <ff000000>;
-			linux,phandle = <201>;
+			interrupt-parent = <&Mpc8xx_pic>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 800000>;
 	};
 
@@ -57,11 +53,9 @@
 			device_type = "mdio";
 			compatible = "fs_enet";
 			reg = <e80 8>;
-			linux,phandle = <e80>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ethernet-phy@f {
-				linux,phandle = <e800f>;
+			phy: ethernet-phy@f {
 				reg = <f>;
 				device_type = "ethernet-phy";
 			};
@@ -75,12 +69,11 @@
 			reg = <e00 188>;
 			mac-address = [ 00 00 0C 00 01 FD ];
 			interrupts = <3 1>;
-			interrupt-parent = <ff000000>;
-			phy-handle = <e800f>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			phy-handle = <&Phy>;
 		};
 
-		pic@ff000000 {
-			linux,phandle = <ff000000>;
+		mpc8xx_pic: pic@ff000000 {
 			interrupt-controller;
 			#address-cells = <0>;
 			#interrupt-cells = <2>;
@@ -91,7 +84,6 @@
 		};
 
 		cpm@ff000000 {
-			linux,phandle = <ff000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			#interrupt-cells = <2>;
@@ -102,15 +94,14 @@
 			command-proc = <9c0>;
 			brg-frequency = <0>;
 			interrupts = <0 2>;	// cpm error interrupt
-			interrupt-parent = <930>;
+			interrupt-parent = <&Cpm_pic>;
 
-			pic@930 {
-				linux,phandle = <930>;
+			cpm_pic: pic@930 {
 				interrupt-controller;
 				#address-cells = <0>;
 				#interrupt-cells = <2>;
 				interrupts = <5 2 0 2>;
-				interrupt-parent = <ff000000>;
+				interrupt-parent = <&Mpc8xx_pic>;
 				reg = <930 20>;
 				built-in;
 				device_type = "cpm-pic";
@@ -128,7 +119,7 @@
 				tx-clock = <1>;
 				current-speed = <0>;
 				interrupts = <4 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			smc@a90 {
@@ -142,7 +133,7 @@
 				tx-clock = <2>;
 				current-speed = <0>;
 				interrupts = <3 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			scc@a00 {
@@ -153,7 +144,7 @@
 				reg = <a00 18 3c00 80>;
 				mac-address = [ 00 00 0C 00 03 FD ];
 				interrupts = <1e 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 		};
 	};
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index 110bf61..dc7ab9c 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -15,12 +15,10 @@
 	compatible = "mpc8xx";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,885@0 {
 			device_type = "cpu";
@@ -34,14 +32,12 @@
 			clock-frequency = <0>;
 			32-bit;
 			interrupts = <f 2>;	// decrementer interrupt
-			interrupt-parent = <ff000000>;
-			linux,phandle = <201>;
+			interrupt-parent = <&Mpc8xx_pic>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 800000>;
 	};
 
@@ -57,21 +53,17 @@
 			device_type = "mdio";
 			compatible = "fs_enet";
 			reg = <e80 8>;
-			linux,phandle = <e80>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ethernet-phy@0 {
-				linux,phandle = <e8000>;
+			Phy0: ethernet-phy@0 {
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <e8001>;
+			Phy1: ethernet-phy@1 {
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@2 {
-				linux,phandle = <e8002>;
+			Phy2: ethernet-phy@2 {
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
@@ -85,8 +77,8 @@
 			reg = <e00 188>;
 			mac-address = [ 00 00 0C 00 01 FD ];
 			interrupts = <3 1>;
-			interrupt-parent = <ff000000>;
-			phy-handle = <e8000>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			phy-handle = <&Phy1>;
 		};
 
 		fec@1e00 {
@@ -97,12 +89,11 @@
 			reg = <1e00 188>;
 			mac-address = [ 00 00 0C 00 02 FD ];
 			interrupts = <7 1>;
-			interrupt-parent = <ff000000>;
-			phy-handle = <e8001>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			phy-handle = <&Phy2>;
 		};
 
-		pic@ff000000 {
-			linux,phandle = <ff000000>;
+		Mpc8xx_pic: pic@ff000000 {
 			interrupt-controller;
 			#address-cells = <0>;
 			#interrupt-cells = <2>;
@@ -112,8 +103,18 @@
 			compatible = "CPM";
 		};
 
+		pcmcia@0080 {
+			#address-cells = <3>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			compatible = "fsl,pq-pcmcia";
+			device_type = "pcmcia";
+			reg = <80 80>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			interrupts = <d 1>;
+		};
+
 		cpm@ff000000 {
-			linux,phandle = <ff000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			#interrupt-cells = <2>;
@@ -124,15 +125,14 @@
 			command-proc = <9c0>;
 			brg-frequency = <0>;
 			interrupts = <0 2>;	// cpm error interrupt
-			interrupt-parent = <930>;
+			interrupt-parent = <&Cpm_pic>;
 
-			pic@930 {
-				linux,phandle = <930>;
+			Cpm_pic: pic@930 {
 				interrupt-controller;
 				#address-cells = <0>;
 				#interrupt-cells = <2>;
 				interrupts = <5 2 0 2>;
-				interrupt-parent = <ff000000>;
+				interrupt-parent = <&Mpc8xx_pic>;
 				reg = <930 20>;
 				built-in;
 				device_type = "cpm-pic";
@@ -150,7 +150,7 @@
 				tx-clock = <1>;
 				current-speed = <0>;
 				interrupts = <4 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			smc@a90 {
@@ -164,7 +164,7 @@
 				tx-clock = <2>;
 				current-speed = <0>;
 				interrupts = <3 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			scc@a40 {
@@ -175,8 +175,8 @@
 				reg = <a40 18 3e00 80>;
 				mac-address = [ 00 00 0C 00 03 FD ];
 				interrupts = <1c 3>;
-				interrupt-parent = <930>;
-				phy-handle = <e8002>;
+				interrupt-parent = <&Cpm_pic>;
+				phy-handle = <&Phy2>;
 			};
 		};
 	};
diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts
index 568965a..699d0df 100644
--- a/arch/powerpc/boot/dts/prpmc2800.dts
+++ b/arch/powerpc/boot/dts/prpmc2800.dts
@@ -309,7 +309,7 @@
 	};
 
 	chosen {
-		bootargs = "ip=on console=ttyMM0";
+		bootargs = "ip=on";
 		linux,stdout-path = "/mv64x60@f1000000/mpsc@8000";
 	};
 };
diff --git a/arch/powerpc/boot/dts/ps3.dts b/arch/powerpc/boot/dts/ps3.dts
new file mode 100644
index 0000000..379ded2
--- /dev/null
+++ b/arch/powerpc/boot/dts/ps3.dts
@@ -0,0 +1,68 @@
+/*
+ *  PS3 Game Console device tree.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony 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; version 2 of the License.
+ *
+ *  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
+ */
+
+/ {
+	model = "SonyPS3";
+	compatible = "sony,ps3";
+	#size-cells = <2>;
+	#address-cells = <2>;
+
+	chosen {
+	};
+
+	/*
+	 * We'll get the size of the bootmem block from lv1 after startup,
+	 * so we'll put a null entry here.
+	 */
+
+	memory {
+		device_type = "memory";
+		reg = <0 0 0 0>;
+	};
+
+	/*
+	 * The boot cpu is always zero for PS3.
+	 *
+	 * dtc expects a clock-frequency and timebase-frequency entries, so
+	 * we'll put a null entries here.  These will be initialized after
+	 * startup with data from lv1.
+	 *
+	 * Seems the only way currently to indicate a processor has multiple
+	 * threads is with an ibm,ppc-interrupt-server#s entry.  We'll put one
+	 * here so we can bring up both of ours.  See smp_setup_cpu_maps().
+	 */
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			ibm,ppc-interrupt-server#s = <0 1>;
+			clock-frequency = <0>;
+			timebase-frequency = <0>;
+			i-cache-size = <8000>;
+			d-cache-size = <8000>;
+			i-cache-line-size = <80>;
+			d-cache-line-size = <80>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
index b1251ee..75daeda 100644
--- a/arch/powerpc/boot/ebony.c
+++ b/arch/powerpc/boot/ebony.c
@@ -100,28 +100,13 @@
 	ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
 	ibm44x_fixup_memsize();
 	dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
-}
-
-#define SPRN_DBCR0		0x134
-#define   DBCR0_RST_SYSTEM	0x30000000
-
-static void ebony_exit(void)
-{
-	unsigned long tmp;
-
-	asm volatile (
-		"mfspr	%0,%1\n"
-		"oris	%0,%0,%2@h\n"
-		"mtspr	%1,%0"
-		: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
-		);
-
+	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 }
 
 void ebony_init(void *mac0, void *mac1)
 {
 	platform_ops.fixups = ebony_fixups;
-	platform_ops.exit = ebony_exit;
+	platform_ops.exit = ibm44x_dbcr_reset;
 	ebony_mac0 = mac0;
 	ebony_mac1 = mac1;
 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 56b56a8..416dc38 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -36,8 +36,6 @@
 	unsigned long size;
 };
 
-typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
-
 #undef DEBUG
 
 static struct addr_range prep_kernel(void)
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index d16ee3e..385e08b 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -15,8 +15,7 @@
 #include "page.h"
 #include "ops.h"
 
-typedef void *ihandle;
-typedef void *phandle;
+#include "of.h"
 
 extern char _end[];
 
@@ -25,154 +24,10 @@
 #define RAM_END		(512<<20)	/* Fixme: use OF */
 #define	ONE_MB		0x100000
 
-int (*prom) (void *);
 
 
 static unsigned long claim_base;
 
-static int call_prom(const char *service, int nargs, int nret, ...)
-{
-	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
-	va_list list;
-
-	args.service = service;
-	args.nargs = nargs;
-	args.nret = nret;
-
-	va_start(list, nret);
-	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
-	va_end(list);
-
-	for (i = 0; i < nret; i++)
-		args.args[nargs+i] = 0;
-
-	if (prom(&args) < 0)
-		return -1;
-
-	return (nret > 0)? args.args[nargs]: 0;
-}
-
-static int call_prom_ret(const char *service, int nargs, int nret,
-		  unsigned int *rets, ...)
-{
-	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
-	va_list list;
-
-	args.service = service;
-	args.nargs = nargs;
-	args.nret = nret;
-
-	va_start(list, rets);
-	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
-	va_end(list);
-
-	for (i = 0; i < nret; i++)
-		args.args[nargs+i] = 0;
-
-	if (prom(&args) < 0)
-		return -1;
-
-	if (rets != (void *) 0)
-		for (i = 1; i < nret; ++i)
-			rets[i-1] = args.args[nargs+i];
-
-	return (nret > 0)? args.args[nargs]: 0;
-}
-
-/*
- * Older OF's require that when claiming a specific range of addresses,
- * we claim the physical space in the /memory node and the virtual
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
-	for (; *s2; ++s2)
-		if (*s1++ != *s2)
-			return 0;
-	return 1;
-}
-
-static int check_of_version(void)
-{
-	phandle oprom, chosen;
-	char version[64];
-
-	oprom = finddevice("/openprom");
-	if (oprom == (phandle) -1)
-		return 0;
-	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
-		return 0;
-	version[sizeof(version)-1] = 0;
-	printf("OF version = '%s'\r\n", version);
-	if (!string_match(version, "Open Firmware, 1.")
-	    && !string_match(version, "FirmWorks,3."))
-		return 0;
-	chosen = finddevice("/chosen");
-	if (chosen == (phandle) -1) {
-		chosen = finddevice("/chosen@0");
-		if (chosen == (phandle) -1) {
-			printf("no chosen\n");
-			return 0;
-		}
-	}
-	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
-		printf("no mmu\n");
-		return 0;
-	}
-	memory = (ihandle) call_prom("open", 1, 1, "/memory");
-	if (memory == (ihandle) -1) {
-		memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
-		if (memory == (ihandle) -1) {
-			printf("no memory node\n");
-			return 0;
-		}
-	}
-	printf("old OF detected\r\n");
-	return 1;
-}
-
-static void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-	int ret;
-	unsigned int result;
-
-	if (need_map < 0)
-		need_map = check_of_version();
-	if (align || !need_map)
-		return (void *) call_prom("claim", 3, 1, virt, size, align);
-
-	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
-			    align, size, virt);
-	if (ret != 0 || result == -1)
-		return (void *) -1;
-	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
-			    align, size, virt);
-	/* 0x12 == coherent + read/write */
-	ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
-			0x12, size, virt, virt);
-	return (void *) virt;
-}
-
 static void *of_try_claim(unsigned long size)
 {
 	unsigned long addr = 0;
@@ -184,7 +39,7 @@
 #ifdef DEBUG
 		printf("    trying: 0x%08lx\n\r", claim_base);
 #endif
-		addr = (unsigned long)claim(claim_base, size, 0);
+		addr = (unsigned long)of_claim(claim_base, size, 0);
 		if ((void *)addr != (void *)-1)
 			break;
 	}
@@ -208,64 +63,6 @@
 	}
 }
 
-static void *of_vmlinux_alloc(unsigned long size)
-{
-	void *p = malloc(size);
-
-	if (!p)
-		fatal("Can't allocate memory for kernel image!\n\r");
-
-	return p;
-}
-
-static void of_exit(void)
-{
-	call_prom("exit", 0, 0);
-}
-
-/*
- * OF device tree routines
- */
-static void *of_finddevice(const char *name)
-{
-	return (phandle) call_prom("finddevice", 1, 1, name);
-}
-
-static int of_getprop(const void *phandle, const char *name, void *buf,
-		const int buflen)
-{
-	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
-}
-
-static int of_setprop(const void *phandle, const char *name, const void *buf,
-		const int buflen)
-{
-	return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
-}
-
-/*
- * OF console routines
- */
-static void *of_stdout_handle;
-
-static int of_console_open(void)
-{
-	void *devp;
-
-	if (((devp = finddevice("/chosen")) != NULL)
-			&& (getprop(devp, "stdout", &of_stdout_handle,
-				sizeof(of_stdout_handle))
-				== sizeof(of_stdout_handle)))
-		return 0;
-
-	return -1;
-}
-
-static void of_console_write(char *buf, int len)
-{
-	call_prom("write", 3, 1, of_stdout_handle, buf, len);
-}
-
 void platform_init(unsigned long a1, unsigned long a2, void *promptr)
 {
 	platform_ops.image_hdr = of_image_hdr;
@@ -277,10 +74,9 @@
 	dt_ops.getprop = of_getprop;
 	dt_ops.setprop = of_setprop;
 
-	console_ops.open = of_console_open;
-	console_ops.write = of_console_write;
+	of_console_init();
 
-	prom = (int (*)(void *))promptr;
+	of_init(promptr);
 	loader_info.promptr = promptr;
 	if (a1 && a2 && a2 != 0xdeadbeef) {
 		loader_info.initrd_addr = a1;
diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
new file mode 100644
index 0000000..e4c68f7
--- /dev/null
+++ b/arch/powerpc/boot/of.h
@@ -0,0 +1,21 @@
+#ifndef _PPC_BOOT_OF_H_
+#define _PPC_BOOT_OF_H_
+
+typedef void *phandle;
+typedef void *ihandle;
+
+void of_init(void *promptr);
+int of_call_prom(const char *service, int nargs, int nret, ...);
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
+void *of_vmlinux_alloc(unsigned long size);
+void of_exit(void);
+void *of_finddevice(const char *name);
+int of_getprop(const void *phandle, const char *name, void *buf,
+	       const int buflen);
+int of_setprop(const void *phandle, const char *name, const void *buf,
+	       const int buflen);
+
+/* Console functions */
+void of_console_init(void);
+
+#endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c
new file mode 100644
index 0000000..ce0e024
--- /dev/null
+++ b/arch/powerpc/boot/ofconsole.c
@@ -0,0 +1,45 @@
+/*
+ * OF console routines
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static void *of_stdout_handle;
+
+static int of_console_open(void)
+{
+	void *devp;
+
+	if (((devp = of_finddevice("/chosen")) != NULL)
+	    && (of_getprop(devp, "stdout", &of_stdout_handle,
+			   sizeof(of_stdout_handle))
+		== sizeof(of_stdout_handle)))
+		return 0;
+
+	return -1;
+}
+
+static void of_console_write(const char *buf, int len)
+{
+	of_call_prom("write", 3, 1, of_stdout_handle, buf, len);
+}
+
+void of_console_init(void)
+{
+	console_ops.open = of_console_open;
+	console_ops.write = of_console_write;
+}
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
new file mode 100644
index 0000000..95b8fd6
--- /dev/null
+++ b/arch/powerpc/boot/oflib.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static int (*prom) (void *);
+
+void of_init(void *promptr)
+{
+	prom = (int (*)(void *))promptr;
+}
+
+int of_call_prom(const char *service, int nargs, int nret, ...)
+{
+	int i;
+	struct prom_args {
+		const char *service;
+		int nargs;
+		int nret;
+		unsigned int args[12];
+	} args;
+	va_list list;
+
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
+
+	va_start(list, nret);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
+
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
+
+	if (prom(&args) < 0)
+		return -1;
+
+	return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int of_call_prom_ret(const char *service, int nargs, int nret,
+			    unsigned int *rets, ...)
+{
+	int i;
+	struct prom_args {
+		const char *service;
+		int nargs;
+		int nret;
+		unsigned int args[12];
+	} args;
+	va_list list;
+
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
+
+	va_start(list, rets);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
+
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
+
+	if (prom(&args) < 0)
+		return -1;
+
+	if (rets != (void *) 0)
+		for (i = 1; i < nret; ++i)
+			rets[i-1] = args.args[nargs+i];
+
+	return (nret > 0)? args.args[nargs]: 0;
+}
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+	for (; *s2; ++s2)
+		if (*s1++ != *s2)
+			return 0;
+	return 1;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+static int check_of_version(void)
+{
+	phandle oprom, chosen;
+	char version[64];
+
+	oprom = of_finddevice("/openprom");
+	if (oprom == (phandle) -1)
+		return 0;
+	if (of_getprop(oprom, "model", version, sizeof(version)) <= 0)
+		return 0;
+	version[sizeof(version)-1] = 0;
+	printf("OF version = '%s'\r\n", version);
+	if (!string_match(version, "Open Firmware, 1.")
+	    && !string_match(version, "FirmWorks,3."))
+		return 0;
+	chosen = of_finddevice("/chosen");
+	if (chosen == (phandle) -1) {
+		chosen = of_finddevice("/chosen@0");
+		if (chosen == (phandle) -1) {
+			printf("no chosen\n");
+			return 0;
+		}
+	}
+	if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+		printf("no mmu\n");
+		return 0;
+	}
+	memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
+	if (memory == (ihandle) -1) {
+		memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
+		if (memory == (ihandle) -1) {
+			printf("no memory node\n");
+			return 0;
+		}
+	}
+	printf("old OF detected\r\n");
+	return 1;
+}
+
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+	int ret;
+	unsigned int result;
+
+	if (need_map < 0)
+		need_map = check_of_version();
+	if (align || !need_map)
+		return (void *) of_call_prom("claim", 3, 1, virt, size, align);
+
+	ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+			       align, size, virt);
+	if (ret != 0 || result == -1)
+		return (void *) -1;
+	ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+			       align, size, virt);
+	/* 0x12 == coherent + read/write */
+	ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
+			   0x12, size, virt, virt);
+	return (void *) virt;
+}
+
+void *of_vmlinux_alloc(unsigned long size)
+{
+	void *p = malloc(size);
+
+	if (!p)
+		fatal("Can't allocate memory for kernel image!\n\r");
+
+	return p;
+}
+
+void of_exit(void)
+{
+	of_call_prom("exit", 0, 0);
+}
+
+/*
+ * OF device tree routines
+ */
+void *of_finddevice(const char *name)
+{
+	return (phandle) of_call_prom("finddevice", 1, 1, name);
+}
+
+int of_getprop(const void *phandle, const char *name, void *buf,
+	       const int buflen)
+{
+	return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
+int of_setprop(const void *phandle, const char *name, const void *buf,
+	       const int buflen)
+{
+	return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 959124f..8607706 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -19,6 +19,8 @@
 #define	MAX_PATH_LEN		256
 #define	MAX_PROP_LEN		256 /* What should this be? */
 
+typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5);
+
 /* Platform specific operations */
 struct platform_ops {
 	void	(*fixups)(void);
@@ -51,7 +53,7 @@
 /* Console operations */
 struct console_ops {
 	int	(*open)(void);
-	void	(*write)(char *buf, int len);
+	void	(*write)(const char *buf, int len);
 	void	(*edit_cmdline)(char *buf, int len);
 	void	(*close)(void);
 	void	*data;
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
new file mode 100644
index 0000000..1a6d64a
--- /dev/null
+++ b/arch/powerpc/boot/ps3-head.S
@@ -0,0 +1,80 @@
+/*
+ *  PS3 bootwrapper entry.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony 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; version 2 of the License.
+ *
+ *  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 "ppc_asm.h"
+
+	.text
+
+/*
+ * __system_reset_overlay - The PS3 first stage entry.
+ *
+ * The bootwraper build script copies the 0x100 bytes at symbol
+ * __system_reset_overlay to offset 0x100 of the rom image.
+ *
+ * The PS3 has a single processor with two threads.
+ */
+
+	.globl __system_reset_overlay
+__system_reset_overlay:
+
+	/* Switch to 32-bit mode. */
+
+	mfmsr	r9
+	clrldi	r9,r9,1
+	mtmsrd	r9
+	nop
+
+	/* Get thread number in r3 and branch. */
+
+	mfspr	r3, 0x88
+	cntlzw.	r3, r3
+	li	r4, 0
+	li	r5, 0
+	beq	1f
+
+	/* Secondary goes to __secondary_hold in kernel. */
+
+	li	r4, 0x60
+	mtctr	r4
+	bctr
+
+	/* Primary delays then goes to _zimage_start in wrapper. */
+1:
+	or	31, 31, 31 /* db16cyc */
+	or	31, 31, 31 /* db16cyc */
+
+	lis	r4, _zimage_start@ha
+	addi	r4, r4, _zimage_start@l
+	mtctr	r4
+	bctr
+
+/*
+ * __system_reset_kernel - Place holder for the kernel reset vector.
+ *
+ * The bootwrapper build script copies 0x100 bytes from offset 0x100
+ * of the rom image to the symbol __system_reset_kernel.  At runtime
+ * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+ * to ram address 0x100.  This symbol must occupy 0x100 bytes.
+ */
+
+	.globl __system_reset_kernel
+__system_reset_kernel:
+
+	. = __system_reset_kernel + 0x100
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S
new file mode 100644
index 0000000..c8b7df3
--- /dev/null
+++ b/arch/powerpc/boot/ps3-hvcall.S
@@ -0,0 +1,184 @@
+/*
+ *  PS3 bootwrapper hvcalls.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony 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; version 2 of the License.
+ *
+ *  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 "ppc_asm.h"
+
+/*
+ * The PS3 hypervisor uses a 64 bit "C" language calling convention.
+ * The routines here marshal arguments between the 32 bit wrapper
+ * program and the 64 bit hvcalls.
+ *
+ *  wrapper           lv1
+ *  32-bit (h,l)      64-bit
+ *
+ *  1: r3,r4          <-> r3
+ *  2: r5,r6          <-> r4
+ *  3: r7,r8          <-> r5
+ *  4: r9,r10         <-> r6
+ *  5: 8(r1),12(r1)   <-> r7
+ *  6: 16(r1),20(r1)  <-> r8
+ *  7: 24(r1),28(r1)  <-> r9
+ *  8: 32(r1),36(r1)  <-> r10
+ *
+ */
+
+.macro GLOBAL name
+	.section ".text"
+	.balign 4
+	.globl \name
+\name:
+.endm
+
+.macro NO_SUPPORT name
+	GLOBAL \name
+	b ps3_no_support
+.endm
+
+.macro HVCALL num
+	li r11, \num
+	.long 0x44000022
+	extsw r3, r3
+.endm
+
+.macro SAVE_LR offset=4
+	mflr r0
+	stw r0, \offset(r1)
+.endm
+
+.macro LOAD_LR offset=4
+	lwz r0, \offset(r1)
+	mtlr r0
+.endm
+
+.macro LOAD_64_REG target,high,low
+	sldi r11, \high, 32
+	or \target, r11, \low
+.endm
+
+.macro LOAD_64_STACK target,offset
+	ld \target, \offset(r1)
+.endm
+
+.macro LOAD_R3
+	LOAD_64_REG r3,r3,r4
+.endm
+
+.macro LOAD_R4
+	LOAD_64_REG r4,r5,r6
+.endm
+
+.macro LOAD_R5
+	LOAD_64_REG r5,r7,r8
+.endm
+
+.macro LOAD_R6
+	LOAD_64_REG r6,r9,r10
+.endm
+
+.macro LOAD_R7
+	LOAD_64_STACK r7,8
+.endm
+
+.macro LOAD_R8
+	LOAD_64_STACK r8,16
+.endm
+
+.macro LOAD_R9
+	LOAD_64_STACK r9,24
+.endm
+
+.macro LOAD_R10
+	LOAD_64_STACK r10,32
+.endm
+
+.macro LOAD_REGS_0
+	stwu 1,-16(1)
+	stw 3, 8(1)
+.endm
+
+.macro LOAD_REGS_5
+	LOAD_R3
+	LOAD_R4
+	LOAD_R5
+	LOAD_R6
+	LOAD_R7
+.endm
+
+.macro LOAD_REGS_6
+	LOAD_REGS_5
+	LOAD_R8
+.endm
+
+.macro LOAD_REGS_8
+	LOAD_REGS_6
+	LOAD_R9
+	LOAD_R10
+.endm
+
+.macro STORE_REGS_0_1
+	lwz r11, 8(r1)
+	std r4, 0(r11)
+	mr r4, r3
+	li r3, 0
+	addi r1,r1,16
+.endm
+
+.macro STORE_REGS_5_2
+	lwz r11, 16(r1)
+	std r4, 0(r11)
+	lwz r11, 24(r1)
+	std r5, 0(r11)
+.endm
+
+.macro STORE_REGS_6_1
+	lwz r11, 24(r1)
+	std r4, 0(r11)
+.endm
+
+GLOBAL lv1_get_logical_ppe_id
+	SAVE_LR
+	LOAD_REGS_0
+	HVCALL 69
+	STORE_REGS_0_1
+	LOAD_LR
+	blr
+
+GLOBAL lv1_get_logical_partition_id
+	SAVE_LR
+	LOAD_REGS_0
+	HVCALL 74
+	STORE_REGS_0_1
+	LOAD_LR
+	blr
+
+GLOBAL lv1_get_repository_node_value
+	SAVE_LR
+	LOAD_REGS_5
+	HVCALL 91
+	STORE_REGS_5_2
+	LOAD_LR
+	blr
+
+GLOBAL lv1_panic
+	SAVE_LR
+	LOAD_REGS_8
+	HVCALL 255
+	LOAD_LR
+	blr
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
new file mode 100644
index 0000000..893d593
--- /dev/null
+++ b/arch/powerpc/boot/ps3.c
@@ -0,0 +1,161 @@
+/*
+ *  PS3 bootwrapper support.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony 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; version 2 of the License.
+ *
+ *  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 <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+extern s64 lv1_panic(u64 in_1);
+extern s64 lv1_get_logical_partition_id(u64 *out_1);
+extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+	u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+
+#ifdef DEBUG
+#define DBG(fmt...) printf(fmt)
+#else
+static inline int __attribute__ ((format (printf, 1, 2))) DBG(
+	const char *fmt, ...) {return 0;}
+#endif
+
+BSS_STACK(4096);
+
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char cmdline[COMMAND_LINE_SIZE]
+	__attribute__((__section__("__builtin_cmdline")));
+
+static void prep_cmdline(void *chosen)
+{
+	if (cmdline[0] == '\0')
+		getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+	else
+		setprop_str(chosen, "bootargs", cmdline);
+
+	printf("cmdline: '%s'\n", cmdline);
+}
+
+static void ps3_console_write(const char *buf, int len)
+{
+}
+
+static void ps3_exit(void)
+{
+	printf("ps3_exit\n");
+
+	/* lv1_panic will shutdown the lpar. */
+
+	lv1_panic(0); /* zero = do not reboot */
+	while (1);
+}
+
+static int ps3_repository_read_rm_size(u64 *rm_size)
+{
+	s64 result;
+	u64 lpar_id;
+	u64 ppe_id;
+	u64 v2;
+
+	result = lv1_get_logical_partition_id(&lpar_id);
+
+	if (result)
+		return -1;
+
+	result = lv1_get_logical_ppe_id(&ppe_id);
+
+	if (result)
+		return -1;
+
+	/*
+	 * n1: 0000000062690000 : ....bi..
+	 * n2: 7075000000000000 : pu......
+	 * n3: 0000000000000001 : ........
+	 * n4: 726d5f73697a6500 : rm_size.
+	*/
+
+	result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
+		0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
+		&v2);
+
+	printf("%s:%d: ppe_id  %lu \n", __func__, __LINE__,
+		(unsigned long)ppe_id);
+	printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
+		(unsigned long)lpar_id);
+	printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
+
+	return result ? -1 : 0;
+}
+
+void ps3_copy_vectors(void)
+{
+	extern char __system_reset_kernel[];
+
+	memcpy((void *)0x100, __system_reset_kernel, 0x100);
+	flush_cache((void *)0x100, 0x100);
+}
+
+void platform_init(void)
+{
+	extern char _end[];
+	extern char _dtb_start[];
+	extern char _initrd_start[];
+	extern char _initrd_end[];
+	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+	void *chosen;
+	unsigned long ft_addr;
+	u64 rm_size;
+
+	console_ops.write = ps3_console_write;
+	platform_ops.exit = ps3_exit;
+
+	printf("\n-- PS3 bootwrapper --\n");
+
+	simple_alloc_init(_end, heapsize, 32, 64);
+	ft_init(_dtb_start, 0, 4);
+
+	chosen = finddevice("/chosen");
+
+	ps3_repository_read_rm_size(&rm_size);
+	dt_fixup_memory(0, rm_size);
+
+	if (_initrd_end > _initrd_start) {
+		setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
+		setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
+	}
+
+	prep_cmdline(chosen);
+
+	ft_addr = dt_ops.finalize();
+
+	ps3_copy_vectors();
+
+	printf(" flat tree at 0x%lx\n\r", ft_addr);
+
+	((kernel_entry_t)0)(ft_addr, 0, NULL);
+
+	ps3_exit();
+}
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
index 7fd3233..eaa0d3a 100644
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -27,7 +27,7 @@
 	return scdp->open();
 }
 
-static void serial_write(char *buf, int len)
+static void serial_write(const char *buf, int len)
 {
 	struct serial_console_data *scdp = console_ops.data;
 
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 0a9feeb..5b57800 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -190,7 +190,11 @@
 
 		/* get the conversion qualifier */
 		qualifier = -1;
-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+		if (*fmt == 'l' && *(fmt + 1) == 'l') {
+			qualifier = 'q';
+			fmt += 2;
+		} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
+			|| *fmt == 'Z') {
 			qualifier = *fmt;
 			++fmt;
 		}
@@ -281,6 +285,10 @@
 			num = va_arg(args, unsigned long);
 			if (flags & SIGN)
 				num = (signed long) num;
+		} else if (qualifier == 'q') {
+			num = va_arg(args, unsigned long long);
+			if (flags & SIGN)
+				num = (signed long long) num;
 		} else if (qualifier == 'Z') {
 			num = va_arg(args, size_t);
 		} else if (qualifier == 'h') {
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
index 79d26e7..31393d1 100644
--- a/arch/powerpc/boot/types.h
+++ b/arch/powerpc/boot/types.h
@@ -7,6 +7,10 @@
 typedef unsigned short		u16;
 typedef unsigned int		u32;
 typedef unsigned long long	u64;
+typedef signed char		s8;
+typedef short			s16;
+typedef int			s32;
+typedef long long		s64;
 
 #define min(x,y) ({ \
 	typeof(x) _x = (x);	\
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index da77adc..65f6854 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -144,6 +144,15 @@
 cuboot*)
     gzip=
     ;;
+ps3)
+    platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
+    lds=$object/zImage.ps3.lds
+    gzip=
+    ext=bin
+    objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
+    ksection=.kernel:vmlinux.bin
+    isection=.kernel:initrd
+    ;;
 esac
 
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
@@ -239,4 +248,50 @@
     fi
     exit 0
     ;;
+ps3)
+    # The ps3's loader supports loading gzipped binary images from flash
+    # rom to addr zero. The loader enters the image at addr 0x100.  A
+    # bootwrapper overlay is use to arrange for the kernel to be loaded
+    # to addr zero and to have a suitable bootwrapper entry at 0x100.
+    # To construct the rom image, 0x100 bytes from offset 0x100 in the
+    # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+    # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+    # then copied to offset 0x100.  At runtime the bootwrapper program
+    # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
+
+    system_reset_overlay=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_overlay$'       \
+        | cut -d' ' -f1`
+    system_reset_overlay=`printf "%d" $system_reset_overlay`
+    system_reset_kernel=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_kernel$'       \
+        | cut -d' ' -f1`
+    system_reset_kernel=`printf "%d" $system_reset_kernel`
+    overlay_dest="256"
+    overlay_size="256"
+
+    rm -f "$object/otheros.bld"
+
+    ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$overlay_dest seek=$system_reset_kernel      \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 1
+    fi
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$system_reset_overlay seek=$overlay_dest     \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 2
+    fi
+
+    gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
+    ;;
 esac
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S
new file mode 100644
index 0000000..aaa469c
--- /dev/null
+++ b/arch/powerpc/boot/zImage.ps3.lds.S
@@ -0,0 +1,50 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_zimage_start)
+EXTERN(_zimage_start)
+SECTIONS
+{
+  _vmlinux_start =  .;
+  .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) }
+  _vmlinux_end =  .;
+
+  . = ALIGN(4096);
+  _dtb_start = .;
+  .kernel:dtb : { *(.kernel:dtb) }
+  _dtb_end = .;
+
+  . = ALIGN(4096);
+  _initrd_start =  .;
+  .kernel:initrd : { *(.kernel:initrd) }
+  _initrd_end =  .;
+
+  _start = .;
+  .text      :
+  {
+    *(.text)
+    *(.fixup)
+  }
+  _etext = .;
+  . = ALIGN(4096);
+  .data    :
+  {
+    *(.rodata*)
+    *(.data*)
+    *(.sdata*)
+    __got2_start = .;
+    *(.got2)
+    __got2_end = .;
+  }
+
+  . = ALIGN(4096);
+  _edata  =  .;
+
+  . = ALIGN(4096);
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss)
+   *(.bss)
+  }
+  . = ALIGN(4096);
+  _end = . ;
+}
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig
index 3278184..04b94f8 100644
--- a/arch/powerpc/configs/holly_defconfig
+++ b/arch/powerpc/configs/holly_defconfig
@@ -190,10 +190,12 @@
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
-# CONFIG_WANT_DEVICE_TREE is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE="holly.dts"
 CONFIG_ISA_DMA_API=y
 
 #
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 956d1df..d0b43df 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -156,7 +156,11 @@
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
 CONFIG_PS3_PS3AV=y
-CONFIG_PS3_SYS_MANAGER=y
+CONFIG_PS3_SYS_MANAGER=m
+CONFIG_PS3_STORAGE=y
+CONFIG_PS3_DISK=y
+CONFIG_PS3_ROM=y
+CONFIG_PS3_FLASH=y
 CONFIG_PPC_CELL=y
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
@@ -335,7 +339,7 @@
 CONFIG_BT_L2CAP=m
 CONFIG_BT_SCO=m
 CONFIG_BT_RFCOMM=m
-# CONFIG_BT_RFCOMM_TTY is not set
+CONFIG_BT_RFCOMM_TTY=y
 # CONFIG_BT_BNEP is not set
 CONFIG_BT_HIDP=m
 
@@ -344,7 +348,9 @@
 #
 CONFIG_BT_HCIUSB=m
 CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
@@ -435,7 +441,7 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
@@ -479,6 +485,7 @@
 CONFIG_MII=m
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
+CONFIG_GELIC_NET=y
 
 #
 # Wireless LAN
@@ -546,7 +553,27 @@
 #
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_JOYSTICK_XPAD is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
@@ -563,7 +590,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -1086,7 +1113,7 @@
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1116,16 +1143,7 @@
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 3e779f0..42c42ec 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,7 +12,8 @@
 
 obj-y				:= semaphore.o cputable.o ptrace.o syscalls.o \
 				   irq.o align.o signal_32.o pmc.o vdso.o \
-				   init_task.o process.o systbl.o idle.o
+				   init_task.o process.o systbl.o idle.o \
+				   signal.o
 obj-y				+= vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
 				   signal_64.o ptrace32.o \
@@ -65,9 +66,9 @@
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
 
-pci64-$(CONFIG_PPC64)		+= pci_64.o pci_dn.o
+pci64-$(CONFIG_PPC64)		+= pci_64.o pci_dn.o isa-bridge.o
 pci32-$(CONFIG_PPC32)		:= pci_32.o
-obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y)
+obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y) pci-common.o
 obj-$(CONFIG_PCI_MSI)		+= msi.o
 kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
 kexec-$(CONFIG_PPC32)		:= machine_kexec_32.o
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index b2b5d66..b1f8000 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -294,6 +294,21 @@
 		.oprofile_mmcra_sipr	= MMCRA_SIPR,
 		.platform		= "power5",
 	},
+	{	/* Power5++ */
+		.pvr_mask		= 0xffffff00,
+		.pvr_value		= 0x003b0300,
+		.cpu_name		= "POWER5+ (gs)",
+		.cpu_features		= CPU_FTRS_POWER5,
+		.cpu_user_features	= COMMON_USER_POWER5_PLUS,
+		.icache_bsize		= 128,
+		.dcache_bsize		= 128,
+		.num_pmcs		= 6,
+		.oprofile_cpu_type	= "ppc64/power5++",
+		.oprofile_type		= PPC_OPROFILE_POWER4,
+		.oprofile_mmcra_sihv	= MMCRA_SIHV,
+		.oprofile_mmcra_sipr	= MMCRA_SIPR,
+		.platform		= "power5+",
+	},
 	{	/* Power5 GS */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x003b0000,
@@ -1178,8 +1193,8 @@
 		.platform		= "ppc440",
 	},
 	{ /* 440SP Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000891,
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53200891,
 		.cpu_name		= "440SP Rev. A",
 		.cpu_features		= CPU_FTRS_44X,
 		.cpu_user_features	= COMMON_USER_BOOKE,
@@ -1188,9 +1203,19 @@
 		.platform		= "ppc440",
 	},
 	{ /* 440SPe Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000890,
-		.cpu_name		= "440SPe Rev. A",
+		.pvr_mask               = 0xfff00fff,
+		.pvr_value              = 0x53400890,
+		.cpu_name               = "440SPe Rev. A",
+		.cpu_features		= CPU_FTRS_44X,
+		.cpu_user_features      = COMMON_USER_BOOKE,
+		.icache_bsize           = 32,
+		.dcache_bsize           = 32,
+		.platform               = "ppc440",
+	},
+	{ /* 440SPe Rev. B */
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53400891,
+		.cpu_name		= "440SPe Rev. B",
 		.cpu_features		= CPU_FTRS_44X,
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.icache_bsize		= 32,
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index c897203..7d73a13 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -9,7 +9,6 @@
  *  rewritten by Paul Mackerras.
  *    Copyright (C) 1996 Paul Mackerras.
  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  This file contains the low-level support and setup for the
  *  PowerPC platform, including trap and interrupt dispatch.
@@ -32,10 +31,6 @@
 #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 */ \
@@ -92,11 +87,6 @@
  *  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
@@ -150,14 +140,6 @@
  */
 	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()
  */
@@ -167,7 +149,7 @@
 	bl	flush_tlbs
 
 	bl	initial_bats
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#if defined(CONFIG_BOOTX_TEXT)
 	bl	setup_disp_bat
 #endif
 
@@ -183,7 +165,6 @@
 #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
@@ -196,7 +177,6 @@
 	addis	r4,r3,KERNELBASE@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.
@@ -881,85 +861,6 @@
 	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@h    /* virt_to_phys constant */
-	neg	r11,r10	                 /* phys_to_virt constant */
-
-	lis	r12,__vtop_table_begin@h
-	ori	r12,r12,__vtop_table_begin@l
-	add	r12,r12,r10	         /* table begin phys address */
-	lis	r13,__vtop_table_end@h
-	ori	r13,r13,__vtop_table_end@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@h
-	ori	r12,r12,__ptov_table_begin@l
-	add	r12,r12,r10	         /* table begin phys address */
-	lis	r13,__ptov_table_end@h
-	ori	r13,r13,__ptov_table_end@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
@@ -1135,19 +1036,6 @@
 	bl	__save_cpu_setup
 	bl	MMU_init
 
-#ifdef CONFIG_APUS
-	/* Copy exception code to exception vector base on APUS. */
-	lis	r4,KERNELBASE@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
@@ -1324,11 +1212,7 @@
 #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 */
@@ -1338,7 +1222,7 @@
 	blr
 
 
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#ifdef CONFIG_BOOTX_TEXT
 setup_disp_bat:
 	/*
 	 * setup the display bat prepared for us in prom.c
@@ -1362,7 +1246,7 @@
 1:	mtspr	SPRN_IBAT3L,r8
 	mtspr	SPRN_IBAT3U,r11
 	blr
-#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+#endif /* CONFIG_BOOTX_TEXT */
 
 #ifdef CONFIG_8260
 /* Jump into the system reset for the rom.
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 1111fce..8cdd48e 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -103,8 +103,8 @@
 
 	. = 0x60
 /*
- * The following code is used on pSeries to hold secondary processors
- * in a spin loop after they have been freed from OpenFirmware, but
+ * The following code is used to hold secondary processors
+ * in a spin loop after they have entered the kernel, 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.
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c
index 34ae114..e31aca92 100644
--- a/arch/powerpc/kernel/io.c
+++ b/arch/powerpc/kernel/io.c
@@ -35,7 +35,7 @@
 	asm volatile("sync");
 	do {
 		tmp = *port;
-		asm volatile("eieio");
+		eieio();
 		*tbuf++ = tmp;
 	} while (--count != 0);
 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -66,7 +66,7 @@
 	asm volatile("sync");
 	do {
 		tmp = *port;
-		asm volatile("eieio");
+		eieio();
 		*tbuf++ = tmp;
 	} while (--count != 0);
 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -97,7 +97,7 @@
 	asm volatile("sync");
 	do {
 		tmp = *port;
-		asm volatile("eieio");
+		eieio();
 		*tbuf++ = tmp;
 	} while (--count != 0);
 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -155,21 +155,21 @@
 	__asm__ __volatile__ ("sync" : : : "memory");
 	while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
 		*((u8 *)dest) = *((volatile u8 *)vsrc);
-		__asm__ __volatile__ ("eieio" : : : "memory");
+		eieio();
 		vsrc++;
 		dest++;
 		n--;
 	}
 	while(n > 4) {
 		*((u32 *)dest) = *((volatile u32 *)vsrc);
-		__asm__ __volatile__ ("eieio" : : : "memory");
+		eieio();
 		vsrc += 4;
 		dest += 4;
 		n -= 4;
 	}
 	while(n) {
 		*((u8 *)dest) = *((volatile u8 *)vsrc);
-		__asm__ __volatile__ ("eieio" : : : "memory");
+		eieio();
 		vsrc++;
 		dest++;
 		n--;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index c2b84c6..2fc8786 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -7,7 +7,6 @@
  *    Copyright (C) 1996-2001 Cort Dougan
  *  Adapted for Power Macintosh by Paul Mackerras
  *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -337,7 +336,8 @@
 
 void __init init_IRQ(void)
 {
-	ppc_md.init_IRQ();
+	if (ppc_md.init_IRQ)
+		ppc_md.init_IRQ();
 #ifdef CONFIG_PPC64
 	irq_ctx_init();
 #endif
@@ -597,6 +597,49 @@
 	local_irq_restore(flags);
 }
 
+static int irq_setup_virq(struct irq_host *host, unsigned int virq,
+			    irq_hw_number_t hwirq)
+{
+	/* Clear IRQ_NOREQUEST flag */
+	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
+
+	/* map it */
+	smp_wmb();
+	irq_map[virq].hwirq = hwirq;
+	smp_mb();
+
+	if (host->ops->map(host, virq, hwirq)) {
+		pr_debug("irq: -> mapping failed, freeing\n");
+		irq_free_virt(virq, 1);
+		return -1;
+	}
+
+	return 0;
+}
+
+unsigned int irq_create_direct_mapping(struct irq_host *host)
+{
+	unsigned int virq;
+
+	if (host == NULL)
+		host = irq_default_host;
+
+	BUG_ON(host == NULL);
+	WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
+
+	virq = irq_alloc_virt(host, 1, 0);
+	if (virq == NO_IRQ) {
+		pr_debug("irq: create_direct virq allocation failed\n");
+		return NO_IRQ;
+	}
+
+	pr_debug("irq: create_direct obtained virq %d\n", virq);
+
+	if (irq_setup_virq(host, virq, virq))
+		return NO_IRQ;
+
+	return virq;
+}
 
 unsigned int irq_create_mapping(struct irq_host *host,
 				irq_hw_number_t hwirq)
@@ -645,18 +688,9 @@
 	}
 	pr_debug("irq: -> obtained virq %d\n", virq);
 
-	/* Clear IRQ_NOREQUEST flag */
-	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
-
-	/* map it */
-	smp_wmb();
-	irq_map[virq].hwirq = hwirq;
-	smp_mb();
-	if (host->ops->map(host, virq, hwirq)) {
-		pr_debug("irq: -> mapping failed, freeing\n");
-		irq_free_virt(virq, 1);
+	if (irq_setup_virq(host, virq, hwirq))
 		return NO_IRQ;
-	}
+
 	return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
new file mode 100644
index 0000000..f0f49d1
--- /dev/null
+++ b/arch/powerpc/kernel/isa-bridge.c
@@ -0,0 +1,271 @@
+/*
+ * Routines for tracking a legacy ISA bridge
+ *
+ * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ * Some bits and pieces moved over from pci_64.c
+ *
+ * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, 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/string.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+unsigned long isa_io_base;	/* NULL if no ISA bus */
+EXPORT_SYMBOL(isa_io_base);
+
+/* Cached ISA bridge dev. */
+static struct device_node *isa_bridge_devnode;
+struct pci_dev *isa_bridge_pcidev;
+EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
+
+#define ISA_SPACE_MASK 0x1
+#define ISA_SPACE_IO 0x1
+
+static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+						unsigned long phb_io_base_phys)
+{
+	/* We should get some saner parsing here and remove these structs */
+	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;
+	};
+
+	const struct isa_range *range;
+	unsigned long pci_addr;
+	unsigned int isa_addr;
+	unsigned int size;
+	int rlen = 0;
+
+	range = of_get_property(isa_node, "ranges", &rlen);
+	if (range == NULL || (rlen < sizeof(struct isa_range)))
+		goto inval_range;
+
+	/* From "ISA Binding to 1275"
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 1:	an ISA address
+	 *   cells 2 - 4:	a PCI address
+	 *			(size depending on dev->n_addr_cells)
+	 *   cell 5:		the size of the range
+	 */
+	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
+		range++;
+		rlen -= sizeof(struct isa_range);
+		if (rlen < sizeof(struct isa_range))
+			goto inval_range;
+	}
+	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
+		goto inval_range;
+
+	isa_addr = range->isa_addr.a_lo;
+	pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
+		range->pci_addr.a_lo;
+
+	/* Assume these are both zero. Note: We could fix that and
+	 * do a proper parsing instead ... oh well, that will do for
+	 * now as nobody uses fancy mappings for ISA bridges
+	 */
+	if ((pci_addr != 0) || (isa_addr != 0)) {
+		printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+		       __FUNCTION__);
+		return;
+	}
+
+	/* Align size and make sure it's cropped to 64K */
+	size = PAGE_ALIGN(range->size);
+	if (size > 0x10000)
+		size = 0x10000;
+
+	printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+	       "mapping 64k\n");
+
+	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+		     size, _PAGE_NO_CACHE|_PAGE_GUARDED);
+	return;
+
+inval_range:
+	printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+	       "mapping 64k\n");
+	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+		     0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
+}
+
+
+/**
+ * isa_bridge_find_early - Find and map the ISA IO space early before
+ *                         main PCI discovery. This is optionally called by
+ *                         the arch code when adding PCI PHBs to get early
+ *                         access to ISA IO ports
+ */
+void __init isa_bridge_find_early(struct pci_controller *hose)
+{
+	struct device_node *np, *parent = NULL, *tmp;
+
+	/* If we already have an ISA bridge, bail off */
+	if (isa_bridge_devnode != NULL)
+		return;
+
+	/* For each "isa" node in the system. Note : we do a search by
+	 * type and not by name. It might be better to do by name but that's
+	 * what the code used to do and I don't want to break too much at
+	 * once. We can look into changing that separately
+	 */
+	for_each_node_by_type(np, "isa") {
+		/* Look for our hose being a parent */
+		for (parent = of_get_parent(np); parent;) {
+			if (parent == hose->arch_data) {
+				of_node_put(parent);
+				break;
+			}
+			tmp = parent;
+			parent = of_get_parent(parent);
+			of_node_put(tmp);
+		}
+		if (parent != NULL)
+			break;
+	}
+	if (np == NULL)
+		return;
+	isa_bridge_devnode = np;
+
+	/* Now parse the "ranges" property and setup the ISA mapping */
+	pci_process_ISA_OF_ranges(np, hose->io_base_phys);
+
+	/* Set the global ISA io base to indicate we have an ISA bridge */
+	isa_io_base = ISA_IO_BASE;
+
+	pr_debug("ISA bridge (early) is %s\n", np->full_name);
+}
+
+/**
+ * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
+ *                        a new ISA bridge
+ */
+static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
+					   struct device_node *devnode)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+	/* Store ISA device node and PCI device */
+	isa_bridge_devnode = of_node_get(devnode);
+	isa_bridge_pcidev = pdev;
+
+	/* Now parse the "ranges" property and setup the ISA mapping */
+	pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
+
+	/* Set the global ISA io base to indicate we have an ISA bridge */
+	isa_io_base = ISA_IO_BASE;
+
+	pr_debug("ISA bridge (late) is %s on %s\n",
+		 devnode->full_name, pci_name(pdev));
+}
+
+/**
+ * isa_bridge_remove - Remove/unmap an ISA bridge
+ */
+static void isa_bridge_remove(void)
+{
+	pr_debug("ISA bridge removed !\n");
+
+	/* Clear the global ISA io base to indicate that we have no more
+	 * ISA bridge. Note that drivers don't quite handle that, though
+	 * we should probably do something about it. But do we ever really
+	 * have ISA bridges being removed on machines using legacy devices ?
+	 */
+	isa_io_base = ISA_IO_BASE;
+
+	/* Clear references to the bridge */
+	of_node_put(isa_bridge_devnode);
+	isa_bridge_devnode = NULL;
+	isa_bridge_pcidev = NULL;
+
+	/* Unmap the ISA area */
+	__iounmap_at((void *)ISA_IO_BASE, 0x10000);
+}
+
+/**
+ * isa_bridge_notify - Get notified of PCI devices addition/removal
+ */
+static int __devinit isa_bridge_notify(struct notifier_block *nb,
+				       unsigned long action, void *data)
+{
+	struct device *dev = data;
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct device_node *devnode = pci_device_to_OF_node(pdev);
+
+	switch(action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		/* Check if we have an early ISA device, without PCI dev */
+		if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
+		    !isa_bridge_pcidev) {
+			pr_debug("ISA bridge PCI attached: %s\n",
+				 pci_name(pdev));
+			isa_bridge_pcidev = pdev;
+		}
+
+		/* Check if we have no ISA device, and this happens to be one,
+		 * register it as such if it has an OF device
+		 */
+		if (!isa_bridge_devnode && devnode && devnode->type &&
+		    !strcmp(devnode->type, "isa"))
+			isa_bridge_find_late(pdev, devnode);
+
+		return 0;
+	case BUS_NOTIFY_DEL_DEVICE:
+		/* Check if this our existing ISA device */
+		if (pdev == isa_bridge_pcidev ||
+		    (devnode && devnode == isa_bridge_devnode))
+			isa_bridge_remove();
+		return 0;
+	}
+	return 0;
+}
+
+static struct notifier_block isa_bridge_notifier = {
+	.notifier_call = isa_bridge_notify
+};
+
+/**
+ * isa_bridge_init - register to be notified of ISA bridge addition/removal
+ *
+ */
+static int __init isa_bridge_init(void)
+{
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+	bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
+	return 0;
+}
+arch_initcall(isa_bridge_init);
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 98decf8..e708ab7 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -392,7 +392,7 @@
 	mtspr   SPRN_L1CSR0,r3
 	isync
 	blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
 	mfspr	r3,SPRN_L1CSR1
 	ori	r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
 	mtspr	SPRN_L1CSR1,r3
@@ -419,7 +419,7 @@
 _GLOBAL(__flush_icache_range)
 BEGIN_FTR_SECTION
 	blr				/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	li	r5,L1_CACHE_BYTES-1
 	andc	r3,r3,r5
 	subf	r4,r3,r4
@@ -514,8 +514,8 @@
  */
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
-	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+	blr
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	rlwinm	r3,r3,0,0,19			/* Get page base address */
 	li	r4,4096/L1_CACHE_BYTES	/* Number of lines in a page */
 	mtctr	r4
@@ -543,7 +543,7 @@
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	mfmsr	r10
 	rlwinm	r0,r10,0,28,26			/* clear DR */
 	mtmsr	r0
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 519861d..bbb3ba5 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -646,6 +646,19 @@
 	/* turn off mmu */
 	bl	real_mode
 
+	/* copy  0x100 bytes starting at start to 0 */
+	li	r3,0
+	mr	r4,r30		/* start, aka phys mem offset */
+	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)
+
 	/* clear out hardware hash page table and tlb */
 	ld	r5,0(r27)		/* deref function descriptor */
 	mtctr	r5
@@ -676,19 +689,6 @@
  *    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
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index d454f61..9536ed7 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -427,14 +427,6 @@
 	/* Process "ranges" property */
 	pci_process_bridge_OF_ranges(phb, dev->node, 0);
 
-	/* Setup IO space. We use the non-dynamic version of that code here,
-	 * which doesn't quite support unplugging. Next kernel release will
-	 * have a better fix for this.
-	 * Note also that we don't do ISA, this will also be fixed with a
-	 * more massive rework.
-	 */
-	pci_setup_phb_io(phb, pci_io_base == 0);
-
 	/* Init pci_dn data structures */
 	pci_devs_phb_init_dynamic(phb);
 
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
new file mode 100644
index 0000000..faf5ef3
--- /dev/null
+++ b/arch/powerpc/kernel/pci-common.c
@@ -0,0 +1,454 @@
+/*
+ * Contains common pci routines for ALL ppc platform
+ * (based on pci_32.c and pci_64.c)
+ *
+ * Port for PPC64 David Engebretsen, IBM Corp.
+ * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
+ *
+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
+ *   Rework, based on alpha PCI code.
+ *
+ * Common pmac/prep/chrp pci routines. -- Cort
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/syscalls.h>
+#include <linux/irq.h>
+#include <linux/vmalloc.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static DEFINE_SPINLOCK(hose_spinlock);
+
+/* XXX kill that some day ... */
+int global_phb_number;		/* Global phb counter */
+
+extern struct list_head hose_list;
+
+/*
+ * pci_controller(phb) initialized common variables.
+ */
+static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
+{
+	memset(hose, 0, sizeof(struct pci_controller));
+
+	spin_lock(&hose_spinlock);
+	hose->global_number = global_phb_number++;
+	list_add_tail(&hose->list_node, &hose_list);
+	spin_unlock(&hose_spinlock);
+}
+
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+{
+	struct pci_controller *phb;
+
+	if (mem_init_done)
+		phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+	else
+		phb = alloc_bootmem(sizeof (struct pci_controller));
+	if (phb == NULL)
+		return NULL;
+	pci_setup_pci_controller(phb);
+	phb->arch_data = dev;
+	phb->is_dynamic = mem_init_done;
+#ifdef CONFIG_PPC64
+	if (dev) {
+		int nid = of_node_to_nid(dev);
+
+		if (nid < 0 || !node_online(nid))
+			nid = -1;
+
+		PHB_SET_NODE(phb, nid);
+	}
+#endif
+	return phb;
+}
+
+void pcibios_free_controller(struct pci_controller *phb)
+{
+	spin_lock(&hose_spinlock);
+	list_del(&phb->list_node);
+	spin_unlock(&hose_spinlock);
+
+	if (phb->is_dynamic)
+		kfree(phb);
+}
+
+/*
+ * Return the domain number for this bus.
+ */
+int pci_domain_nr(struct pci_bus *bus)
+{
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+	else {
+		struct pci_controller *hose = pci_bus_to_host(bus);
+
+		return hose->global_number;
+	}
+}
+
+EXPORT_SYMBOL(pci_domain_nr);
+
+#ifdef CONFIG_PPC_OF
+
+/* 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_buses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
+{
+	if (!have_of)
+		return NULL;
+	while(node) {
+		struct pci_controller *hose, *tmp;
+		list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+			if (hose->arch_data == node)
+				return hose;
+		node = node->parent;
+	}
+	return NULL;
+}
+
+static ssize_t pci_show_devspec(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pci_dev *pdev;
+	struct device_node *np;
+
+	pdev = to_pci_dev (dev);
+	np = pci_device_to_OF_node(pdev);
+	if (np == NULL || np->full_name == NULL)
+		return 0;
+	return sprintf(buf, "%s", np->full_name);
+}
+static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
+#endif /* CONFIG_PPC_OF */
+
+/* Add sysfs properties */
+void pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PPC_OF
+	device_create_file(&pdev->dev, &dev_attr_devspec);
+#endif /* CONFIG_PPC_OF */
+}
+
+char __init *pcibios_setup(char *str)
+{
+	return str;
+}
+
+/*
+ * Reads the interrupt pin to determine if interrupt is use by card.
+ * If the interrupt is used, then gets the interrupt line from the
+ * openfirmware and sets it in the pci_dev and pci_config line.
+ */
+int pci_read_irq_line(struct pci_dev *pci_dev)
+{
+	struct of_irq oirq;
+	unsigned int virq;
+
+	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
+
+#ifdef DEBUG
+	memset(&oirq, 0xff, sizeof(oirq));
+#endif
+	/* Try to get a mapping from the device-tree */
+	if (of_irq_map_pci(pci_dev, &oirq)) {
+		u8 line, pin;
+
+		/* If that fails, lets fallback to what is in the config
+		 * space and map that through the default controller. We
+		 * also set the type to level low since that's what PCI
+		 * interrupts are. If your platform does differently, then
+		 * either provide a proper interrupt tree or don't use this
+		 * function.
+		 */
+		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+			return -1;
+		if (pin == 0)
+			return -1;
+		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+		    line == 0xff) {
+			return -1;
+		}
+		DBG(" -> no map ! Using irq line %d from PCI config\n", line);
+
+		virq = irq_create_mapping(NULL, line);
+		if (virq != NO_IRQ)
+			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+	} else {
+		DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+		    oirq.size, oirq.specifier[0], oirq.specifier[1],
+		    oirq.controller->full_name);
+
+		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+					     oirq.size);
+	}
+	if(virq == NO_IRQ) {
+		DBG(" -> failed to map !\n");
+		return -1;
+	}
+
+	DBG(" -> mapped to linux irq %d\n", virq);
+
+	pci_dev->irq = virq;
+
+	return 0;
+}
+EXPORT_SYMBOL(pci_read_irq_line);
+
+/*
+ * Platform support for /proc/bus/pci/X/Y mmap()s,
+ * modelled on the sparc64 implementation by Dave Miller.
+ *  -- paulus.
+ */
+
+/*
+ * Adjust vm_pgoff of VMA such that it is the physical page offset
+ * corresponding to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
+					       resource_size_t *offset,
+					       enum pci_mmap_state mmap_state)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	unsigned long io_offset = 0;
+	int i, res_bit;
+
+	if (hose == 0)
+		return NULL;		/* should never happen */
+
+	/* If memory, add on the PCI bridge address offset */
+	if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
+		*offset += hose->pci_mem_offset;
+#endif
+		res_bit = IORESOURCE_MEM;
+	} else {
+		io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		*offset += io_offset;
+		res_bit = IORESOURCE_IO;
+	}
+
+	/*
+	 * Check that the offset requested corresponds to one of the
+	 * resources of the device.
+	 */
+	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+		struct resource *rp = &dev->resource[i];
+		int flags = rp->flags;
+
+		/* treat ROM as memory (should be already) */
+		if (i == PCI_ROM_RESOURCE)
+			flags |= IORESOURCE_MEM;
+
+		/* Active and same type? */
+		if ((flags & res_bit) == 0)
+			continue;
+
+		/* In the range of this resource? */
+		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
+			continue;
+
+		/* found it! construct the final physical address */
+		if (mmap_state == pci_mmap_io)
+			*offset += hose->io_base_phys - io_offset;
+		return rp;
+	}
+
+	return NULL;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
+				      pgprot_t protection,
+				      enum pci_mmap_state mmap_state,
+				      int write_combine)
+{
+	unsigned long prot = pgprot_val(protection);
+
+	/* Write combine is always 0 on non-memory space mappings. On
+	 * memory space, if the user didn't pass 1, we check for a
+	 * "prefetchable" resource. This is a bit hackish, but we use
+	 * this to workaround the inability of /sysfs to provide a write
+	 * combine bit
+	 */
+	if (mmap_state != pci_mmap_mem)
+		write_combine = 0;
+	else if (write_combine == 0) {
+		if (rp->flags & IORESOURCE_PREFETCH)
+			write_combine = 1;
+	}
+
+	/* XXX would be nice to have a way to ask for write-through */
+	prot |= _PAGE_NO_CACHE;
+	if (write_combine)
+		prot &= ~_PAGE_GUARDED;
+	else
+		prot |= _PAGE_GUARDED;
+
+	return __pgprot(prot);
+}
+
+/*
+ * This one is used by /dev/mem and fbdev who have no clue about the
+ * PCI device, it tries to find the PCI device first and calls the
+ * above routine
+ */
+pgprot_t pci_phys_mem_access_prot(struct file *file,
+				  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(pfn))
+		return __pgprot(prot);
+
+	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+
+	for_each_pci_dev(pdev) {
+		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+			struct resource *rp = &pdev->resource[i];
+			int flags = rp->flags;
+
+			/* Active and same type? */
+			if ((flags & IORESOURCE_MEM) == 0)
+				continue;
+			/* In the range of this resource? */
+			if (offset < (rp->start & PAGE_MASK) ||
+			    offset > rp->end)
+				continue;
+			found = rp;
+			break;
+		}
+		if (found)
+			break;
+	}
+	if (found) {
+		if (found->flags & IORESOURCE_PREFETCH)
+			prot &= ~_PAGE_GUARDED;
+		pci_dev_put(pdev);
+	}
+
+	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
+
+	return __pgprot(prot);
+}
+
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture.  The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine)
+{
+	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
+	struct resource *rp;
+	int ret;
+
+	rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+	if (rp == NULL)
+		return -EINVAL;
+
+	vma->vm_pgoff = offset >> PAGE_SHIFT;
+	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
+						  vma->vm_page_prot,
+						  mmap_state, write_combine);
+
+	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+	return ret;
+}
+
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+			  const struct resource *rsrc,
+			  resource_size_t *start, resource_size_t *end)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	resource_size_t offset = 0;
+
+	if (hose == NULL)
+		return;
+
+	if (rsrc->flags & IORESOURCE_IO)
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+	/* We pass a fully fixed up address to userland for MMIO instead of
+	 * a BAR value because X is lame and expects to be able to use that
+	 * to pass to /dev/mem !
+	 *
+	 * That means that we'll have potentially 64 bits values where some
+	 * userland apps only expect 32 (like X itself since it thinks only
+	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+	 * 32 bits CHRPs :-(
+	 *
+	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
+	 * has been fixed (and the fix spread enough), we can re-enable the
+	 * 2 lines below and pass down a BAR value to userland. In that case
+	 * we'll also have to re-enable the matching code in
+	 * __pci_mmap_make_offset().
+	 *
+	 * BenH.
+	 */
+#if 0
+	else if (rsrc->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+#endif
+
+	*start = rsrc->start - offset;
+	*end = rsrc->end - offset;
+}
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 8698211..0adf077 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -55,8 +55,7 @@
  */
 int pci_assign_all_buses;
 
-struct pci_controller* hose_head;
-struct pci_controller** hose_tail = &hose_head;
+LIST_HEAD(hose_list);
 
 static int pci_bus_count;
 
@@ -573,58 +572,6 @@
 	}
 }
 
-
-int
-pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx=0; idx<6; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<idx)))
-			continue;
-	
-		r = &dev->resource[idx];
-		if (r->flags & IORESOURCE_UNSET) {
-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (dev->resource[PCI_ROM_RESOURCE].start)
-		cmd |= PCI_COMMAND_MEMORY;
-	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
-static int next_controller_index;
-
-struct pci_controller * __init
-pcibios_alloc_controller(void)
-{
-	struct pci_controller *hose;
-
-	hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
-	memset(hose, 0, sizeof(struct pci_controller));
-
-	*hose_tail = hose;
-	hose_tail = &hose->next;
-
-	hose->index = next_controller_index++;
-
-	return hose;
-}
-
 #ifdef CONFIG_PPC_OF
 /*
  * Functions below are used on OpenFirmware machines.
@@ -670,7 +617,7 @@
 pcibios_make_OF_bus_map(void)
 {
 	int i;
-	struct pci_controller* hose;
+	struct pci_controller *hose, *tmp;
 	struct property *map_prop;
 	struct device_node *dn;
 
@@ -687,7 +634,7 @@
 		pci_to_OF_bus_map[i] = 0xff;
 
 	/* For each hose, we begin searching bridges */
-	for(hose=hose_head; hose; hose=hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		struct device_node* node;	
 		node = (struct device_node *)hose->arch_data;
 		if (!node)
@@ -765,7 +712,7 @@
 
 	/* Are we a root bus ? */
 	if (bus->self == NULL || bus->parent == NULL) {
-		struct pci_controller *hose = pci_bus_to_hose(bus->number);
+		struct pci_controller *hose = pci_bus_to_host(bus);
 		if (hose == NULL)
 			return NULL;
 		return of_node_get(hose->arch_data);
@@ -818,27 +765,6 @@
 }
 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_buses to 1 and still use RTAS for PCI
- * config cycles.
- */
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
-	if (!have_of)
-		return NULL;
-	while(node) {
-		struct pci_controller* hose;
-		for (hose=hose_head;hose;hose=hose->next)
-			if (hose->arch_data == node)
-				return hose;
-		node=node->parent;
-	}
-	return NULL;
-}
-
 static int
 find_OF_pci_device_filter(struct device_node* node, void* data)
 {
@@ -1027,34 +953,12 @@
 	}
 }
 
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pci_dev *pdev;
-	struct device_node *np;
-
-	pdev = to_pci_dev (dev);
-	np = pci_device_to_OF_node(pdev);
-	if (np == NULL || np->full_name == NULL)
-		return 0;
-	return sprintf(buf, "%s", np->full_name);
-}
-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 */
-int pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-#ifdef CONFIG_PPC_OF
-	return device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_OF */
-}
-
-
 #ifdef CONFIG_PPC_PMAC
 /*
  * This set of routines checks for PCI<->PCI bridges that have closed
@@ -1269,14 +1173,14 @@
 static int __init
 pcibios_init(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 	struct pci_bus *bus;
-	int next_busno;
+	int next_busno = 0;
 
 	printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
-	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		if (pci_assign_all_buses)
 			hose->first_busno = next_busno;
 		hose->last_busno = 0xff;
@@ -1319,12 +1223,6 @@
 
 subsys_initcall(pcibios_init);
 
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
-			     unsigned long start, unsigned long size)
-{
-	return start;
-}
-
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@@ -1342,7 +1240,7 @@
 		if (!res->flags) {
 			if (io_offset)
 				printk(KERN_ERR "I/O resource not set for host"
-				       " bridge %d\n", hose->index);
+				       " bridge %d\n", hose->global_number);
 			res->start = 0;
 			res->end = IO_SPACE_LIMIT;
 			res->flags = IORESOURCE_IO;
@@ -1356,7 +1254,7 @@
 				if (i > 0)
 					continue;
 				printk(KERN_ERR "Memory resource not set for "
-				       "host bridge %d\n", hose->index);
+				       "host bridge %d\n", hose->global_number);
 				res->start = hose->pci_mem_offset;
 				res->end = ~0U;
 				res->flags = IORESOURCE_MEM;
@@ -1370,7 +1268,7 @@
 		for (i = 0; i < 4; ++i) {
 			if ((res = bus->resource[i]) == NULL)
 				continue;
-			if (!res->flags)
+			if (!res->flags || bus->self->transparent)
 				continue;
 			if (io_offset && (res->flags & IORESOURCE_IO)) {
 				res->start += io_offset;
@@ -1395,11 +1293,6 @@
 	}
 }
 
-char __init *pcibios_setup(char *str)
-{
-	return str;
-}
-
 /* the next one is stolen from the alpha port... */
 void __init
 pcibios_update_irq(struct pci_dev *dev, int irq)
@@ -1408,64 +1301,6 @@
 	/* XXX FIXME - update OF device tree node interrupt property */
 }
 
-#ifdef CONFIG_PPC_MERGE
-/* XXX This is a copy of the ppc64 version. This is temporary until we start
- * merging the 2 PCI layers
- */
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-	struct of_irq oirq;
-	unsigned int virq;
-
-	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
-	/* Try to get a mapping from the device-tree */
-	if (of_irq_map_pci(pci_dev, &oirq)) {
-		u8 line, pin;
-
-		/* If that fails, lets fallback to what is in the config
-		 * space and map that through the default controller. We
-		 * also set the type to level low since that's what PCI
-		 * interrupts are. If your platform does differently, then
-		 * either provide a proper interrupt tree or don't use this
-		 * function.
-		 */
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-			return -1;
-		if (pin == 0)
-			return -1;
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-		    line == 0xff) {
-			return -1;
-		}
-		DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
-		virq = irq_create_mapping(NULL, line);
-		if (virq != NO_IRQ)
-			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-	} else {
-		DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-		    oirq.size, oirq.specifier[0], oirq.controller->full_name);
-
-		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-					     oirq.size);
-	}
-	if(virq == NO_IRQ) {
-		DBG(" -> failed to map !\n");
-		return -1;
-	}
-	pci_dev->irq = virq;
-
-	return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-#endif /* CONFIG_PPC_MERGE */
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	u16 cmd, old_cmd;
@@ -1497,281 +1332,17 @@
 	return 0;
 }
 
-struct pci_controller*
+static struct pci_controller*
 pci_bus_to_hose(int bus)
 {
-	struct pci_controller* hose = hose_head;
+	struct pci_controller *hose, *tmp;
 
-	for (; hose; hose = hose->next)
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
 		if (bus >= hose->first_busno && bus <= hose->last_busno)
 			return hose;
 	return NULL;
 }
 
-void __iomem *
-pci_bus_io_base(unsigned int bus)
-{
-	struct pci_controller *hose;
-
-	hose = pci_bus_to_hose(bus);
-	if (!hose)
-		return NULL;
-	return hose->io_base_virt;
-}
-
-unsigned long
-pci_bus_io_base_phys(unsigned int bus)
-{
-	struct pci_controller *hose;
-
-	hose = pci_bus_to_hose(bus);
-	if (!hose)
-		return 0;
-	return hose->io_base_phys;
-}
-
-unsigned long
-pci_bus_mem_base_phys(unsigned int bus)
-{
-	struct pci_controller *hose;
-
-	hose = pci_bus_to_hose(bus);
-	if (!hose)
-		return 0;
-	return hose->pci_mem_offset;
-}
-
-unsigned long
-pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
-{
-	/* Hack alert again ! See comments in chrp_pci.c
-	 */
-	struct pci_controller* hose =
-		(struct pci_controller *)pdev->sysdata;
-	if (hose && res->flags & IORESOURCE_MEM)
-		return res->start - hose->pci_mem_offset;
-	/* We may want to do something with IOs here... */
-	return res->start;
-}
-
-
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-					       resource_size_t *offset,
-					       enum pci_mmap_state mmap_state)
-{
-	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-	unsigned long io_offset = 0;
-	int i, res_bit;
-
-	if (hose == 0)
-		return NULL;		/* should never happen */
-
-	/* If memory, add on the PCI bridge address offset */
-	if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
-		*offset += hose->pci_mem_offset;
-#endif
-		res_bit = IORESOURCE_MEM;
-	} else {
-		io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
-		*offset += io_offset;
-		res_bit = IORESOURCE_IO;
-	}
-
-	/*
-	 * Check that the offset requested corresponds to one of the
-	 * resources of the device.
-	 */
-	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-		struct resource *rp = &dev->resource[i];
-		int flags = rp->flags;
-
-		/* treat ROM as memory (should be already) */
-		if (i == PCI_ROM_RESOURCE)
-			flags |= IORESOURCE_MEM;
-
-		/* Active and same type? */
-		if ((flags & res_bit) == 0)
-			continue;
-
-		/* In the range of this resource? */
-		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
-			continue;
-
-		/* found it! construct the final physical address */
-		if (mmap_state == pci_mmap_io)
-			*offset += hose->io_base_phys - io_offset;
-		return rp;
-	}
-
-	return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
-				      pgprot_t protection,
-				      enum pci_mmap_state mmap_state,
-				      int write_combine)
-{
-	unsigned long prot = pgprot_val(protection);
-
-	/* Write combine is always 0 on non-memory space mappings. On
-	 * memory space, if the user didn't pass 1, we check for a
-	 * "prefetchable" resource. This is a bit hackish, but we use
-	 * this to workaround the inability of /sysfs to provide a write
-	 * combine bit
-	 */
-	if (mmap_state != pci_mmap_mem)
-		write_combine = 0;
-	else if (write_combine == 0) {
-		if (rp->flags & IORESOURCE_PREFETCH)
-			write_combine = 1;
-	}
-
-	/* XXX would be nice to have a way to ask for write-through */
-	prot |= _PAGE_NO_CACHE;
-	if (write_combine)
-		prot &= ~_PAGE_GUARDED;
-	else
-		prot |= _PAGE_GUARDED;
-
-	return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
-				  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(pfn))
-		return __pgprot(prot);
-
-	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
-	for_each_pci_dev(pdev) {
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-			struct resource *rp = &pdev->resource[i];
-			int flags = rp->flags;
-
-			/* Active and same type? */
-			if ((flags & IORESOURCE_MEM) == 0)
-				continue;
-			/* In the range of this resource? */
-			if (offset < (rp->start & PAGE_MASK) ||
-			    offset > rp->end)
-				continue;
-			found = rp;
-			break;
-		}
-		if (found)
-			break;
-	}
-	if (found) {
-		if (found->flags & IORESOURCE_PREFETCH)
-			prot &= ~_PAGE_GUARDED;
-		pci_dev_put(pdev);
-	}
-
-	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
-	return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture.  The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-			enum pci_mmap_state mmap_state,
-			int write_combine)
-{
-	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
-	struct resource *rp;
-	int ret;
-
-	rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
-	if (rp == NULL)
-		return -EINVAL;
-
-	vma->vm_pgoff = offset >> PAGE_SHIFT;
-	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
-						  vma->vm_page_prot,
-						  mmap_state, write_combine);
-
-	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
-	return ret;
-}
-
-/* Obsolete functions. Should be removed once the symbios driver
- * is fixed
- */
-unsigned long
-phys_to_bus(unsigned long pa)
-{
-	struct pci_controller *hose;
-	int i;
-
-	for (hose = hose_head; hose; hose = hose->next) {
-		for (i = 0; i < 3; ++i) {
-			if (pa >= hose->mem_resources[i].start
-			    && pa <= hose->mem_resources[i].end) {
-				/*
-				 * XXX the hose->pci_mem_offset really
-				 * only applies to mem_resources[0].
-				 * We need a way to store an offset for
-				 * the others.  -- paulus
-				 */
-				if (i == 0)
-					pa -= hose->pci_mem_offset;
-				return pa;
-			}
-		}
-	}
-	/* hmmm, didn't find it */
-	return 0;
-}
-
-unsigned long
-pci_phys_to_bus(unsigned long pa, int busnr)
-{
-	struct pci_controller* hose = pci_bus_to_hose(busnr);
-	if (!hose)
-		return pa;
-	return pa - hose->pci_mem_offset;
-}
-
-unsigned long
-pci_bus_to_phys(unsigned int ba, int busnr)
-{
-	struct pci_controller* hose = pci_bus_to_hose(busnr);
-	if (!hose)
-		return ba;
-	return ba + hose->pci_mem_offset;
-}
-
 /* Provide information on locations of various I/O regions in physical
  * memory.  Do this on a per-card basis so that we choose the right
  * root bridge.
@@ -1814,62 +1385,11 @@
 	return result;
 }
 
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
-			  const struct resource *rsrc,
-			  resource_size_t *start, resource_size_t *end)
-{
-	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-	resource_size_t offset = 0;
-
-	if (hose == NULL)
-		return;
-
-	if (rsrc->flags & IORESOURCE_IO)
-		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-	/* We pass a fully fixed up address to userland for MMIO instead of
-	 * a BAR value because X is lame and expects to be able to use that
-	 * to pass to /dev/mem !
-	 *
-	 * That means that we'll have potentially 64 bits values where some
-	 * userland apps only expect 32 (like X itself since it thinks only
-	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
-	 * 32 bits CHRPs :-(
-	 *
-	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
-	 * has been fixed (and the fix spread enough), we can re-enable the
-	 * 2 lines below and pass down a BAR value to userland. In that case
-	 * we'll also have to re-enable the matching code in
-	 * __pci_mmap_make_offset().
-	 *
-	 * BenH.
-	 */
-#if 0
-	else if (rsrc->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-#endif
-
-	*start = rsrc->start - offset;
-	*end = rsrc->end - offset;
-}
-
-void __init pci_init_resource(struct resource *res, resource_size_t start,
-			      resource_size_t end, int flags, char *name)
-{
-	res->start = start;
-	res->end = end;
-	res->flags = flags;
-	res->name = name;
-	res->parent = NULL;
-	res->sibling = NULL;
-	res->child = NULL;
-}
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
-	struct pci_controller* hose = hose_head;
+	struct pci_controller *hose, *tmp;
 
-	for (; hose; hose = hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		unsigned int size = hose->io_resource.end -
 			hose->io_resource.start + 1;
 		if (address >= hose->io_base_phys &&
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index e3009a4..a97e23a 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/syscalls.h>
 #include <linux/irq.h>
+#include <linux/vmalloc.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -41,35 +42,23 @@
 
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
-static int pci_initial_scan_done;
 
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
-static void phbs_remap_io(void);
 
 /* pci_io_base -- the base address from which io bars are offsets.
  * This is the lowest I/O base address (so bar values are always positive),
  * and it *must* be the start of ISA space if an ISA bus exists because
- * ISA drivers use hard coded offsets.  If no ISA bus exists a dummy
- * page is mapped and isa_io_limit prevents access to it.
+ * ISA drivers use hard coded offsets.  If no ISA bus exists nothing
+ * is mapped on the first 64K of IO space
  */
-unsigned long isa_io_base;	/* NULL if no ISA bus */
-EXPORT_SYMBOL(isa_io_base);
-unsigned long pci_io_base;
+unsigned long pci_io_base = ISA_IO_BASE;
 EXPORT_SYMBOL(pci_io_base);
 
-void iSeries_pcibios_init(void);
-
 LIST_HEAD(hose_list);
 
 static struct dma_mapping_ops *pci_dma_ops;
 
-int global_phb_number;		/* Global phb counter */
-
-/* Cached ISA bridge dev. */
-struct pci_dev *ppc64_isabridge_dev = NULL;
-EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
-
 void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
 {
 	pci_dma_ops = dma_ops;
@@ -100,7 +89,7 @@
 		return;
 
 	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - pci_io_base;
+	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
 	if (res->flags & IORESOURCE_MEM)
 		offset = hose->pci_mem_offset;
@@ -119,7 +108,7 @@
 		return;
 
 	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - pci_io_base;
+	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
 	if (res->flags & IORESOURCE_MEM)
 		offset = hose->pci_mem_offset;
@@ -156,7 +145,7 @@
 
 	if (res->flags & IORESOURCE_IO) {
 	        unsigned long offset = (unsigned long)hose->io_base_virt -
-					pci_io_base;
+					_IO_BASE;
 		/* Make sure we start at our min on all hoses */
 		if (start - offset < PCIBIOS_MIN_IO)
 			start = PCIBIOS_MIN_IO + offset;
@@ -180,55 +169,6 @@
 	res->start = start;
 }
 
-static DEFINE_SPINLOCK(hose_spinlock);
-
-/*
- * pci_controller(phb) initialized common variables.
- */
-static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
-{
-	memset(hose, 0, sizeof(struct pci_controller));
-
-	spin_lock(&hose_spinlock);
-	hose->global_number = global_phb_number++;
-	list_add_tail(&hose->list_node, &hose_list);
-	spin_unlock(&hose_spinlock);
-}
-
-struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
-{
-	struct pci_controller *phb;
-
-	if (mem_init_done)
-		phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
-	else
-		phb = alloc_bootmem(sizeof (struct pci_controller));
-	if (phb == NULL)
-		return NULL;
-	pci_setup_pci_controller(phb);
-	phb->arch_data = dev;
-	phb->is_dynamic = mem_init_done;
-	if (dev) {
-		int nid = of_node_to_nid(dev);
-
-		if (nid < 0 || !node_online(nid))
-			nid = -1;
-
-		PHB_SET_NODE(phb, nid);
-	}
-	return phb;
-}
-
-void pcibios_free_controller(struct pci_controller *phb)
-{
-	spin_lock(&hose_spinlock);
-	list_del(&phb->list_node);
-	spin_unlock(&hose_spinlock);
-
-	if (phb->is_dynamic)
-		kfree(phb);
-}
-
 void __devinit pcibios_claim_one_bus(struct pci_bus *b)
 {
 	struct pci_dev *dev;
@@ -291,7 +231,6 @@
 	return flags;
 }
 
-#define GET_64BIT(prop, i)	((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
 
 static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
 {
@@ -310,8 +249,8 @@
 		flags = pci_parse_of_flags(addrs[0]);
 		if (!flags)
 			continue;
-		base = GET_64BIT(addrs, 1);
-		size = GET_64BIT(addrs, 3);
+		base = of_read_number(&addrs[1], 2);
+		size = of_read_number(&addrs[3], 2);
 		if (!size)
 			continue;
 		i = addrs[0] & 0xff;
@@ -479,7 +418,7 @@
 	i = 1;
 	for (; len >= 32; len -= 32, ranges += 8) {
 		flags = pci_parse_of_flags(ranges[0]);
-		size = GET_64BIT(ranges, 6);
+		size = of_read_number(&ranges[6], 2);
 		if (flags == 0 || size == 0)
 			continue;
 		if (flags & IORESOURCE_IO) {
@@ -498,7 +437,7 @@
 			res = bus->resource[i];
 			++i;
 		}
-		res->start = GET_64BIT(ranges, 1);
+		res->start = of_read_number(&ranges[1], 2);
 		res->end = res->start + size - 1;
 		res->flags = flags;
 		fixup_resource(res, dev);
@@ -537,10 +476,16 @@
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		pcibios_map_io_space(bus);
+
 	bus->resource[0] = res = &hose->io_resource;
-	if (res->flags && request_resource(&ioport_resource, res))
+	if (res->flags && request_resource(&ioport_resource, res)) {
 		printk(KERN_ERR "Failed to request PCI IO region "
 		       "on PCI domain %04x\n", hose->global_number);
+		DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
+		    res->start, res->end);
+	}
 
 	for (i = 0; i < 3; ++i) {
 		res = &hose->mem_resources[i];
@@ -598,17 +543,6 @@
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
 
-	/* Cache the location of the ISA bridge (if we have one) */
-	ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-	if (ppc64_isabridge_dev != NULL)
-		printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
-
-	if (!firmware_has_feature(FW_FEATURE_ISERIES))
-		/* map in PCI I/O space */
-		phbs_remap_io();
-
-	pci_initial_scan_done = 1;
-
 	printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
 	return 0;
@@ -616,11 +550,6 @@
 
 subsys_initcall(pcibios_init);
 
-char __init *pcibios_setup(char *str)
-{
-	return str;
-}
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	u16 cmd, oldcmd;
@@ -651,22 +580,6 @@
 	return 0;
 }
 
-/*
- * Return the domain number for this bus.
- */
-int pci_domain_nr(struct pci_bus *bus)
-{
-	if (firmware_has_feature(FW_FEATURE_ISERIES))
-		return 0;
-	else {
-		struct pci_controller *hose = pci_bus_to_host(bus);
-
-		return hose->global_number;
-	}
-}
-
-EXPORT_SYMBOL(pci_domain_nr);
-
 /* Decide whether to display the domain number in /proc */
 int pci_proc_domain(struct pci_bus *bus)
 {
@@ -678,281 +591,6 @@
 	}
 }
 
-/*
- * Platform support for /proc/bus/pci/X/Y mmap()s,
- * modelled on the sparc64 implementation by Dave Miller.
- *  -- paulus.
- */
-
-/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap.  They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-					       resource_size_t *offset,
-					       enum pci_mmap_state mmap_state)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long io_offset = 0;
-	int i, res_bit;
-
-	if (hose == 0)
-		return NULL;		/* should never happen */
-
-	/* If memory, add on the PCI bridge address offset */
-	if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
-		*offset += hose->pci_mem_offset;
-#endif
-		res_bit = IORESOURCE_MEM;
-	} else {
-		io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-		*offset += io_offset;
-		res_bit = IORESOURCE_IO;
-	}
-
-	/*
-	 * Check that the offset requested corresponds to one of the
-	 * resources of the device.
-	 */
-	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-		struct resource *rp = &dev->resource[i];
-		int flags = rp->flags;
-
-		/* treat ROM as memory (should be already) */
-		if (i == PCI_ROM_RESOURCE)
-			flags |= IORESOURCE_MEM;
-
-		/* Active and same type? */
-		if ((flags & res_bit) == 0)
-			continue;
-
-		/* In the range of this resource? */
-		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
-			continue;
-
-		/* found it! construct the final physical address */
-		if (mmap_state == pci_mmap_io)
-		       	*offset += hose->io_base_phys - io_offset;
-		return rp;
-	}
-
-	return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
-				      pgprot_t protection,
-				      enum pci_mmap_state mmap_state,
-				      int write_combine)
-{
-	unsigned long prot = pgprot_val(protection);
-
-	/* Write combine is always 0 on non-memory space mappings. On
-	 * memory space, if the user didn't pass 1, we check for a
-	 * "prefetchable" resource. This is a bit hackish, but we use
-	 * this to workaround the inability of /sysfs to provide a write
-	 * combine bit
-	 */
-	if (mmap_state != pci_mmap_mem)
-		write_combine = 0;
-	else if (write_combine == 0) {
-		if (rp->flags & IORESOURCE_PREFETCH)
-			write_combine = 1;
-	}
-
-	/* XXX would be nice to have a way to ask for write-through */
-	prot |= _PAGE_NO_CACHE;
-	if (write_combine)
-		prot &= ~_PAGE_GUARDED;
-	else
-		prot |= _PAGE_GUARDED;
-
-	return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
-				  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(pfn))
-		return __pgprot(prot);
-
-	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
-	for_each_pci_dev(pdev) {
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-			struct resource *rp = &pdev->resource[i];
-			int flags = rp->flags;
-
-			/* Active and same type? */
-			if ((flags & IORESOURCE_MEM) == 0)
-				continue;
-			/* In the range of this resource? */
-			if (offset < (rp->start & PAGE_MASK) ||
-			    offset > rp->end)
-				continue;
-			found = rp;
-			break;
-		}
-		if (found)
-			break;
-	}
-	if (found) {
-		if (found->flags & IORESOURCE_PREFETCH)
-			prot &= ~_PAGE_GUARDED;
-		pci_dev_put(pdev);
-	}
-
-	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
-	return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture.  The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-			enum pci_mmap_state mmap_state, int write_combine)
-{
-	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
-	struct resource *rp;
-	int ret;
-
-	rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
-	if (rp == NULL)
-		return -EINVAL;
-
-	vma->vm_pgoff = offset >> PAGE_SHIFT;
-	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
-						  vma->vm_page_prot,
-						  mmap_state, write_combine);
-
-	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
-	return ret;
-}
-
-static ssize_t pci_show_devspec(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct pci_dev *pdev;
-	struct device_node *np;
-
-	pdev = to_pci_dev (dev);
-	np = pci_device_to_OF_node(pdev);
-	if (np == NULL || np->full_name == NULL)
-		return 0;
-	return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
-int pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-	return device_create_file(&pdev->dev, &dev_attr_devspec);
-}
-
-#define ISA_SPACE_MASK 0x1
-#define ISA_SPACE_IO 0x1
-
-static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
-				      unsigned long phb_io_base_phys,
-				      void __iomem * phb_io_base_virt)
-{
-	/* Remove these asap */
-
-	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;
-	};
-
-	const struct isa_range *range;
-	unsigned long pci_addr;
-	unsigned int isa_addr;
-	unsigned int size;
-	int rlen = 0;
-
-	range = of_get_property(isa_node, "ranges", &rlen);
-	if (range == NULL || (rlen < sizeof(struct isa_range))) {
-		printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
-		       "mapping 64k\n");
-		__ioremap_explicit(phb_io_base_phys,
-				   (unsigned long)phb_io_base_virt,
-				   0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED);
-		return;	
-	}
-	
-	/* From "ISA Binding to 1275"
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 1:	an ISA address
-	 *   cells 2 - 4:	a PCI address 
-	 *			(size depending on dev->n_addr_cells)
-	 *   cell 5:		the size of the range
-	 */
-	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
-		isa_addr = range->isa_addr.a_lo;
-		pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
-			range->pci_addr.a_lo;
-
-		/* Assume these are both zero */
-		if ((pci_addr != 0) || (isa_addr != 0)) {
-			printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
-					__FUNCTION__);
-			return;
-		}
-		
-		size = PAGE_ALIGN(range->size);
-
-		__ioremap_explicit(phb_io_base_phys, 
-				   (unsigned long) phb_io_base_virt, 
-				   size, _PAGE_NO_CACHE | _PAGE_GUARDED);
-	}
-}
-
 void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
 					    struct device_node *dev, int prim)
 {
@@ -1047,155 +685,122 @@
 	}
 }
 
-void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
+#ifdef CONFIG_HOTPLUG
+
+int pcibios_unmap_io_space(struct pci_bus *bus)
 {
-	unsigned long size = hose->pci_io_size;
-	unsigned long io_virt_offset;
-	struct resource *res;
-	struct device_node *isa_dn;
+	struct pci_controller *hose;
 
-	if (size == 0)
-		return;
+	WARN_ON(bus == NULL);
 
-	hose->io_base_virt = reserve_phb_iospace(size);
-	DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
-		hose->global_number, hose->io_base_phys,
-		(unsigned long) hose->io_base_virt);
-
-	if (primary) {
-		pci_io_base = (unsigned long)hose->io_base_virt;
-		isa_dn = of_find_node_by_type(NULL, "isa");
-		if (isa_dn) {
-			isa_io_base = pci_io_base;
-			pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
-						hose->io_base_virt);
-			of_node_put(isa_dn);
-		}
-	}
-
-	io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-	res = &hose->io_resource;
-	res->start += io_virt_offset;
-	res->end += io_virt_offset;
-
-	/* If this is called after the initial PCI scan, then we need to
-	 * proceed to IO mappings now
+	/* If this is not a PHB, we only flush the hash table over
+	 * the area mapped by this bridge. We don't play with the PTE
+	 * mappings since we might have to deal with sub-page alignemnts
+	 * so flushing the hash table is the only sane way to make sure
+	 * that no hash entries are covering that removed bridge area
+	 * while still allowing other busses overlapping those pages
 	 */
-	if (pci_initial_scan_done)
-		__ioremap_explicit(hose->io_base_phys,
-				   (unsigned long)hose->io_base_virt,
-				   hose->pci_io_size,
-				   _PAGE_NO_CACHE | _PAGE_GUARDED);
-}
+	if (bus->self) {
+		struct resource *res = bus->resource[0];
 
-void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
-					int primary)
+		DBG("IO unmapping for PCI-PCI bridge %s\n",
+		    pci_name(bus->self));
+
+		__flush_hash_table_range(&init_mm, res->start + _IO_BASE,
+					 res->end - res->start + 1);
+		return 0;
+	}
+
+	/* Get the host bridge */
+	hose = pci_bus_to_host(bus);
+
+	/* Check if we have IOs allocated */
+	if (hose->io_base_alloc == 0)
+		return 0;
+
+	DBG("IO unmapping for PHB %s\n",
+	    ((struct device_node *)hose->arch_data)->full_name);
+	DBG("  alloc=0x%p\n", hose->io_base_alloc);
+
+	/* This is a PHB, we fully unmap the IO area */
+	vunmap(hose->io_base_alloc);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
+
+#endif /* CONFIG_HOTPLUG */
+
+int __devinit pcibios_map_io_space(struct pci_bus *bus)
 {
-	unsigned long size = hose->pci_io_size;
+	struct vm_struct *area;
+	unsigned long phys_page;
+	unsigned long size_page;
 	unsigned long io_virt_offset;
-	struct resource *res;
+	struct pci_controller *hose;
 
-	if (size == 0)
-		return;
+	WARN_ON(bus == NULL);
 
-	hose->io_base_virt = __ioremap(hose->io_base_phys, size,
-					_PAGE_NO_CACHE | _PAGE_GUARDED);
-	DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
-		hose->global_number, hose->io_base_phys,
-		(unsigned long) hose->io_base_virt);
-
-	if (primary)
-		pci_io_base = (unsigned long)hose->io_base_virt;
-
-	io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-	res = &hose->io_resource;
-	res->start += io_virt_offset;
-	res->end += io_virt_offset;
-}
-
-
-static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
-				unsigned long *start_virt, unsigned long *size)
-{
-	struct pci_controller *hose = pci_bus_to_host(bus);
-	struct resource *res;
-
-	if (bus->self)
-		res = bus->resource[0];
-	else
-		/* Root Bus */
-		res = &hose->io_resource;
-
-	if (res->end == 0 && res->start == 0)
-		return 1;
-
-	*start_virt = pci_io_base + res->start;
-	*start_phys = *start_virt + hose->io_base_phys
-		- (unsigned long) hose->io_base_virt;
-
-	if (res->end > res->start)
-		*size = res->end - res->start + 1;
-	else {
-		printk("%s(): unexpected region 0x%lx->0x%lx\n",
-		       __FUNCTION__, res->start, res->end);
-		return 1;
+	/* If this not a PHB, nothing to do, page tables still exist and
+	 * thus HPTEs will be faulted in when needed
+	 */
+	if (bus->self) {
+		DBG("IO mapping for PCI-PCI bridge %s\n",
+		    pci_name(bus->self));
+		DBG("  virt=0x%016lx...0x%016lx\n",
+		    bus->resource[0]->start + _IO_BASE,
+		    bus->resource[0]->end + _IO_BASE);
+		return 0;
 	}
 
+	/* Get the host bridge */
+	hose = pci_bus_to_host(bus);
+	phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
+	size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
+
+	/* Make sure IO area address is clear */
+	hose->io_base_alloc = NULL;
+
+	/* If there's no IO to map on that bus, get away too */
+	if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
+		return 0;
+
+	/* Let's allocate some IO space for that guy. We don't pass
+	 * VM_IOREMAP because we don't care about alignment tricks that
+	 * the core does in that case. Maybe we should due to stupid card
+	 * with incomplete address decoding but I'd rather not deal with
+	 * those outside of the reserved 64K legacy region.
+	 */
+	area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
+	if (area == NULL)
+		return -ENOMEM;
+	hose->io_base_alloc = area->addr;
+	hose->io_base_virt = (void __iomem *)(area->addr +
+					      hose->io_base_phys - phys_page);
+
+	DBG("IO mapping for PHB %s\n",
+	    ((struct device_node *)hose->arch_data)->full_name);
+	DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
+	    hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
+	DBG("  size=0x%016lx (alloc=0x%016lx)\n",
+	    hose->pci_io_size, size_page);
+
+	/* Establish the mapping */
+	if (__ioremap_at(phys_page, area->addr, size_page,
+			 _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
+		return -ENOMEM;
+
+	/* Fixup hose IO resource */
+	io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+	hose->io_resource.start += io_virt_offset;
+	hose->io_resource.end += io_virt_offset;
+
+	DBG("  hose->io_resource=0x%016lx...0x%016lx\n",
+	    hose->io_resource.start, hose->io_resource.end);
+
 	return 0;
 }
-
-int unmap_bus_range(struct pci_bus *bus)
-{
-	unsigned long start_phys;
-	unsigned long start_virt;
-	unsigned long size;
-
-	if (!bus) {
-		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-		return 1;
-	}
-	
-	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-		return 1;
-	if (__iounmap_explicit((void __iomem *) start_virt, size))
-		return 1;
-
-	return 0;
-}
-EXPORT_SYMBOL(unmap_bus_range);
-
-int remap_bus_range(struct pci_bus *bus)
-{
-	unsigned long start_phys;
-	unsigned long start_virt;
-	unsigned long size;
-
-	if (!bus) {
-		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-		return 1;
-	}
-	
-	
-	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-		return 1;
-	if (start_phys == 0)
-		return 1;
-	printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
-	if (__ioremap_explicit(start_phys, start_virt, size,
-			       _PAGE_NO_CACHE | _PAGE_GUARDED))
-		return 1;
-
-	return 0;
-}
-EXPORT_SYMBOL(remap_bus_range);
-
-static void phbs_remap_io(void)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-		remap_bus_range(hose->bus);
-}
+EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
 static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 {
@@ -1203,8 +808,7 @@
 	unsigned long offset;
 
 	if (res->flags & IORESOURCE_IO) {
-		offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 		res->start += offset;
 		res->end += offset;
 	} else if (res->flags & IORESOURCE_MEM) {
@@ -1219,9 +823,20 @@
 	/* Update device resources.  */
 	int i;
 
-	for (i = 0; i < PCI_NUM_RESOURCES; i++)
-		if (dev->resource[i].flags)
-			fixup_resource(&dev->resource[i], dev);
+	DBG("%s: Fixup resources:\n", pci_name(dev));
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		struct resource *res = &dev->resource[i];
+		if (!res->flags)
+			continue;
+
+		DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
+		    i, res->flags, res->start, res->end);
+
+		fixup_resource(res, dev);
+
+		DBG("       > %08lx:0x%016lx...0x%016lx\n",
+		    res->flags, res->start, res->end);
+	}
 }
 EXPORT_SYMBOL(pcibios_fixup_device_resources);
 
@@ -1291,119 +906,6 @@
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the 
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-	struct of_irq oirq;
-	unsigned int virq;
-
-	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
-#ifdef DEBUG
-	memset(&oirq, 0xff, sizeof(oirq));
-#endif
-	/* Try to get a mapping from the device-tree */
-	if (of_irq_map_pci(pci_dev, &oirq)) {
-		u8 line, pin;
-
-		/* If that fails, lets fallback to what is in the config
-		 * space and map that through the default controller. We
-		 * also set the type to level low since that's what PCI
-		 * interrupts are. If your platform does differently, then
-		 * either provide a proper interrupt tree or don't use this
-		 * function.
-		 */
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-			return -1;
-		if (pin == 0)
-			return -1;
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-		    line == 0xff) {
-			return -1;
-		}
-		DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
-		virq = irq_create_mapping(NULL, line);
-		if (virq != NO_IRQ)
-			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-	} else {
-		DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
-		    oirq.size, oirq.specifier[0], oirq.specifier[1],
-		    oirq.controller->full_name);
-
-		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-					     oirq.size);
-	}
-	if(virq == NO_IRQ) {
-		DBG(" -> failed to map !\n");
-		return -1;
-	}
-
-	DBG(" -> mapped to linux irq %d\n", virq);
-
-	pci_dev->irq = virq;
-
-	return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
-			  const struct resource *rsrc,
-			  resource_size_t *start, resource_size_t *end)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	resource_size_t offset = 0;
-
-	if (hose == NULL)
-		return;
-
-	if (rsrc->flags & IORESOURCE_IO)
-		offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
-	/* We pass a fully fixed up address to userland for MMIO instead of
-	 * a BAR value because X is lame and expects to be able to use that
-	 * to pass to /dev/mem !
-	 *
-	 * That means that we'll have potentially 64 bits values where some
-	 * userland apps only expect 32 (like X itself since it thinks only
-	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
-	 * 32 bits CHRPs :-(
-	 *
-	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
-	 * has been fixed (and the fix spread enough), we can re-enable the
-	 * 2 lines below and pass down a BAR value to userland. In that case
-	 * we'll also have to re-enable the matching code in
-	 * __pci_mmap_make_offset().
-	 *
-	 * BenH.
-	 */
-#if 0
-	else if (rsrc->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-#endif
-
-	*start = rsrc->start - offset;
-	*end = rsrc->end - offset;
-}
-
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
-	if (!have_of)
-		return NULL;
-	while(node) {
-		struct pci_controller *hose, *tmp;
-		list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-			if (hose->arch_data == node)
-				return hose;
-		node = node->parent;
-	}
-	return NULL;
-}
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
 	struct pci_controller *hose, *tmp;
@@ -1412,7 +914,7 @@
 		if (address >= hose->io_base_phys &&
 		    address < (hose->io_base_phys + hose->pci_io_size)) {
 			unsigned long base =
-				(unsigned long)hose->io_base_virt - pci_io_base;
+				(unsigned long)hose->io_base_virt - _IO_BASE;
 			return base + (address - hose->io_base_phys);
 		}
 	}
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index c96fa9b..a20f195 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -67,7 +67,6 @@
 EXPORT_SYMBOL(DMA_MODE_READ);
 EXPORT_SYMBOL(DMA_MODE_WRITE);
 
-EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(machine_check_exception);
@@ -106,10 +105,6 @@
 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);
 #endif /* CONFIG_PCI */
 
 EXPORT_SYMBOL(start_thread);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 6e2f035..84f000a 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -219,22 +219,26 @@
 }
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_PPC_MERGE		/* XXX for now */
 int set_dabr(unsigned long dabr)
 {
+#ifdef CONFIG_PPC_MERGE		/* XXX for now */
 	if (ppc_md.set_dabr)
 		return ppc_md.set_dabr(dabr);
+#endif
 
+	/* XXX should we have a CPU_FTR_HAS_DABR ? */
+#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
 	mtspr(SPRN_DABR, dabr);
+#endif
 	return 0;
 }
-#endif
 
 #ifdef CONFIG_PPC64
 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
-static DEFINE_PER_CPU(unsigned long, current_dabr);
 #endif
 
+static DEFINE_PER_CPU(unsigned long, current_dabr);
+
 struct task_struct *__switch_to(struct task_struct *prev,
 	struct task_struct *new)
 {
@@ -299,12 +303,10 @@
 
 #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;
 	}
-#endif /* CONFIG_PPC64 */
 
 	new_thread = &new->thread;
 	old_thread = &current->thread;
@@ -473,12 +475,10 @@
 
 	discard_lazy_cpu_state();
 
-#ifdef CONFIG_PPC64	/* for now */
 	if (current->thread.dabr) {
 		current->thread.dabr = 0;
 		set_dabr(0);
 	}
-#endif
 }
 
 void
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index af42dda..37ff99b 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -52,6 +52,7 @@
 #include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
 #include <asm/kexec.h>
+#include <asm/system.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) printk(KERN_ERR fmt)
@@ -1005,7 +1006,7 @@
 
 void __init early_init_devtree(void *params)
 {
-	DBG(" -> early_init_devtree()\n");
+	DBG(" -> early_init_devtree(%p)\n", params);
 
 	/* Setup flat device-tree pointer */
 	initial_boot_params = params;
@@ -1055,8 +1056,6 @@
 	DBG(" <- early_init_devtree()\n");
 }
 
-#undef printk
-
 int of_n_addr_cells(struct device_node* np)
 {
 	const int *ip;
@@ -1375,8 +1374,17 @@
 	struct device_node *node = kref_to_device_node(kref);
 	struct property *prop = node->properties;
 
-	if (!OF_IS_DYNAMIC(node))
+	/* We should never be releasing nodes that haven't been detached. */
+	if (!of_node_check_flag(node, OF_DETACHED)) {
+		printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
+		dump_stack();
+		kref_init(&node->kref);
 		return;
+	}
+
+	if (!of_node_check_flag(node, OF_DYNAMIC))
+		return;
+
 	while (prop) {
 		struct property *next = prop->next;
 		kfree(prop->name);
@@ -1432,6 +1440,8 @@
 	write_lock(&devtree_lock);
 
 	parent = np->parent;
+	if (!parent)
+		goto out_unlock;
 
 	if (allnodes == np)
 		allnodes = np->allnext;
@@ -1455,6 +1465,9 @@
 		prevsib->sibling = np->sibling;
 	}
 
+	of_node_set_flag(np, OF_DETACHED);
+
+out_unlock:
 	write_unlock(&devtree_lock);
 }
 
@@ -1716,22 +1729,18 @@
 }
 EXPORT_SYMBOL(of_get_cpu_node);
 
-#ifdef DEBUG
+#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
 static struct debugfs_blob_wrapper flat_dt_blob;
 
 static int __init export_flat_device_tree(void)
 {
 	struct dentry *d;
 
-	d = debugfs_create_dir("powerpc", NULL);
-	if (!d)
-		return 1;
-
 	flat_dt_blob.data = initial_boot_params;
 	flat_dt_blob.size = initial_boot_params->totalsize;
 
 	d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
-				d, &flat_dt_blob);
+				powerpc_debugfs_root, &flat_dt_blob);
 	if (!d)
 		return 1;
 
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index d6047c4..a1d582e 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -635,6 +635,7 @@
 /* ibm,dynamic-reconfiguration-memory property supported */
 #define OV5_DRCONF_MEMORY	0x20
 #define OV5_LARGE_PAGES		0x10	/* large pages supported */
+#define OV5_DONATE_DEDICATE_CPU 0x02	/* donate dedicated CPU support */
 /* PCIe/MSI support.  Without MSI full PCIe is not supported */
 #ifdef CONFIG_PCI_MSI
 #define OV5_MSI			0x01	/* PCIe/MSI support */
@@ -685,7 +686,8 @@
 	/* option vector 5: PAPR/OF options */
 	3 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
-	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
+	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
+	OV5_DONATE_DEDICATE_CPU | OV5_MSI,
 };
 
 /* Old method - ELF header with PT_NOTE sections */
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h
deleted file mode 100644
index 8797ae7..0000000
--- a/arch/powerpc/kernel/ptrace-common.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration
- *    Extracted from ptrace.c and ptrace32.c
- *
- * 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.
- */
-
-#ifndef _PPC64_PTRACE_COMMON_H
-#define _PPC64_PTRACE_COMMON_H
-
-#include <asm/system.h>
-
-/*
- * Set of msr bits that gdb can change on behalf of a process.
- */
-#define MSR_DEBUGCHANGE	(MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
-
-/*
- * Get contents of register REGNO in task TASK.
- */
-static inline unsigned long get_reg(struct task_struct *task, int regno)
-{
-	unsigned long tmp = 0;
-
-	/*
-	 * Put the correct FP bits in, they might be wrong as a result
-	 * of our lazy FP restore.
-	 */
-	if (regno == PT_MSR) {
-		tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
-		tmp |= task->thread.fpexc_mode;
-	} else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
-		tmp = ((unsigned long *)task->thread.regs)[regno];
-	}
-
-	return tmp;
-}
-
-/*
- * 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_SOFTE) {
-		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;
-}
-
-static inline void set_single_step(struct task_struct *task)
-{
-	struct pt_regs *regs = task->thread.regs;
-	if (regs != NULL)
-		regs->msr |= MSR_SE;
-	set_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-static inline void clear_single_step(struct task_struct *task)
-{
-	struct pt_regs *regs = task->thread.regs;
-	if (regs != NULL)
-		regs->msr &= ~MSR_SE;
-	clear_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-#ifdef CONFIG_ALTIVEC
-/*
- * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
- * The transfer totals 34 quadword.  Quadwords 0-31 contain the
- * corresponding vector registers.  Quadword 32 contains the vscr as the
- * last word (offset 12) within that quadword.  Quadword 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.
- */
-
-/*
- * Get contents of AltiVec register state in task TASK
- */
-static inline int get_vrregs(unsigned long __user *data,
-			     struct task_struct *task)
-{
-	unsigned long regsize;
-
-	/* copy AltiVec registers VR[0] .. VR[31] */
-	regsize = 32 * sizeof(vector128);
-	if (copy_to_user(data, task->thread.vr, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VSCR */
-	regsize = 1 * sizeof(vector128);
-	if (copy_to_user(data, &task->thread.vscr, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VRSAVE */
-	if (put_user(task->thread.vrsave, (u32 __user *)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)
-{
-	unsigned long regsize;
-
-	/* copy AltiVec registers VR[0] .. VR[31] */
-	regsize = 32 * sizeof(vector128);
-	if (copy_from_user(task->thread.vr, data, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VSCR */
-	regsize = 1 * sizeof(vector128);
-	if (copy_from_user(&task->thread.vscr, data, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VRSAVE */
-	if (get_user(task->thread.vrsave, (u32 __user *)data))
-		return -EFAULT;
-
-	return 0;
-}
-#endif
-
-static inline int ptrace_set_debugreg(struct task_struct *task,
-				      unsigned long addr, unsigned long data)
-{
-	/* We only support one DABR and no IABRS at the moment */
-	if (addr > 0)
-		return -EINVAL;
-
-	/* The bottom 3 bits are flags */
-	if ((data & ~0x7UL) >= TASK_SIZE)
-		return -EIO;
-
-	/* Ensure translation is on */
-	if (data && !(data & DABR_TRANSLATION))
-		return -EIO;
-
-	task->thread.dabr = data;
-	return 0;
-}
-
-#endif /* _PPC64_PTRACE_COMMON_H */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index bf76562..8a177bd 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -35,11 +35,11 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_PPC64
-#include "ptrace-common.h"
-#endif
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
 
-#ifdef CONFIG_PPC32
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
@@ -48,65 +48,117 @@
 #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.
+ * Max register writeable via put_reg
  */
-
 #ifdef CONFIG_PPC32
+#define PT_MAX_PUT_REG	PT_MQ
+#else
+#define PT_MAX_PUT_REG	PT_CCR
+#endif
+
 /*
  * Get contents of register REGNO in task TASK.
  */
-static inline unsigned long get_reg(struct task_struct *task, int regno)
+unsigned long ptrace_get_reg(struct task_struct *task, int regno)
 {
-	if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
-	    && task->thread.regs != NULL)
+	unsigned long tmp = 0;
+
+	if (task->thread.regs == NULL)
+		return -EIO;
+
+	if (regno == PT_MSR) {
+		tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
+		return tmp | task->thread.fpexc_mode;
+	}
+
+	if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
 		return ((unsigned long *)task->thread.regs)[regno];
-	return (0);
+
+	return -EIO;
 }
 
 /*
  * Write contents of register REGNO in task TASK.
  */
-static inline int put_reg(struct task_struct *task, int regno,
-			  unsigned long data)
+int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
 {
-	if (regno <= PT_MQ && task->thread.regs != NULL) {
+	if (task->thread.regs == NULL)
+		return -EIO;
+
+	if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
 		if (regno == PT_MSR)
 			data = (data & MSR_DEBUGCHANGE)
 				| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+		/* We prevent mucking around with the reserved area of trap
+		 * which are used internally by the kernel
+		 */
+		if (regno == PT_TRAP)
+			data &= 0xfff0;
 		((unsigned long *)task->thread.regs)[regno] = data;
 		return 0;
 	}
 	return -EIO;
 }
 
+
+static int get_fpregs(void __user *data, struct task_struct *task,
+		      int has_fpscr)
+{
+	unsigned int count = has_fpscr ? 33 : 32;
+
+	if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_fpregs(void __user *data, struct task_struct *task,
+		      int has_fpscr)
+{
+	unsigned int count = has_fpscr ? 33 : 32;
+
+	if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
+		return -EFAULT;
+	return 0;
+}
+
+
 #ifdef CONFIG_ALTIVEC
 /*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
+ * corresponding vector registers.  Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword.  Quadword 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.
+ */
+
+/*
  * Get contents of AltiVec register state in task TASK
  */
-static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
+static 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;
+	unsigned long regsize;
 
 	/* 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;
+	regsize = 32 * sizeof(vector128);
+	if (copy_to_user(data, task->thread.vr, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
 	/* copy VSCR */
-	for (i = 0; i < 4; i++, data++)
-		if (__put_user(task->thread.vscr.u[i], data))
-			return -EFAULT;
+	regsize = 1 * sizeof(vector128);
+	if (copy_to_user(data, &task->thread.vscr, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
-        /* copy VRSAVE */
-	if (__put_user(task->thread.vrsave, data))
+	/* copy VRSAVE */
+	if (put_user(task->thread.vrsave, (u32 __user *)data))
 		return -EFAULT;
 
 	return 0;
@@ -115,31 +167,29 @@
 /*
  * Write contents of AltiVec register state into task TASK.
  */
-static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
+static 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;
+	unsigned long regsize;
 
 	/* 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;
+	regsize = 32 * sizeof(vector128);
+	if (copy_from_user(task->thread.vr, data, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
 	/* copy VSCR */
-	for (i = 0; i < 4; i++, data++)
-		if (__get_user(task->thread.vscr.u[i], data))
-			return -EFAULT;
+	regsize = 1 * sizeof(vector128);
+	if (copy_from_user(&task->thread.vscr, data, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
 	/* copy VRSAVE */
-	if (__get_user(task->thread.vrsave, data))
+	if (get_user(task->thread.vrsave, (u32 __user *)data))
 		return -EFAULT;
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_SPE
 
@@ -156,7 +206,7 @@
 /*
  * Get contents of SPE register state in task TASK.
  */
-static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+static int get_evrregs(unsigned long *data, struct task_struct *task)
 {
 	int i;
 
@@ -182,7 +232,7 @@
 /*
  * Write contents of SPE register state into task TASK.
  */
-static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+static int set_evrregs(struct task_struct *task, unsigned long *data)
 {
 	int i;
 
@@ -205,8 +255,8 @@
 }
 #endif /* CONFIG_SPE */
 
-static inline void
-set_single_step(struct task_struct *task)
+
+static void set_single_step(struct task_struct *task)
 {
 	struct pt_regs *regs = task->thread.regs;
 
@@ -221,8 +271,7 @@
 	set_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
 
-static inline void
-clear_single_step(struct task_struct *task)
+static void clear_single_step(struct task_struct *task)
 {
 	struct pt_regs *regs = task->thread.regs;
 
@@ -236,7 +285,25 @@
 	}
 	clear_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
-#endif /* CONFIG_PPC32 */
+
+static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
+			       unsigned long data)
+{
+	/* We only support one DABR and no IABRS at the moment */
+	if (addr > 0)
+		return -EINVAL;
+
+	/* The bottom 3 bits are flags */
+	if ((data & ~0x7UL) >= TASK_SIZE)
+		return -EIO;
+
+	/* Ensure translation is on */
+	if (data && !(data & DABR_TRANSLATION))
+		return -EIO;
+
+	task->thread.dabr = data;
+	return 0;
+}
 
 /*
  * Called by kernel/ptrace.c when detaching..
@@ -249,6 +316,62 @@
 	clear_single_step(child);
 }
 
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long arch_ptrace_old(struct task_struct *child, long request, long addr,
+			    long data)
+{
+	int ret = -EPERM;
+
+	switch(request) {
+	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. */
+		flush_fp_to_thread(child);
+		ret = get_fpregs((void __user *)addr, child, 0);
+		break;
+	}
+
+	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+		flush_fp_to_thread(child);
+		ret = set_fpregs((void __user *)addr, child, 0);
+		break;
+	}
+
+	}
+	return ret;
+}
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
 	int ret = -EPERM;
@@ -256,17 +379,9 @@
 	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);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -284,11 +399,9 @@
 #endif
 			break;
 
-#ifdef CONFIG_PPC32
 		CHECK_FULL_REGS(child->thread.regs);
-#endif
 		if (index < PT_FPR0) {
-			tmp = get_reg(child, (int) index);
+			tmp = ptrace_get_reg(child, (int) index);
 		} else {
 			flush_fp_to_thread(child);
 			tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
@@ -300,11 +413,7 @@
 	/* 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;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	/* write the word at location addr in the USER area */
@@ -323,13 +432,9 @@
 #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);
+			ret = ptrace_put_reg(child, index, data);
 		} else {
 			flush_fp_to_thread(child);
 			((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
@@ -384,7 +489,6 @@
 		break;
 	}
 
-#ifdef CONFIG_PPC64
 	case PTRACE_GET_DEBUGREG: {
 		ret = -EINVAL;
 		/* We only support one DABR and no IABRS at the moment */
@@ -398,73 +502,61 @@
 	case PTRACE_SET_DEBUGREG:
 		ret = ptrace_set_debugreg(child, addr, data);
 		break;
-#endif
 
 	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++;
+#ifdef CONFIG_PPC64
+	case PTRACE_GETREGS64:
+#endif
+	case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+		int ui;
+	  	if (!access_ok(VERIFY_WRITE, (void __user *)data,
+			       sizeof(struct pt_regs))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret |= __put_user(ptrace_get_reg(child, ui),
+					  (unsigned long __user *) data);
+			data += sizeof(long);
 		}
 		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);
+#ifdef CONFIG_PPC64
+	case PTRACE_SETREGS64:
+#endif
+	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+		unsigned long tmp;
+		int ui;
+	  	if (!access_ok(VERIFY_READ, (void __user *)data,
+			       sizeof(struct pt_regs))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret = __get_user(tmp, (unsigned long __user *) data);
 			if (ret)
 				break;
-			reg++;
-			tmp++;
+			ptrace_put_reg(child, ui, tmp);
+			data += sizeof(long);
 		}
 		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;
-
+	case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
 		flush_fp_to_thread(child);
-
-		for (i = 0; i < 32; i++) {
-			ret = put_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
+		ret = get_fpregs((void __user *)data, child, 1);
 		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;
-
+	case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
 		flush_fp_to_thread(child);
-
-		for (i = 0; i < 32; i++) {
-			ret = get_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
+		ret = set_fpregs((void __user *)data, child, 1);
 		break;
 	}
 
@@ -499,11 +591,18 @@
 		break;
 #endif
 
+	/* Old reverse args ptrace callss */
+	case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+	case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+	case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
+	case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
+		ret = arch_ptrace_old(child, request, addr, data);
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-
 	return ret;
 }
 
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 9b9a230..9e6baea 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -33,13 +33,55 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
-#include "ptrace-common.h"
-
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
 
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long compat_ptrace_old(struct task_struct *child, long request,
+			      long addr, long data)
+{
+	int ret = -EPERM;
+
+	switch(request) {
+	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;
+	}
+
+	}
+	return ret;
+}
+
 long compat_sys_ptrace(int request, int pid, unsigned long addr,
 		       unsigned long data)
 {
@@ -123,7 +165,7 @@
 			break;
 
 		if (index < PT_FPR0) {
-			tmp = get_reg(child, index);
+			tmp = ptrace_get_reg(child, index);
 		} else {
 			flush_fp_to_thread(child);
 			/*
@@ -162,7 +204,9 @@
 		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 */
+		/* 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;
 
@@ -170,7 +214,7 @@
 			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);
+			tmp = ptrace_get_reg(child, numReg);
 		} 
 		reg32bits = ((u32*)&tmp)[part];
 		ret = put_user(reg32bits, (u32 __user *)data);
@@ -226,10 +270,8 @@
 		if ((addr & 3) || (index > PT_FPSCR32))
 			break;
 
-		if (index == PT_ORIG_R3)
-			break;
 		if (index < PT_FPR0) {
-			ret = put_reg(child, index, data);
+			ret = ptrace_put_reg(child, index, data);
 		} else {
 			flush_fp_to_thread(child);
 			/*
@@ -258,70 +300,25 @@
 		/* 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) {
+		if (numReg < PT_FPR0) {
+			unsigned long freg = ptrace_get_reg(child, numReg);
+			if (index % 2)
+				freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
+			else
+				freg = (freg & 0xfffffffful) | (data << 32);
+			ret = ptrace_put_reg(child, numReg, freg);
+		} else {
 			flush_fp_to_thread(child);
+			((unsigned int *)child->thread.regs)[index] = data;
+			ret = 0;
 		}
-		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;
 	}
 
@@ -334,95 +331,67 @@
 		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_GETREGS: { /* Get all pt_regs from the child. */
+		int ui;
+	  	if (!access_ok(VERIFY_WRITE, (void __user *)data,
+			       PT_REGS_COUNT * sizeof(int))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret |= __put_user(ptrace_get_reg(child, ui),
+					  (unsigned int __user *) data);
+			data += sizeof(int);
+		}
+		break;
+	}
+
+	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+		unsigned long tmp;
+		int ui;
+	  	if (!access_ok(VERIFY_READ, (void __user *)data,
+			       PT_REGS_COUNT * sizeof(int))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret = __get_user(tmp, (unsigned int __user *) data);
+			if (ret)
+				break;
+			ptrace_put_reg(child, ui, tmp);
+			data += sizeof(int);
+		}
+		break;
+	}
+
+	case PTRACE_GETFPREGS:
+	case PTRACE_SETFPREGS:
 	case PTRACE_GETVRREGS:
-		/* Get the child altivec register state. */
-		flush_altivec_to_thread(child);
-		ret = get_vrregs((unsigned long __user *)data, child);
+	case PTRACE_SETVRREGS:
+	case PTRACE_GETREGS64:
+	case PTRACE_SETREGS64:
+	case PPC_PTRACE_GETFPREGS:
+	case PPC_PTRACE_SETFPREGS:
+	case PTRACE_KILL:
+	case PTRACE_SINGLESTEP:
+	case PTRACE_DETACH:
+	case PTRACE_SET_DEBUGREG:
+	case PTRACE_SYSCALL:
+	case PTRACE_CONT:
+		ret = arch_ptrace(child, request, addr, data);
 		break;
 
-	case PTRACE_SETVRREGS:
-		/* Set the child altivec register state. */
-		flush_altivec_to_thread(child);
-		ret = set_vrregs(child, (unsigned long __user *)data);
+	/* Old reverse args ptrace callss */
+	case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+	case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+		ret = compat_ptrace_old(child, request, addr, data);
 		break;
-#endif
 
 	default:
 		ret = ptrace_request(child, request, addr, data);
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index f228682..a5de621 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -278,10 +278,8 @@
 {
 	struct device_node *node;
 	struct pci_controller *phb;
-	unsigned int index;
 	struct device_node *root = of_find_node_by_path("/");
 
-	index = 0;
 	for (node = of_get_next_child(root, NULL);
 	     node != NULL;
 	     node = of_get_next_child(root, node)) {
@@ -295,8 +293,7 @@
 			continue;
 		rtas_setup_phb(phb);
 		pci_process_bridge_OF_ranges(phb, node, 0);
-		pci_setup_phb_io(phb, index == 0);
-		index++;
+		isa_bridge_find_early(phb);
 	}
 
 	of_node_put(root);
@@ -335,7 +332,7 @@
 		return 1;
 	}
 
-	rc = unmap_bus_range(b);
+	rc = pcibios_unmap_io_space(b);
 	if (rc) {
 		printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
 			__FUNCTION__, b->name);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index ed07a19..4924c48 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -32,6 +32,7 @@
 #include <linux/unistd.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/debugfs.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -486,6 +487,14 @@
 
 	switch(base_port) {
 	case I8042_DATA_REG:
+		if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303")))
+			np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03");
+		if (np) {
+			parent = of_get_parent(np);
+			of_node_put(np);
+			np = parent;
+			break;
+		}
 		np = of_find_node_by_type(NULL, "8042");
 		break;
 	case FDC_BASE: /* FDC1 */
@@ -571,3 +580,15 @@
 
 late_initcall(check_cache_coherency);
 #endif /* CONFIG_CHECK_CACHE_COHERENCY */
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *powerpc_debugfs_root;
+
+static int powerpc_debugfs_init(void)
+{
+	powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL);
+
+	return powerpc_debugfs_root == NULL;
+}
+arch_initcall(powerpc_debugfs_init);
+#endif
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 35f8f44..7ec6ba5 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -262,13 +262,11 @@
 	 * 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;
+	dcache_bsize = cur_cpu_spec->dcache_bsize;
+	icache_bsize = cur_cpu_spec->icache_bsize;
+	ucache_bsize = 0;
+	if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
+		ucache_bsize = icache_bsize = dcache_bsize;
 
 	/* reboot on panic */
 	panic_timeout = 180;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6018178..bc43bba 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -350,13 +350,11 @@
 {
 	DBG(" -> setup_system()\n");
 
-	/* Apply the CPUs-specific and firmware specific fixups to kernel
-	 * text (nop out sections not relevant to this CPU or this firmware)
+	/* Apply CPUs-specific fixups to kernel text (nop out sections
+	 * not relevant to this CPU)
 	 */
 	do_feature_fixups(cur_cpu_spec->cpu_features,
 			  &__start___ftr_fixup, &__stop___ftr_fixup);
-	do_feature_fixups(powerpc_firmware_features,
-			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
@@ -394,6 +392,12 @@
 	if (ppc_md.init_early)
 		ppc_md.init_early();
 
+	/* Apply firmware specific fixups to kernel text (nop out
+	 * sections not relevant to this firmware)
+	 */
+	do_feature_fixups(powerpc_firmware_features,
+			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
+
  	/*
 	 * We can discover serial ports now since the above did setup the
 	 * hash table management for us, thus ioremap works. We do that early
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
new file mode 100644
index 0000000..c434d6c
--- /dev/null
+++ b/arch/powerpc/kernel/signal.c
@@ -0,0 +1,180 @@
+/*
+ * Common signal handling code for both 32 and 64 bits
+ *
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * 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/ptrace.h>
+#include <linux/signal.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+#include "signal.h"
+
+/*
+ * Allocate space for the signal frame
+ */
+void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+			   size_t frame_size)
+{
+        unsigned long oldsp, newsp;
+
+        /* Default to using normal stack */
+        oldsp = regs->gpr[1];
+
+	/* Check for alt stack */
+	if ((ka->sa.sa_flags & SA_ONSTACK) &&
+	    current->sas_ss_size && !on_sig_stack(oldsp))
+		oldsp = (current->sas_ss_sp + current->sas_ss_size);
+
+	/* Get aligned frame */
+	newsp = (oldsp - frame_size) & ~0xFUL;
+
+	/* Check access */
+	if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
+		return NULL;
+
+        return (void __user *)newsp;
+}
+
+
+/*
+ * Restore the user process's signal mask
+ */
+void restore_sigmask(sigset_t *set)
+{
+	sigdelsetmask(set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = *set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+}
+
+static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+				  int has_handler)
+{
+	unsigned long ret = regs->gpr[3];
+	int restart = 1;
+
+	/* syscall ? */
+	if (TRAP(regs) != 0x0C00)
+		return;
+
+	/* error signalled ? */
+	if (!(regs->ccr & 0x10000000))
+		return;
+
+	switch (ret) {
+	case ERESTART_RESTARTBLOCK:
+	case ERESTARTNOHAND:
+		/* ERESTARTNOHAND means that the syscall should only be
+		 * restarted if there was no handler for the signal, and since
+		 * we only get here if there is a handler, we dont restart.
+		 */
+		restart = !has_handler;
+		break;
+	case ERESTARTSYS:
+		/* ERESTARTSYS means to restart the syscall if there is no
+		 * handler or the handler was registered with SA_RESTART
+		 */
+		restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
+		break;
+	case ERESTARTNOINTR:
+		/* ERESTARTNOINTR means that the syscall should be
+		 * called again after the signal handler returns.
+		 */
+		break;
+	default:
+		return;
+	}
+	if (restart) {
+		if (ret == ERESTART_RESTARTBLOCK)
+			regs->gpr[0] = __NR_restart_syscall;
+		else
+			regs->gpr[3] = regs->orig_gpr3;
+		regs->nip -= 4;
+		regs->result = 0;
+	} else {
+		regs->result = -EINTR;
+		regs->gpr[3] = EINTR;
+		regs->ccr |= 0x10000000;
+	}
+}
+
+int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+	siginfo_t info;
+	int signr;
+	struct k_sigaction ka;
+	int ret;
+	int is32 = is_32bit_task();
+
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else if (!oldset)
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+	/* Is there any syscall restart business here ? */
+	check_syscall_restart(regs, &ka, signr > 0);
+
+	if (signr <= 0) {
+		/* No signal to deliver -- put the saved sigmask back */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
+		return 0;               /* no signals delivered */
+	}
+
+        /*
+	 * 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);
+
+	if (is32) {
+        	if (ka.sa.sa_flags & SA_SIGINFO)
+			ret = handle_rt_signal32(signr, &ka, &info, oldset,
+					regs);
+		else
+			ret = handle_signal32(signr, &ka, &info, oldset,
+					regs);
+	} else {
+		ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+	}
+
+	if (ret) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked, &current->blocked,
+			  &ka.sa.sa_mask);
+		if (!(ka.sa.sa_flags & SA_NODEFER))
+			sigaddset(&current->blocked, signr);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+
+		/*
+		 * A signal was successfully delivered; the saved sigmask is in
+		 * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+	}
+
+	return ret;
+}
+
+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+		unsigned long r5, unsigned long r6, unsigned long r7,
+		unsigned long r8, struct pt_regs *regs)
+{
+	return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
new file mode 100644
index 0000000..77efb3d
--- /dev/null
+++ b/arch/powerpc/kernel/signal.h
@@ -0,0 +1,55 @@
+/*
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * 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.
+ */
+
+#ifndef _POWERPC_ARCH_SIGNAL_H
+#define _POWERPC_ARCH_SIGNAL_H
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+				  size_t frame_size);
+extern void restore_sigmask(sigset_t *set);
+
+extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+			   siginfo_t *info, sigset_t *oldset,
+			   struct pt_regs *regs);
+
+extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+			      siginfo_t *info, sigset_t *oldset,
+			      struct pt_regs *regs);
+
+
+#ifdef CONFIG_PPC64
+
+static inline int is_32bit_task(void)
+{
+	return test_thread_flag(TIF_32BIT);
+}
+
+extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
+			      siginfo_t *info, sigset_t *set,
+			      struct pt_regs *regs);
+
+#else /* CONFIG_PPC64 */
+
+static inline int is_32bit_task(void)
+{
+	return 1;
+}
+
+static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
+				     siginfo_t *info, sigset_t *set,
+				     struct pt_regs *regs)
+{
+	return -EFAULT;
+}
+
+#endif /* !defined(CONFIG_PPC64) */
+
+#endif  /* _POWERPC_ARCH_SIGNAL_H */
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index dd1dca5..590057e 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -51,12 +51,11 @@
 #include <asm/pgtable.h>
 #endif
 
+#include "signal.h"
+
 #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
@@ -231,8 +230,6 @@
 
 #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.
  */
@@ -251,14 +248,6 @@
  	return -ERESTARTNOHAND;
 }
 
-#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)
 {
@@ -293,14 +282,17 @@
 /*
  * When we have signals to deliver, we set up on the
  * user stack, going down from the original stack pointer:
- *	a sigregs struct
+ *	an ABI gap of 56 words
+ *	an mcontext struct
  *	a sigcontext struct
  *	a gap of __SIGNAL_FRAMESIZE bytes
  *
- * Each of these things must be a multiple of 16 bytes in size.
+ * Each of these things must be a multiple of 16 bytes in size. The following
+ * structure represent all of this except the __SIGNAL_FRAMESIZE gap
  *
  */
-struct sigregs {
+struct sigframe {
+	struct sigcontext sctx;		/* the sigcontext */
 	struct mcontext	mctx;		/* all the register values */
 	/*
 	 * Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -703,44 +695,22 @@
 }
 #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(&current->sighand->siglock);
-	current->blocked = *set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->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,
+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 pt_regs *regs)
 {
 	struct rt_sigframe __user *rt_sf;
 	struct mcontext __user *frame;
-	unsigned long origsp = newsp;
+	unsigned long newsp = 0;
 
 	/* 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))
+	rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+	if (unlikely(rt_sf == NULL))
 		goto badframe;
 
 	/* Put the siginfo & fill in most of the ucontext */
@@ -770,8 +740,12 @@
 
 	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */
 
+	/* create a stack frame for the caller of the handler */
+	newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
 	if (put_user(regs->gpr[1], (u32 __user *)newsp))
 		goto badframe;
+
+	/* Fill registers for signal handler */
 	regs->gpr[1] = newsp;
 	regs->gpr[3] = sig;
 	regs->gpr[4] = (unsigned long) &rt_sf->info;
@@ -1015,27 +989,18 @@
 /*
  * 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)
+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
 	struct sigcontext __user *sc;
-	struct sigregs __user *frame;
-	unsigned long origsp = newsp;
+	struct sigframe __user *frame;
+	unsigned long newsp = 0;
 
 	/* 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))
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+	if (unlikely(frame == NULL))
 		goto badframe;
+	sc = (struct sigcontext __user *) &frame->sctx;
 
 #if _NSIG != 64
 #error "Please adjust handle_signal()"
@@ -1047,7 +1012,7 @@
 #else
 	    || __put_user(oldset->sig[1], &sc->_unused[3])
 #endif
-	    || __put_user(to_user_ptr(frame), &sc->regs)
+	    || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
 	    || __put_user(sig, &sc->signal))
 		goto badframe;
 
@@ -1063,8 +1028,11 @@
 
 	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */
 
+	/* create a stack frame for the caller of the handler */
+	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
 	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;
@@ -1126,106 +1094,3 @@
 	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 newsp;
-	int signr, ret;
-
-#ifdef CONFIG_PPC32
-	if (try_to_freeze()) {
-		signr = 0;
-		if (!signal_pending(current))
-			goto no_signal;
-	}
-#endif
-
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
-		oldset = &current->saved_sigmask;
-	else if (!oldset)
-		oldset = &current->blocked;
-
-	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) {
-		/* No signal to deliver -- put the saved sigmask back */
-		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-		}
-		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(&current->sighand->siglock);
-		sigorsets(&current->blocked, &current->blocked,
-			  &ka.sa.sa_mask);
-		if (!(ka.sa.sa_flags & SA_NODEFER))
-			sigaddset(&current->blocked, signr);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-		/* A signal was successfully delivered; the saved sigmask is in
-		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-		if (test_thread_flag(TIF_RESTORE_SIGMASK))
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-	}
-
-	return ret;
-}
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index b27e268..de895e6 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -34,9 +34,9 @@
 #include <asm/syscalls.h>
 #include <asm/vdso.h>
 
-#define DEBUG_SIG 0
+#include "signal.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#define DEBUG_SIG 0
 
 #define GP_REGS_SIZE	min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
 #define FP_REGS_SIZE	sizeof(elf_fpregset_t)
@@ -64,14 +64,6 @@
 	char abigap[288];
 } __attribute__ ((aligned (16)));
 
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
-		     unsigned long r6, unsigned long r7, unsigned long r8,
-		     struct pt_regs *regs)
-{
-	return do_sigaltstack(uss, uoss, regs->gpr[1]);
-}
-
-
 /*
  * Set up the sigcontext for the signal frame.
  */
@@ -208,25 +200,6 @@
 }
 
 /*
- * Allocate space for the signal frame
- */
-static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-				  size_t frame_size)
-{
-        unsigned long newsp;
-
-        /* Default to using normal stack */
-        newsp = regs->gpr[1];
-
-	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
-		if (! on_sig_stack(regs->gpr[1]))
-			newsp = (current->sas_ss_sp + current->sas_ss_size);
-	}
-
-        return (void __user *)((newsp - frame_size) & -16ul);
-}
-
-/*
  * Setup the trampoline code on the stack
  */
 static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
@@ -253,19 +226,6 @@
 }
 
 /*
- * Restore the user process's signal mask (also used by signal32.c)
- */
-void restore_sigmask(sigset_t *set)
-{
-	sigdelsetmask(set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = *set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-}
-
-
-/*
  * Handle {get,set,swap}_context operations
  */
 int sys_swapcontext(struct ucontext __user *old_ctx,
@@ -359,7 +319,7 @@
 	return 0;
 }
 
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
 		sigset_t *set, struct pt_regs *regs)
 {
 	/* Handler is *really* a pointer to the function descriptor for
@@ -373,8 +333,7 @@
 	long err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+	if (unlikely(frame == NULL))
 		goto badframe;
 
 	err |= __put_user(&frame->info, &frame->pinfo);
@@ -411,7 +370,7 @@
 	funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
 
 	/* Allocate a dummy caller frame for the signal handler. */
-	newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
+	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
 	err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
 
 	/* Set up "regs" so we "return" to the signal handler. */
@@ -442,134 +401,3 @@
 	force_sigsegv(signr, current);
 	return 0;
 }
-
-
-/*
- * 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)
-{
-	int ret;
-
-	/* Set up Signal Frame */
-	ret = setup_rt_frame(sig, ka, info, oldset, regs);
-
-	if (ret) {
-		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-		if (!(ka->sa.sa_flags & SA_NODEFER))
-			sigaddset(&current->blocked,sig);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-	}
-
-	return ret;
-}
-
-static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
-{
-	switch ((int)regs->result) {
-	case -ERESTART_RESTARTBLOCK:
-	case -ERESTARTNOHAND:
-		/* ERESTARTNOHAND means that the syscall should only be
-		 * restarted if there was no handler for the signal, and since
-		 * we only get here if there is a handler, we dont restart.
-		 */
-		regs->result = -EINTR;
-		regs->gpr[3] = EINTR;
-		regs->ccr |= 0x10000000;
-		break;
-	case -ERESTARTSYS:
-		/* ERESTARTSYS means to restart the syscall if there is no
-		 * handler or the handler was registered with SA_RESTART
-		 */
-		if (!(ka->sa.sa_flags & SA_RESTART)) {
-			regs->result = -EINTR;
-			regs->gpr[3] = EINTR;
-			regs->ccr |= 0x10000000;
-			break;
-		}
-		/* fallthrough */
-	case -ERESTARTNOINTR:
-		/* ERESTARTNOINTR means that the syscall should be
-		 * called again after the signal handler returns.
-		 */
-		regs->gpr[3] = regs->orig_gpr3;
-		regs->nip -= 4;
-		regs->result = 0;
-		break;
-	}
-}
-
-/*
- * 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;
-	int signr;
-	struct k_sigaction ka;
-
-	/*
-	 * If the current thread is 32 bit - invoke the
-	 * 32 bit signal handling code
-	 */
-	if (test_thread_flag(TIF_32BIT))
-		return do_signal32(oldset, regs);
-
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
-		oldset = &current->saved_sigmask;
-	else if (!oldset)
-		oldset = &current->blocked;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		int ret;
-
-		/* Whee!  Actually deliver the signal.  */
-		if (TRAP(regs) == 0x0C00)
-			syscall_restart(regs, &ka);
-
-		/*
-		 * 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);
-
-		ret = handle_signal(signr, &ka, &info, oldset, regs);
-
-		/* If a signal was successfully delivered, the saved sigmask is in
-		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-		if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-		return ret;
-	}
-
-	if (TRAP(regs) == 0x0C00) {	/* System Call! */
-		if ((int)regs->result == -ERESTARTNOHAND ||
-		    (int)regs->result == -ERESTARTSYS ||
-		    (int)regs->result == -ERESTARTNOINTR) {
-			regs->gpr[3] = regs->orig_gpr3;
-			regs->nip -= 4; /* Back up & retry system call */
-			regs->result = 0;
-		} else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
-			regs->gpr[0] = __NR_restart_syscall;
-			regs->nip -= 4;
-			regs->result = 0;
-		}
-	}
-	/* No signal to deliver -- put the saved sigmask back */
-	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-		clear_thread_flag(TIF_RESTORE_SIGMASK);
-		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(do_signal);
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 68991c2..55d29ed 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -442,12 +442,14 @@
 	return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
 			kobject_name(&dev->kobj));
 }
+EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
 
 void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
 {
 	struct node *node = &node_devices[nid];
 	sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
 }
+EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
 
 #else
 static void register_nodes(void)
@@ -457,9 +459,6 @@
 
 #endif
 
-EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
-EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
-
 /* Only valid if CPU is present. */
 static ssize_t show_physical_id(struct sys_device *dev, char *buf)
 {
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 2c8564d..e5df167 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -77,9 +77,8 @@
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
 #ifdef CONFIG_PPC_ISERIES
-unsigned long iSeries_recal_titan = 0;
-unsigned long iSeries_recal_tb = 0; 
-static unsigned long first_settimeofday = 1;
+static unsigned long __initdata iSeries_recal_titan;
+static signed long __initdata iSeries_recal_tb;
 #endif
 
 /* The decrementer counts down by 128 every 128ns on a 601. */
@@ -113,8 +112,9 @@
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL_GPL(rtc_lock);
 
-u64 tb_to_ns_scale;
-unsigned tb_to_ns_shift;
+static u64 tb_to_ns_scale __read_mostly;
+static unsigned tb_to_ns_shift __read_mostly;
+static unsigned long boot_tb __read_mostly;
 
 struct gettimeofday_struct do_gtod;
 
@@ -214,7 +214,6 @@
  	run_posix_cpu_timers(current);
 }
 
-#ifdef CONFIG_PPC_SPLPAR
 /*
  * Stuff for accounting stolen time.
  */
@@ -222,19 +221,28 @@
 	int	initialized;			/* thread is running */
 	u64	tb;			/* last TB value read */
 	u64	purr;			/* last PURR value read */
-	spinlock_t lock;
 };
 
+/*
+ * Each entry in the cpu_purr_data array is manipulated only by its
+ * "owner" cpu -- usually in the timer interrupt but also occasionally
+ * in process context for cpu online.  As long as cpus do not touch
+ * each others' cpu_purr_data, disabling local interrupts is
+ * sufficient to serialize accesses.
+ */
 static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
 
 static void snapshot_tb_and_purr(void *data)
 {
+	unsigned long flags;
 	struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
 
+	local_irq_save(flags);
 	p->tb = mftb();
 	p->purr = mfspr(SPRN_PURR);
 	wmb();
 	p->initialized = 1;
+	local_irq_restore(flags);
 }
 
 /*
@@ -242,15 +250,14 @@
  */
 void snapshot_timebases(void)
 {
-	int cpu;
-
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
-	for_each_possible_cpu(cpu)
-		spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
 	on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
 }
 
+/*
+ * Must be called with interrupts disabled.
+ */
 void calculate_steal_time(void)
 {
 	u64 tb, purr;
@@ -262,7 +269,6 @@
 	pme = &per_cpu(cpu_purr_data, smp_processor_id());
 	if (!pme->initialized)
 		return;		/* this can happen in early boot */
-	spin_lock(&pme->lock);
 	tb = mftb();
 	purr = mfspr(SPRN_PURR);
 	stolen = (tb - pme->tb) - (purr - pme->purr);
@@ -270,9 +276,9 @@
 		account_steal_time(current, stolen);
 	pme->tb = tb;
 	pme->purr = purr;
-	spin_unlock(&pme->lock);
 }
 
+#ifdef CONFIG_PPC_SPLPAR
 /*
  * Must be called before the cpu is added to the online map when
  * a cpu is being brought up at runtime.
@@ -284,12 +290,12 @@
 
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
+	local_irq_save(flags);
 	pme = &per_cpu(cpu_purr_data, smp_processor_id());
-	spin_lock_irqsave(&pme->lock, flags);
 	pme->tb = mftb();
 	pme->purr = mfspr(SPRN_PURR);
 	pme->initialized = 1;
-	spin_unlock_irqrestore(&pme->lock, flags);
+	local_irq_restore(flags);
 }
 
 #endif /* CONFIG_PPC_SPLPAR */
@@ -550,10 +556,15 @@
  * returned by the service processor for the timebase frequency.  
  */
 
-static void iSeries_tb_recal(void)
+static int __init iSeries_tb_recal(void)
 {
 	struct div_result divres;
 	unsigned long titan, tb;
+
+	/* Make sure we only run on iSeries */
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		return -ENODEV;
+
 	tb = get_tb();
 	titan = HvCallXm_loadTod();
 	if ( iSeries_recal_titan ) {
@@ -594,8 +605,18 @@
 	}
 	iSeries_recal_titan = titan;
 	iSeries_recal_tb = tb;
+
+	return 0;
 }
-#endif
+late_initcall(iSeries_tb_recal);
+
+/* Called from platform early init */
+void __init iSeries_time_init_early(void)
+{
+	iSeries_recal_tb = get_tb();
+	iSeries_recal_titan = HvCallXm_loadTod();
+}
+#endif /* CONFIG_PPC_ISERIES */
 
 /*
  * For iSeries shared processors, we have to let the hypervisor
@@ -735,7 +756,7 @@
 {
 	if (__USE_RTC())
 		return get_rtc();
-	return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
+	return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
 }
 
 int do_settimeofday(struct timespec *tv)
@@ -759,12 +780,6 @@
 	 * 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 (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
-		iSeries_tb_recal();
-		first_settimeofday = 0;
-	}
-#endif
 
 	/* Make userspace gettimeofday spin until we're done. */
 	++vdso_data->tb_update_count;
@@ -960,6 +975,8 @@
 	}
 	tb_to_ns_scale = scale;
 	tb_to_ns_shift = shift;
+	/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
+	boot_tb = get_tb();
 
 	tm = get_boot_time();
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index bf6445a..2bb1cb9 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -149,6 +149,7 @@
 
 	bust_spinlocks(0);
 	die.lock_owner = -1;
+	add_taint(TAINT_DIE);
 	spin_unlock_irqrestore(&die.lock, flags);
 
 	if (kexec_should_crash(current) ||
@@ -777,7 +778,7 @@
 			return;
 
 		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
-		    report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
+		    report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
 			regs->nip += 4;
 			return;
 		}
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 4245579..cef01e4 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -670,7 +670,7 @@
 	/*
 	 * Fill up the "systemcfg" stuff for backward compatiblity
 	 */
-	strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
+	strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
 	vdso_data->version.major = SYSTEMCFG_MAJOR;
 	vdso_data->version.minor = SYSTEMCFG_MINOR;
 	vdso_data->processor = mfspr(SPRN_PVR);
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 21c39ff..ae4acd8 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -7,6 +7,7 @@
 #define PROVIDE32(x)	PROVIDE(x)
 #endif
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
 
 ENTRY(_stext)
 
@@ -211,6 +212,11 @@
 		*(.data.cacheline_aligned)
 	}
 
+	. = ALIGN(L1_CACHE_BYTES);
+	.data.read_mostly : {
+		*(.data.read_mostly)
+	}
+
 	. = ALIGN(PAGE_SIZE);
 	__data_nosave : {
 		__nosave_begin = .;
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index ca4dcb0..c3df504 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -12,7 +12,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c
index 838e09d..7ff2609 100644
--- a/arch/powerpc/mm/4xx_mmu.c
+++ b/arch/powerpc/mm/4xx_mmu.c
@@ -9,7 +9,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 4f839c6..7e4d27a 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -11,8 +11,7 @@
 hash-$(CONFIG_PPC_NATIVE)	:= 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)
+				   slb_low.o slb.o stab.o mmap.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
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 115b25f..0ece513 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -380,7 +380,7 @@
 	}
 	printk("VM: killing process %s\n", current->comm);
 	if (user_mode(regs))
-		do_exit(SIGKILL);
+		do_group_exit(SIGKILL);
 	return SIGKILL;
 
 do_sigbus:
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 123da03..afab247 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -14,7 +14,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 4a20d89..6ba9b47 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -104,7 +104,7 @@
 		spin_unlock(&native_tlbie_lock);
 }
 
-static inline void native_lock_hpte(hpte_t *hptep)
+static inline void native_lock_hpte(struct hash_pte *hptep)
 {
 	unsigned long *word = &hptep->v;
 
@@ -116,7 +116,7 @@
 	}
 }
 
-static inline void native_unlock_hpte(hpte_t *hptep)
+static inline void native_unlock_hpte(struct hash_pte *hptep)
 {
 	unsigned long *word = &hptep->v;
 
@@ -128,7 +128,7 @@
 			unsigned long pa, unsigned long rflags,
 			unsigned long vflags, int psize)
 {
-	hpte_t *hptep = htab_address + hpte_group;
+	struct hash_pte *hptep = htab_address + hpte_group;
 	unsigned long hpte_v, hpte_r;
 	int i;
 
@@ -163,7 +163,7 @@
 
 	hptep->r = hpte_r;
 	/* Guarantee the second dword is visible before the valid bit */
-	__asm__ __volatile__ ("eieio" : : : "memory");
+	eieio();
 	/*
 	 * Now set the first dword including the valid bit
 	 * NOTE: this also unlocks the hpte
@@ -177,7 +177,7 @@
 
 static long native_hpte_remove(unsigned long hpte_group)
 {
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 	int i;
 	int slot_offset;
 	unsigned long hpte_v;
@@ -217,7 +217,7 @@
 static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 				 unsigned long va, int psize, int local)
 {
-	hpte_t *hptep = htab_address + slot;
+	struct hash_pte *hptep = htab_address + slot;
 	unsigned long hpte_v, want_v;
 	int ret = 0;
 
@@ -233,15 +233,14 @@
 	/* Even if we miss, we need to invalidate the TLB */
 	if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
 		DBG_LOW(" -> miss\n");
-		native_unlock_hpte(hptep);
 		ret = -1;
 	} else {
 		DBG_LOW(" -> hit\n");
 		/* Update the HPTE */
 		hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
 			(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
-		native_unlock_hpte(hptep);
 	}
+	native_unlock_hpte(hptep);
 
 	/* Ensure it is out of the tlb too. */
 	tlbie(va, psize, local);
@@ -251,7 +250,7 @@
 
 static long native_hpte_find(unsigned long va, int psize)
 {
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 	unsigned long hash;
 	unsigned long i, j;
 	long slot;
@@ -294,7 +293,7 @@
 {
 	unsigned long vsid, va;
 	long slot;
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 
 	vsid = get_kernel_vsid(ea);
 	va = (vsid << 28) | (ea & 0x0fffffff);
@@ -315,7 +314,7 @@
 static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 				   int psize, int local)
 {
-	hpte_t *hptep = htab_address + slot;
+	struct hash_pte *hptep = htab_address + slot;
 	unsigned long hpte_v;
 	unsigned long want_v;
 	unsigned long flags;
@@ -345,7 +344,7 @@
 #define LP_BITS		8
 #define LP_MASK(i)	((0xFF >> (i)) << LP_SHIFT)
 
-static void hpte_decode(hpte_t *hpte, unsigned long slot,
+static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 			int *psize, unsigned long *va)
 {
 	unsigned long hpte_r = hpte->r;
@@ -415,7 +414,7 @@
 static void native_hpte_clear(void)
 {
 	unsigned long slot, slots, flags;
-	hpte_t *hptep = htab_address;
+	struct hash_pte *hptep = htab_address;
 	unsigned long hpte_v, va;
 	unsigned long pteg_count;
 	int psize;
@@ -462,7 +461,7 @@
 static void native_flush_hash_range(unsigned long number, int local)
 {
 	unsigned long va, hash, index, hidx, shift, slot;
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 	unsigned long hpte_v;
 	unsigned long want_v;
 	unsigned long flags;
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 4f2f453..2ce9491 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -87,7 +87,7 @@
 static unsigned long _SDR1;
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
 
-hpte_t *htab_address;
+struct hash_pte *htab_address;
 unsigned long htab_size_bytes;
 unsigned long htab_hash_mask;
 int mmu_linear_psize = MMU_PAGE_4K;
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
deleted file mode 100644
index c831815..0000000
--- a/arch/powerpc/mm/imalloc.c
+++ /dev/null
@@ -1,313 +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 <linux/mutex.h>
-#include <asm/cacheflush.h>
-
-#include "mmu_decl.h"
-
-static DEFINE_MUTEX(imlist_mutex);
-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;
-
-	*vm = NULL;
-	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;
-		}
-	}
-
-	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 = 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 = 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 = 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;
-	
-	mutex_lock(&imlist_mutex);
-	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:
-	mutex_unlock(&imlist_mutex);
-	return area;
-}
-
-struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-		int criteria)
-{
-	struct vm_struct *area;
-
-	mutex_lock(&imlist_mutex);
-	area = __im_get_area(v_addr, size, criteria);
-	mutex_unlock(&imlist_mutex);
-	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;
-	}
-	mutex_lock(&imlist_mutex);
-	for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
-		if (tmp->addr == addr) {
-			*p = tmp->next;
-			unmap_vm_area(tmp);
-			kfree(tmp);
-			mutex_unlock(&imlist_mutex);
-			return;
-		}
-	}
-	mutex_unlock(&imlist_mutex);
-	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
index 5fce6cc..e1f5ded 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
  *
  *  Derived from "arch/i386/mm/init.c"
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 7312a26..1d6edf7 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 0266a94..f0e7eed 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
  *
  *  Derived from "arch/i386/mm/init.c"
@@ -129,8 +128,6 @@
 	zone = pgdata->node_zones;
 
 	return __add_pages(zone, start_pfn, nr_pages);
-
-	return 0;
 }
 
 /*
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c
index 792086b..cc32ba4 100644
--- a/arch/powerpc/mm/mmu_context_32.c
+++ b/arch/powerpc/mm/mmu_context_32.c
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 2558c34..c94a64f 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -40,8 +39,8 @@
 extern unsigned long ioremap_base;
 extern unsigned int rtas_data, rtas_size;
 
-struct _PTE;
-extern struct _PTE *Hash, *Hash_end;
+struct hash_pte;
+extern struct hash_pte *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 
 extern unsigned int num_tlbcam_entries;
@@ -90,16 +89,4 @@
 	else
 		_tlbie(va);
 }
-#else /* CONFIG_PPC64 */
-/* imalloc region types */
-#define IM_REGION_UNUSED	0x1
-#define IM_REGION_SUBSET	0x2
-#define IM_REGION_EXISTS	0x4
-#define IM_REGION_OVERLAP	0x8
-#define IM_REGION_SUPERSET	0x10
-
-extern struct vm_struct * im_get_free_area(unsigned long size);
-extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-				      int region_type);
-extern void im_free(void *addr);
 #endif
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index f6ae1a5..6448872 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -37,7 +36,6 @@
 unsigned long ioremap_base;
 unsigned long ioremap_bot;
 EXPORT_SYMBOL(ioremap_bot);	/* aka VMALLOC_END */
-int io_bat_index;
 
 #if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
 #define HAVE_BATS	1
@@ -300,51 +298,6 @@
 	}
 }
 
-/* is x a power of 4? */
-#define is_power_of_4(x)	is_power_of_2(x) && (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
@@ -379,82 +332,6 @@
         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, NULL)) {
-		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;
-}
-
 #ifdef CONFIG_DEBUG_PAGEALLOC
 
 static int __change_page_attr(struct page *page, pgprot_t prot)
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index ad6e135..3dfd10d 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -7,7 +7,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -34,41 +33,27 @@
 #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/sections.h>
 #include <asm/system.h>
-#include <asm/iommu.h>
 #include <asm/abs_addr.h>
-#include <asm/vdso.h>
 #include <asm/firmware.h>
 
 #include "mmu_decl.h"
 
-unsigned long ioremap_bot = IMALLOC_BASE;
-static unsigned long phbs_io_bot = PHBS_IO_BASE;
+unsigned long ioremap_bot = IOREMAP_BASE;
 
 /*
  * map_io_page currently only called by __ioremap
@@ -102,8 +87,8 @@
 		 * entry in the hardware page table.
 		 *
 		 */
-		if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
-				      mmu_io_psize)) {
+		if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE,
+				      pa, flags, mmu_io_psize)) {
 			printk(KERN_ERR "Failed to do bolted mapping IO "
 			       "memory at %016lx !\n", pa);
 			return -ENOMEM;
@@ -113,8 +98,11 @@
 }
 
 
-static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
-			    unsigned long ea, unsigned long size,
+/**
+ * __ioremap_at - Low level function to establish the page tables
+ *                for an IO mapping
+ */
+void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
 			    unsigned long flags)
 {
 	unsigned long i;
@@ -122,17 +110,35 @@
 	if ((flags & _PAGE_PRESENT) == 0)
 		flags |= pgprot_val(PAGE_KERNEL);
 
+	WARN_ON(pa & ~PAGE_MASK);
+	WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+	WARN_ON(size & ~PAGE_MASK);
+
 	for (i = 0; i < size; i += PAGE_SIZE)
-		if (map_io_page(ea+i, pa+i, flags))
+		if (map_io_page((unsigned long)ea+i, pa+i, flags))
 			return NULL;
 
-	return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+	return (void __iomem *)ea;
+}
+
+/**
+ * __iounmap_from - Low level function to tear down the page tables
+ *                  for an IO mapping. This is used for mappings that
+ *                  are manipulated manually, like partial unmapping of
+ *                  PCI IOs or ISA space.
+ */
+void __iounmap_at(void *ea, unsigned long size)
+{
+	WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+	WARN_ON(size & ~PAGE_MASK);
+
+	unmap_kernel_range((unsigned long)ea, size);
 }
 
 void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
 			 unsigned long flags)
 {
-	unsigned long pa, ea;
+	phys_addr_t paligned;
 	void __iomem *ret;
 
 	/*
@@ -144,27 +150,30 @@
 	 * IMALLOC_END
 	 * 
 	 */
-	pa = addr & PAGE_MASK;
-	size = PAGE_ALIGN(addr + size) - pa;
+	paligned = addr & PAGE_MASK;
+	size = PAGE_ALIGN(addr + size) - paligned;
 
-	if ((size == 0) || (pa == 0))
+	if ((size == 0) || (paligned == 0))
 		return NULL;
 
 	if (mem_init_done) {
 		struct vm_struct *area;
-		area = im_get_free_area(size);
+
+		area = __get_vm_area(size, VM_IOREMAP,
+				     ioremap_bot, IOREMAP_END);
 		if (area == NULL)
 			return NULL;
-		ea = (unsigned long)(area->addr);
-		ret = __ioremap_com(addr, pa, ea, size, flags);
+		ret = __ioremap_at(paligned, area->addr, size, flags);
 		if (!ret)
-			im_free(area->addr);
+			vunmap(area->addr);
 	} else {
-		ea = ioremap_bot;
-		ret = __ioremap_com(addr, pa, ea, size, flags);
+		ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags);
 		if (ret)
 			ioremap_bot += size;
 	}
+
+	if (ret)
+		ret += addr & ~PAGE_MASK;
 	return ret;
 }
 
@@ -187,62 +196,9 @@
 }
 
 
-#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
-
-int __ioremap_explicit(phys_addr_t 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)
 {
@@ -251,9 +207,14 @@
 	if (!mem_init_done)
 		return;
 	
-	addr = (void *) ((unsigned long __force) token & PAGE_MASK);
-
-	im_free(addr);
+	addr = (void *) ((unsigned long __force)
+			 PCI_FIX_ADDR(token) & PAGE_MASK);
+	if ((unsigned long)addr < ioremap_bot) {
+		printk(KERN_WARNING "Attempt to iounmap early bolted mapping"
+		       " at 0x%p\n", addr);
+		return;
+	}
+	vunmap(addr);
 }
 
 void iounmap(volatile void __iomem *token)
@@ -264,77 +225,8 @@
 		__iounmap(token);
 }
 
-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;
-}
-
 EXPORT_SYMBOL(ioremap);
 EXPORT_SYMBOL(ioremap_flags);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(__iounmap);
-
-static DEFINE_SPINLOCK(phb_io_lock);
-
-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");
-			
-	spin_lock(&phb_io_lock);
-	virt_addr = (void __iomem *) phbs_io_bot;
-	phbs_io_bot += size;
-	spin_unlock(&phb_io_lock);
-
-	return virt_addr;
-}
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index ec1421a..5c45d47 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -35,12 +34,12 @@
 
 #include "mmu_decl.h"
 
-PTE *Hash, *Hash_end;
+struct hash_pte *Hash, *Hash_end;
 unsigned long Hash_size, Hash_mask;
 unsigned long _SDR1;
 
 union ubat {			/* BAT register values to be loaded */
-	BAT	bat;
+	struct ppc_bat bat;
 	u32	word[2];
 } BATS[8][2];			/* 8 pairs of IBAT, DBAT */
 
@@ -245,7 +244,7 @@
 	cacheable_memzero(Hash, Hash_size);
 	_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 
-	Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
+	Hash_end = (struct hash_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);
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 132c6bc..28492bb 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -55,7 +55,7 @@
 		for (entry = 0; entry < 8; entry++, ste++) {
 			if (!(ste->esid_data & STE_ESID_V)) {
 				ste->vsid_data = vsid_data;
-				asm volatile("eieio":::"memory");
+				eieio();
 				ste->esid_data = esid_data;
 				return (global_entry | entry);
 			}
@@ -101,7 +101,7 @@
 	asm volatile("sync" : : : "memory");    /* Order update */
 
 	castout_ste->vsid_data = vsid_data;
-	asm volatile("eieio" : : : "memory");   /* Order update */
+	eieio();				/* Order update */
 	castout_ste->esid_data = esid_data;
 
 	asm volatile("slbie  %0" : : "r" (old_esid << SID_SHIFT));
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c
index 6a69417..06c7e77 100644
--- a/arch/powerpc/mm/tlb_32.c
+++ b/arch/powerpc/mm/tlb_32.c
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index 2bfc4d7..cbd34fc 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -239,3 +238,59 @@
 	pte_free_submit(*batchp);
 	*batchp = NULL;
 }
+
+/**
+ * __flush_hash_table_range - Flush all HPTEs for a given address range
+ *                            from the hash table (and the TLB). But keeps
+ *                            the linux PTEs intact.
+ *
+ * @mm		: mm_struct of the target address space (generally init_mm)
+ * @start	: starting address
+ * @end         : ending address (not included in the flush)
+ *
+ * This function is mostly to be used by some IO hotplug code in order
+ * to remove all hash entries from a given address range used to map IO
+ * space on a removed PCI-PCI bidge without tearing down the full mapping
+ * since 64K pages may overlap with other bridges when using 64K pages
+ * with 4K HW pages on IO space.
+ *
+ * Because of that usage pattern, it's only available with CONFIG_HOTPLUG
+ * and is implemented for small size rather than speed.
+ */
+#ifdef CONFIG_HOTPLUG
+
+void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+			      unsigned long end)
+{
+	unsigned long flags;
+
+	start = _ALIGN_DOWN(start, PAGE_SIZE);
+	end = _ALIGN_UP(end, PAGE_SIZE);
+
+	BUG_ON(!mm->pgd);
+
+	/* Note: Normally, we should only ever use a batch within a
+	 * PTE locked section. This violates the rule, but will work
+	 * since we don't actually modify the PTEs, we just flush the
+	 * hash while leaving the PTEs intact (including their reference
+	 * to being hashed). This is not the most performance oriented
+	 * way to do things but is fine for our needs here.
+	 */
+	local_irq_save(flags);
+	arch_enter_lazy_mmu_mode();
+	for (; start < end; start += PAGE_SIZE) {
+		pte_t *ptep = find_linux_pte(mm->pgd, start);
+		unsigned long pte;
+
+		if (ptep == NULL)
+			continue;
+		pte = pte_val(*ptep);
+		if (!(pte & _PAGE_HASHPTE))
+			continue;
+		hpte_need_flush(mm, start, ptep, pte, 0);
+	}
+	arch_leave_lazy_mmu_mode();
+	local_irq_restore(flags);
+}
+
+#endif /* CONFIG_HOTPLUG */
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index fe597a1..a7c206b 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Added mmcra[slot] support:
+ * Copyright (C) 2006-2007 Will Schmidt <willschm@us.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
@@ -181,11 +183,17 @@
  * 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.
+ * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits
+ * to more accurately identify the address of the sampled instruction. The
+ * mmcra[slot] bits represent the slot number of a sampled instruction
+ * within an instruction group.  The slot will contain a value between 1
+ * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0.
  */
 static unsigned long get_pc(struct pt_regs *regs)
 {
 	unsigned long pc = mfspr(SPRN_SIAR);
 	unsigned long mmcra;
+	unsigned long slot;
 
 	/* Cant do much about it */
 	if (!cur_cpu_spec->oprofile_mmcra_sihv)
@@ -193,6 +201,12 @@
 
 	mmcra = mfspr(SPRN_MMCRA);
 
+	if (mmcra & MMCRA_SAMPLE_ENABLE) {
+		slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT);
+		if (slot > 1)
+			pc += 4 * (slot - 1);
+	}
+
 	/* Were we in the hypervisor? */
 	if (firmware_has_feature(FW_FEATURE_LPAR) &&
 	    (mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index f591a9f..4be6e7a 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -54,7 +54,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
-	    | (hose->index << 24);
+	    | (hose->global_number << 24);
 	int ret = -1;
 	int rval;
 
@@ -69,7 +69,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
-	    | (hose->index << 24);
+	    | (hose->global_number << 24);
 	int rval;
 
 	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -83,7 +83,7 @@
 };
 
 
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
 {
 	const int *bus_range;
 	int len;
@@ -128,7 +128,7 @@
 	printk(" controlled by %s\n", pcictrl->full_name);
 	printk("\n");
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(of_node_get(pcictrl));
 	if (!hose) {
 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
 		       ": Can't allocate PCI controller structure for %s\n",
@@ -136,7 +136,6 @@
 		return;
 	}
 
-	hose->arch_data = of_node_get(pcictrl);
 	hose->first_busno = bus_range[0];
 	hose->last_busno = bus_range[1];
 	hose->ops = &rtas_pci_ops;
@@ -145,7 +144,7 @@
 }
 
 #else
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
 {}
 #endif
 
@@ -252,6 +251,8 @@
 	.progress		= rtas_progress,
 	.get_boot_time		= rtas_get_boot_time,
 	.calibrate_decr		= generic_calibrate_decr,
+#ifdef CONFIG_PCI
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
+#endif
 };
 
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 1cfc00d..5c46e89 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -156,7 +156,7 @@
 
 }
 
-void lite5200_show_cpuinfo(struct seq_file *m)
+static void lite5200_show_cpuinfo(struct seq_file *m)
 {
 	struct device_node* np = of_find_all_nodes(NULL);
 	const char *model = NULL;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index 34d34a2..4c6c82a 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -112,18 +112,18 @@
 	u32 value;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	out_be32(hose->cfg_addr,
 		(1 << 31) |
-		((bus->number - hose->bus_offset) << 16) |
+		(bus->number << 16) |
 		(devfn << 8) |
 		(offset & 0xfc));
 	mb();
 
 #if defined(CONFIG_PPC_MPC5200_BUGFIX)
-	if (bus->number != hose->bus_offset) {
+	if (bus->number) {
 		/* workaround for the bug 435 of the MPC5200 (L25R);
 		 * Don't do 32 bits config access during type-1 cycles */
 		switch (len) {
@@ -169,18 +169,18 @@
 	u32 value, mask;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	out_be32(hose->cfg_addr,
 		(1 << 31) |
-		((bus->number - hose->bus_offset) << 16) |
+		(bus->number << 16) |
 		(devfn << 8) |
 		(offset & 0xfc));
 	mb();
 
 #if defined(CONFIG_PPC_MPC5200_BUGFIX)
-	if (bus->number != hose->bus_offset) {
+	if (bus->number) {
 		/* workaround for the bug 435 of the MPC5200 (L25R);
 		 * Don't do 32 bits config access during type-1 cycles */
 		switch (len) {
@@ -385,17 +385,13 @@
 	 * tree are needed to configure the 52xx PCI controller.  Rather
 	 * than parse the tree here, let pci_process_bridge_OF_ranges()
 	 * do it for us and extract the values after the fact */
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(node);
 	if (!hose)
 		return -ENOMEM;
 
-	hose->arch_data = node;
-	hose->set_cfg_type = 1;
-
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-	hose->bus_offset = 0;
 	hose->ops = &mpc52xx_pci_ops;
 
 	pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index fd40044..ee2e763 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -9,8 +9,8 @@
 
 
 /* these are defined in mpc52xx_sleep.S, and only used here */
-extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
-		struct mpc52xx_cdm *, struct mpc52xx_intr *);
+extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs,
+		struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*);
 extern void mpc52xx_ds_sram(void);
 extern const long mpc52xx_ds_sram_size;
 extern void mpc52xx_ds_cached(void);
@@ -21,7 +21,7 @@
 static struct mpc52xx_cdm __iomem *cdm;
 static struct mpc52xx_intr __iomem *intr;
 static struct mpc52xx_gpio_wkup __iomem *gpiow;
-static void *sram;
+static void __iomem *sram;
 static int sram_size;
 
 struct mpc52xx_suspend mpc52xx_suspend;
@@ -100,7 +100,7 @@
 	u32 clk_enables;
 	u32 msr, hid0;
 	u32 intr_main_mask;
-	void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
+	void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500;
 	unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
 	char saved_0x500[mpc52xx_ds_cached_size];
 
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index de7fce9..89fde43 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -1,5 +1,5 @@
 choice
-	prompt "Machine Type"
+	prompt "82xx Board Type"
 	depends on PPC_82xx
 	default MPC82xx_ADS
 
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index 47cb09f..da20832 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -49,7 +49,7 @@
 #include <linux/fs_enet_pd.h>
 
 #include <sysdev/fsl_soc.h>
-#include <../sysdev/cpm2_pic.h>
+#include <sysdev/cpm2_pic.h>
 
 #include "pq2ads.h"
 
@@ -507,7 +507,8 @@
 	return;
 }
 
-static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
+static int m82xx_pci_exclude_device(struct pci_controller *hose,
+				    u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -515,7 +516,7 @@
 		return PCIBIOS_SUCCESSFUL;
 }
 
-void __init add_bridge(struct device_node *np)
+static void __init mpc82xx_add_bridge(struct device_node *np)
 {
 	int len;
 	struct pci_controller *hose;
@@ -542,19 +543,13 @@
 
 	pci_assign_all_buses = 1;
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(np);
 
 	if (!hose)
 		return;
 
-	hose->arch_data = np;
-	hose->set_cfg_type = 1;
-
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
-	hose->bus_offset = 0;
-
-	hose->set_cfg_type = 1;
 
 	setup_indirect_pci(hose,
 			   r.start + offsetof(pci_cpm2_t, pci_cfg_addr),
@@ -584,7 +579,7 @@
 #ifdef CONFIG_PCI
 	ppc_md.pci_exclude_device = m82xx_pci_exclude_device;
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc82xx_add_bridge(np);
 
 	of_node_put(np);
 #endif
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 19cafdf..ec305f1 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -1,5 +1,5 @@
 choice
-	prompt "Machine Type"
+	prompt "83xx Board Type"
 	depends on PPC_83xx
 	default MPC834x_MDS
 
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 31a91b5..5a98f88 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for the PowerPC 83xx linux kernel.
 #
-obj-y				:= misc.o
+obj-y				:= misc.o usb.o
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_MPC8313_RDB)	+= mpc8313_rdb.o
 obj-$(CONFIG_MPC832x_RDB)	+= mpc832x_rdb.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 96970ac..3edfe17 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -28,11 +28,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -49,10 +44,11 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
+	mpc831x_usb_cfg();
 }
 
 void __init mpc8313_rdb_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 94843ed..b39cb52 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -49,11 +49,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static u8 *bcsr_regs = NULL;
 
 /* ************************************************************************
@@ -80,7 +75,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index 3db68b7..b2b28a4 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -32,11 +32,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -53,7 +48,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 40a0194..47ba544 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -38,11 +38,6 @@
 
 #include "mpc83xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -59,10 +54,12 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
+
+	mpc834x_usb_cfg();
 }
 
 static void __init mpc834x_itx_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 10394b2..4c9ff9c 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -38,61 +38,17 @@
 
 #include "mpc83xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 #define BCSR5_INT_USB		0x02
-/* Note: This is only for PB, not for PB+PIB
- * On PB only port0 is connected using ULPI */
-static int mpc834x_usb_cfg(void)
+static int mpc834xemds_usb_cfg(void)
 {
-	unsigned long sccr, sicrl;
-	void __iomem *immap;
+	struct device_node *np;
 	void __iomem *bcsr_regs = NULL;
 	u8 bcsr5;
-	struct device_node *np = NULL;
-	int port0_is_dr = 0;
 
-	if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL)
-		port0_is_dr = 1;
-	if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){
-		if (port0_is_dr) {
-			printk(KERN_WARNING
-				"There is only one USB port on PB board! \n");
-			return -1;
-		} else if (!port0_is_dr)
-			/* No usb port enabled */
-			return -1;
-	}
-
-	immap = ioremap(get_immrbase(), 0x1000);
-	if (!immap)
-		return -1;
-
-	/* Configure clock */
-	sccr = in_be32(immap + MPC83XX_SCCR_OFFS);
-	if (port0_is_dr)
-		sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
-	else
-		sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
-	out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
-
-	/* Configure Pin */
-	sicrl = in_be32(immap + MPC83XX_SICRL_OFFS);
-	/* set port0 only */
-	if (port0_is_dr)
-		sicrl |= MPC83XX_SICRL_USB0;
-	else
-		sicrl &= ~(MPC83XX_SICRL_USB0);
-	out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
-
-	iounmap(immap);
-
+	mpc834x_usb_cfg();
 	/* Map BCSR area */
 	np = of_find_node_by_name(NULL, "bcsr");
-	if (np != 0) {
+	if (np) {
 		struct resource res;
 
 		of_address_to_resource(np, 0, &res);
@@ -129,12 +85,12 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
-	mpc834x_usb_cfg();
+	mpc834xemds_usb_cfg();
 }
 
 static void __init mpc834x_mds_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index bceeff8..0e615fd 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -55,11 +55,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static u8 *bcsr_regs = NULL;
 
 /* ************************************************************************
@@ -86,7 +81,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 9cd03b5..589ee55 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -3,9 +3,11 @@
 
 #include <linux/init.h>
 #include <linux/device.h>
+#include <asm/pci-bridge.h>
 
 /* System Clock Control Register */
 #define MPC83XX_SCCR_OFFS          0xA08
+#define MPC83XX_SCCR_USB_MASK      0x00f00000
 #define MPC83XX_SCCR_USB_MPHCM_11  0x00c00000
 #define MPC83XX_SCCR_USB_MPHCM_01  0x00400000
 #define MPC83XX_SCCR_USB_MPHCM_10  0x00800000
@@ -15,21 +17,43 @@
 
 /* system i/o configuration register low */
 #define MPC83XX_SICRL_OFFS         0x114
-#define MPC83XX_SICRL_USB0         0x40000000
-#define MPC83XX_SICRL_USB1         0x20000000
+#define MPC834X_SICRL_USB_MASK     0x60000000
+#define MPC834X_SICRL_USB0         0x40000000
+#define MPC834X_SICRL_USB1         0x20000000
+#define MPC831X_SICRL_USB_MASK     0x00000c00
+#define MPC831X_SICRL_USB_ULPI     0x00000800
 
 /* system i/o configuration register high */
 #define MPC83XX_SICRH_OFFS         0x118
-#define MPC83XX_SICRH_USB_UTMI     0x00020000
+#define MPC834X_SICRH_USB_UTMI     0x00020000
+#define MPC831X_SICRH_USB_MASK     0x000000e0
+#define MPC831X_SICRH_USB_ULPI     0x000000a0
+
+/* USB Control Register */
+#define FSL_USB2_CONTROL_OFFS      0x500
+#define CONTROL_UTMI_PHY_EN        0x00000200
+#define CONTROL_REFSEL_48MHZ       0x00000080
+#define CONTROL_PHY_CLK_SEL_ULPI   0x00000400
+#define CONTROL_OTG_PORT           0x00000020
+
+/* USB PORTSC Registers */
+#define FSL_USB2_PORTSC1_OFFS      0x184
+#define FSL_USB2_PORTSC2_OFFS      0x188
+#define PORTSCX_PTW_16BIT          0x10000000
+#define PORTSCX_PTS_UTMI           0x00000000
+#define PORTSCX_PTS_ULPI           0x80000000
 
 /*
  * Declaration for the various functions exported by the
  * mpc83xx_* files. Mostly for use by mpc83xx_setup
  */
 
-extern int add_bridge(struct device_node *dev);
-extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern int mpc83xx_add_bridge(struct device_node *dev);
+extern int mpc83xx_exclude_device(struct pci_controller *hose,
+				  u_char bus, u_char devfn);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
+extern int mpc834x_usb_cfg(void);
+extern int mpc831x_usb_cfg(void);
 
 #endif				/* __MPC83XX_H__ */
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 774457d..c0e2b89 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -33,19 +33,14 @@
 #define DBG(x...)
 #endif
 
-int mpc83xx_pci2_busno;
-
-int mpc83xx_exclude_device(u_char bus, u_char devfn)
+int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
 {
-	if (bus == 0 && PCI_SLOT(devfn) == 0)
+	if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (mpc83xx_pci2_busno)
-		if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0)
-			return PCIBIOS_DEVICE_NOT_FOUND;
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int __init add_bridge(struct device_node *dev)
+int __init mpc83xx_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -66,11 +61,10 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	hose = pcibios_alloc_controller();
+	pci_assign_all_buses = 1;
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -86,8 +80,6 @@
 	if ((rsrc.start & 0xfffff) == 0x8600) {
 		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384);
 		primary = 0;
-		hose->bus_offset = hose->first_busno;
-		mpc83xx_pci2_busno = hose->first_busno;
 	}
 
 	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
new file mode 100644
index 0000000..e7fdf01
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -0,0 +1,181 @@
+/*
+ * Freescale 83xx USB SOC setup code
+ *
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ * Author: Li Yang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/errno.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+
+#ifdef CONFIG_MPC834x
+int mpc834x_usb_cfg(void)
+{
+	unsigned long sccr, sicrl, sicrh;
+	void __iomem *immap;
+	struct device_node *np = NULL;
+	int port0_is_dr = 0, port1_is_dr = 0;
+	const void *prop, *dr_mode;
+
+	immap = ioremap(get_immrbase(), 0x1000);
+	if (!immap)
+		return -ENOMEM;
+
+	/* Read registers */
+	/* Note: DR and MPH must use the same clock setting in SCCR */
+	sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK;
+	sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
+	sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
+
+	np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+	if (np) {
+		sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
+
+		prop = of_get_property(np, "phy_type", NULL);
+		if (prop && (!strcmp(prop, "utmi") ||
+					!strcmp(prop, "utmi_wide"))) {
+			sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+			sicrh |= MPC834X_SICRH_USB_UTMI;
+			port1_is_dr = 1;
+		} else if (prop && !strcmp(prop, "serial")) {
+			dr_mode = of_get_property(np, "dr_mode", NULL);
+			if (dr_mode && !strcmp(dr_mode, "otg")) {
+				sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+				port1_is_dr = 1;
+			} else {
+				sicrl |= MPC834X_SICRL_USB0;
+			}
+		} else if (prop && !strcmp(prop, "ulpi")) {
+			sicrl |= MPC834X_SICRL_USB0;
+		} else {
+			printk(KERN_WARNING "834x USB PHY type not supported\n");
+		}
+		port0_is_dr = 1;
+		of_node_put(np);
+	}
+	np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph");
+	if (np) {
+		sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
+
+		prop = of_get_property(np, "port0", NULL);
+		if (prop) {
+			if (port0_is_dr)
+				printk(KERN_WARNING
+					"834x USB port0 can't be used by both DR and MPH!\n");
+			sicrl |= MPC834X_SICRL_USB0;
+		}
+		prop = of_get_property(np, "port1", NULL);
+		if (prop) {
+			if (port1_is_dr)
+				printk(KERN_WARNING
+					"834x USB port1 can't be used by both DR and MPH!\n");
+			sicrl |= MPC834X_SICRL_USB1;
+		}
+		of_node_put(np);
+	}
+
+	/* Write back */
+	out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
+	out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
+	out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);
+
+	iounmap(immap);
+	return 0;
+}
+#endif /* CONFIG_MPC834x */
+
+#ifdef CONFIG_PPC_MPC831x
+int mpc831x_usb_cfg(void)
+{
+	u32 temp;
+	void __iomem *immap, *usb_regs;
+	struct device_node *np = NULL;
+	const void *prop;
+	struct resource res;
+	int ret = 0;
+#ifdef CONFIG_USB_OTG
+	const void *dr_mode;
+#endif
+
+	np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+	if (!np)
+		return -ENODEV;
+	prop = of_get_property(np, "phy_type", NULL);
+
+	/* Map IMMR space for pin and clock settings */
+	immap = ioremap(get_immrbase(), 0x1000);
+	if (!immap) {
+		of_node_put(np);
+		return -ENOMEM;
+	}
+
+	/* Configure clock */
+	temp = in_be32(immap + MPC83XX_SCCR_OFFS);
+	temp &= ~MPC83XX_SCCR_USB_MASK;
+	temp |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
+	out_be32(immap + MPC83XX_SCCR_OFFS, temp);
+
+	/* Configure pin mux for ULPI.  There is no pin mux for UTMI */
+	if (!strcmp(prop, "ulpi")) {
+		temp = in_be32(immap + MPC83XX_SICRL_OFFS);
+		temp &= ~MPC831X_SICRL_USB_MASK;
+		temp |= MPC831X_SICRL_USB_ULPI;
+		out_be32(immap + MPC83XX_SICRL_OFFS, temp);
+
+		temp = in_be32(immap + MPC83XX_SICRH_OFFS);
+		temp &= ~MPC831X_SICRH_USB_MASK;
+		temp |= MPC831X_SICRH_USB_ULPI;
+		out_be32(immap + MPC83XX_SICRH_OFFS, temp);
+	}
+
+	iounmap(immap);
+
+	/* Map USB SOC space */
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret) {
+		of_node_put(np);
+		return ret;
+	}
+	usb_regs = ioremap(res.start, res.end - res.start + 1);
+
+	/* Using on-chip PHY */
+	if (!strcmp(prop, "utmi_wide") ||
+			!strcmp(prop, "utmi")) {
+		/* Set UTMI_PHY_EN, REFSEL to 48MHZ */
+		out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
+				CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ);
+	/* Using external UPLI PHY */
+	} else if (!strcmp(prop, "ulpi")) {
+		/* Set PHY_CLK_SEL to ULPI */
+		temp = CONTROL_PHY_CLK_SEL_ULPI;
+#ifdef CONFIG_USB_OTG
+		/* Set OTG_PORT */
+		dr_mode = of_get_property(np, "dr_mode", NULL);
+		if (dr_mode && !strcmp(dr_mode, "otg"))
+			temp |= CONTROL_OTG_PORT;
+#endif /* CONFIG_USB_OTG */
+		out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
+	} else {
+		printk(KERN_WARNING "831x USB PHY type not supported\n");
+		ret = -EINVAL;
+	}
+
+	iounmap(usb_regs);
+	of_node_put(np);
+	return ret;
+}
+#endif /* CONFIG_PPC_MPC831x */
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c
index 3e62fcb..4fe376e 100644
--- a/arch/powerpc/platforms/85xx/misc.c
+++ b/arch/powerpc/platforms/85xx/misc.c
@@ -13,11 +13,43 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+static __be32 __iomem *rstcr;
 
 extern void abort(void);
 
+static int __init mpc85xx_rstcr(void)
+{
+	struct device_node *np;
+	np = of_find_node_by_name(NULL, "global-utilities");
+	if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
+		const u32 *prop = of_get_property(np, "reg", NULL);
+		if (prop) {
+			/* map reset control register
+			 * 0xE00B0 is offset of reset control register
+			 */
+			rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
+			if (!rstcr)
+				printk (KERN_EMERG "Error: reset control "
+						"register not mapped!\n");
+		}
+	} else
+		printk (KERN_INFO "rstcr compatible register does not exist!\n");
+	if (np)
+		of_node_put(np);
+	return 0;
+}
+
+arch_initcall(mpc85xx_rstcr);
+
 void mpc85xx_restart(char *cmd)
 {
 	local_irq_disable();
+	if (rstcr)
+		/* set reset control register */
+		out_be32(rstcr, 0x2);	/* HRESET_REQ */
 	abort();
 }
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c
index bec84ff..6fb90aa 100644
--- a/arch/powerpc/platforms/85xx/mpc8544_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c
@@ -61,24 +61,11 @@
 		return;
 	}
 
-	/* Alloc mpic structure and per isu has 16 INT entries. */
 	mpic = mpic_alloc(np, r.start,
 			  MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			  16, 64, " OPENPIC     ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 
-	/*
-	 * 48 Internal Interrupts
-	 */
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10400);
-	mpic_assign_isu(mpic, 2, r.start + 0x10600);
-
-	/*
-	 * 16 External interrupts
-	 */
-	mpic_assign_isu(mpic, 3, r.start + 0x10000);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_PPC_I8259
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h
index 83415db..7286ffa 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx.h
@@ -15,4 +15,4 @@
  */
 
 extern void mpc85xx_restart(char *);
-extern int add_bridge(struct device_node *dev);
+extern int mpc85xx_add_bridge(struct device_node *dev);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 5d27621..7235f70 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -38,13 +38,9 @@
 #include <asm/fs_pd.h>
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 #ifdef CONFIG_PCI
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+				   u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -91,30 +87,10 @@
 
 	mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			4, 0, " OpenPIC  ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 	of_node_put(np);
 
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10280);
-	mpic_assign_isu(mpic, 2, r.start + 0x10300);
-	mpic_assign_isu(mpic, 3, r.start + 0x10380);
-	mpic_assign_isu(mpic, 4, r.start + 0x10400);
-	mpic_assign_isu(mpic, 5, r.start + 0x10480);
-	mpic_assign_isu(mpic, 6, r.start + 0x10500);
-	mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
-	/* Unused on this platform (leave room for 8548) */
-	mpic_assign_isu(mpic, 8, r.start + 0x10600);
-	mpic_assign_isu(mpic, 9, r.start + 0x10680);
-	mpic_assign_isu(mpic, 10, r.start + 0x10700);
-	mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-	/* External Interrupts */
-	mpic_assign_isu(mpic, 12, r.start + 0x10000);
-	mpic_assign_isu(mpic, 13, r.start + 0x10080);
-	mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_CPM2
@@ -241,7 +217,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc85xx_add_bridge(np);
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 1490eb3..50c8d64 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -47,11 +47,6 @@
 #include <sysdev/fsl_soc.h>
 #include "mpc85xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static int cds_pci_slot = 2;
 static volatile u8 *cadmus;
 
@@ -60,15 +55,11 @@
 #define ARCADIA_HOST_BRIDGE_IDSEL	17
 #define ARCADIA_2ND_BRIDGE_IDSEL	3
 
-extern int mpc85xx_pci2_busno;
-
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+				  u_char bus, u_char devfn)
 {
-	if (bus == 0 && PCI_SLOT(devfn) == 0)
+	if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (mpc85xx_pci2_busno)
-		if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
-			return PCIBIOS_DEVICE_NOT_FOUND;
 	/* We explicitly do not go past the Tundra 320 Bridge */
 	if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -78,52 +69,44 @@
 		return PCIBIOS_SUCCESSFUL;
 }
 
-static void __init mpc85xx_cds_pcibios_fixup(void)
+static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev)
 {
-	struct pci_dev *dev;
-	u_char		c;
+	u_char c;
+	if (dev->vendor == PCI_VENDOR_ID_VIA) {
+		switch (dev->device) {
+		case PCI_DEVICE_ID_VIA_82C586_1:
+			/*
+			 * U-Boot does not set the enable bits
+			 * for the IDE device. Force them on here.
+			 */
+			pci_read_config_byte(dev, 0x40, &c);
+			c |= 0x03; /* IDE: Chip Enable Bits */
+			pci_write_config_byte(dev, 0x40, c);
 
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-					PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+			/*
+			 * Since only primary interface works, force the
+			 * IDE function to standard primary IDE interrupt
+			 * w/ 8259 offset
+			 */
+			dev->irq = 14;
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+			break;
 		/*
-		 * U-Boot does not set the enable bits
-		 * for the IDE device. Force them on here.
+		 * Force legacy USB interrupt routing
 		 */
-		pci_read_config_byte(dev, 0x40, &c);
-		c |= 0x03; /* IDE: Chip Enable Bits */
-		pci_write_config_byte(dev, 0x40, c);
-
-		/*
-		 * Since only primary interface works, force the
-		 * IDE function to standard primary IDE interrupt
-		 * w/ 8259 offset
+		case PCI_DEVICE_ID_VIA_82C586_2:
+		/* There are two USB controllers.
+		 * Identify them by functon number
 		 */
-		dev->irq = 14;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-		pci_dev_put(dev);
+			if (PCI_FUNC(dev->devfn))
+				dev->irq = 11;
+			else
+				dev->irq = 10;
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		default:
+			break;
+		}
 	}
-
-	/*
-	 * Force legacy USB interrupt routing
-	 */
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-					PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
-		dev->irq = 10;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
-		pci_dev_put(dev);
-	}
-
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-					PCI_DEVICE_ID_VIA_82C586_2, dev))) {
-		dev->irq = 11;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
-		pci_dev_put(dev);
-	}
-
-	/* Now map all the PCI irqs */
-	dev = NULL;
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
 }
 
 #ifdef CONFIG_PPC_I8259
@@ -165,33 +148,12 @@
 
 	mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			4, 0, " OpenPIC  ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 
 	/* Return the mpic node */
 	of_node_put(np);
 
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10280);
-	mpic_assign_isu(mpic, 2, r.start + 0x10300);
-	mpic_assign_isu(mpic, 3, r.start + 0x10380);
-	mpic_assign_isu(mpic, 4, r.start + 0x10400);
-	mpic_assign_isu(mpic, 5, r.start + 0x10480);
-	mpic_assign_isu(mpic, 6, r.start + 0x10500);
-	mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
-	/* Used only for 8548 so far, but no harm in
-	 * allocating them for everyone */
-	mpic_assign_isu(mpic, 8, r.start + 0x10600);
-	mpic_assign_isu(mpic, 9, r.start + 0x10680);
-	mpic_assign_isu(mpic, 10, r.start + 0x10700);
-	mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-	/* External Interrupts */
-	mpic_assign_isu(mpic, 12, r.start + 0x10000);
-	mpic_assign_isu(mpic, 13, r.start + 0x10080);
-	mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_PPC_I8259
@@ -257,9 +219,9 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc85xx_add_bridge(np);
 
-	ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+	ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index e3dddbf..004b80b 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -59,11 +59,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -100,7 +95,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) {
-		add_bridge(np);
+		mpc85xx_add_bridge(np);
 	}
 	of_node_put(np);
 #endif
@@ -181,29 +176,10 @@
 
 	mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			4, 0, " OpenPIC  ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 	of_node_put(np);
 
-	/* Internal Interrupts */
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10280);
-	mpic_assign_isu(mpic, 2, r.start + 0x10300);
-	mpic_assign_isu(mpic, 3, r.start + 0x10380);
-	mpic_assign_isu(mpic, 4, r.start + 0x10400);
-	mpic_assign_isu(mpic, 5, r.start + 0x10480);
-	mpic_assign_isu(mpic, 6, r.start + 0x10500);
-	mpic_assign_isu(mpic, 7, r.start + 0x10580);
-	mpic_assign_isu(mpic, 8, r.start + 0x10600);
-	mpic_assign_isu(mpic, 9, r.start + 0x10680);
-	mpic_assign_isu(mpic, 10, r.start + 0x10700);
-	mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-	/* External Interrupts */
-	mpic_assign_isu(mpic, 12, r.start + 0x10000);
-	mpic_assign_isu(mpic, 13, r.start + 0x10080);
-	mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c
index 48f17e2..8118417 100644
--- a/arch/powerpc/platforms/85xx/pci.c
+++ b/arch/powerpc/platforms/85xx/pci.c
@@ -33,10 +33,8 @@
 #define DBG(x...)
 #endif
 
-int mpc85xx_pci2_busno = 0;
-
 #ifdef CONFIG_PCI
-int __init add_bridge(struct device_node *dev)
+int __init mpc85xx_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -57,11 +55,10 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	hose = pcibios_alloc_controller();
+	pci_assign_all_buses = 1;
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -74,8 +71,6 @@
 	if ((rsrc.start & 0xfffff) == 0x9000) {
 		setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004);
 		primary = 0;
-		hose->bus_offset = hose->first_busno;
-		mpc85xx_pci2_busno = hose->first_busno;
 	}
 
 	printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index d1bcff5..0faebfd 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,5 +1,5 @@
 choice
-	prompt "Machine Type"
+	prompt "86xx Board Type"
 	depends on PPC_86xx
 	default MPC8641_HPCN
 
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
index 2834462..23f7ed2 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx.h
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -15,15 +15,10 @@
  * mpc86xx_* files. Mostly for use by mpc86xx_setup().
  */
 
-extern int add_bridge(struct device_node *dev);
+extern int mpc86xx_add_bridge(struct device_node *dev);
 
-extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
-
-extern void setup_indirect_pcie(struct pci_controller *hose,
-				       u32 cfg_addr, u32 cfg_data);
-extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
-					     void __iomem *cfg_addr,
-					     void __iomem *cfg_data);
+extern int mpc86xx_exclude_device(struct pci_controller *hose,
+				  u_char bus, u_char devfn);
 
 extern void __init mpc86xx_smp_init(void);
 
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 1051702..5b01ec7 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -44,13 +44,6 @@
 #define DBG(fmt...) do { } while(0)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-unsigned long pci_dram_offset = 0;
-#endif
-
-
 #ifdef CONFIG_PCI
 static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
@@ -81,22 +74,9 @@
 	/* Alloc mpic structure and per isu has 16 INT entries. */
 	mpic1 = mpic_alloc(np, res.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			16, NR_IRQS - 4,
-			" MPIC     ");
+			0, 256, " MPIC     ");
 	BUG_ON(mpic1 == NULL);
 
-	mpic_assign_isu(mpic1, 0, res.start + 0x10000);
-
-	/* 48 Internal Interrupts */
-	mpic_assign_isu(mpic1, 1, res.start + 0x10200);
-	mpic_assign_isu(mpic1, 2, res.start + 0x10400);
-	mpic_assign_isu(mpic1, 3, res.start + 0x10600);
-
-	/* 16 External interrupts
-	 * Moving them from [0 - 15] to [64 - 79]
-	 */
-	mpic_assign_isu(mpic1, 4, res.start + 0x10000);
-
 	mpic_init(mpic1);
 
 #ifdef CONFIG_PCI
@@ -319,6 +299,7 @@
 {
 	unsigned short temp;
 	pci_write_config_word(dev, 0x04, 0x0405);
+	dev->class &= ~0x5;
 	pci_read_config_word(dev, 0x4a, &temp);
 	temp |= 0x1000;
 	pci_write_config_word(dev, 0x4a, temp);
@@ -364,9 +345,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
-
-	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+		mpc86xx_add_bridge(np);
 #endif
 
 	printk("MPC86xx HPCN board from Freescale Semiconductor\n");
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index 8235c56..73cd5b0 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -122,7 +122,6 @@
 mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
 {
 	u16 cmd;
-	unsigned int temps;
 
 	DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
 			pcie_offset, pcie_size);
@@ -133,22 +132,49 @@
 	early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
 
 	early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
-
-	/* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
-	early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
-	temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
-	early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
 }
 
-int mpc86xx_exclude_device(u_char bus, u_char devfn)
+static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev)
 {
-	if (bus == 0 && PCI_SLOT(devfn) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	struct resource *res;
+	int i, res_idx = PCI_BRIDGE_RESOURCES;
+	struct pci_controller *hose;
 
-	return PCIBIOS_SUCCESSFUL;
+	/*
+	 * Make the bridge be transparent.
+	 */
+	dev->transparent = 1;
+
+	hose = pci_bus_to_host(dev->bus);
+	if (!hose) {
+		printk(KERN_ERR "Can't find hose for bus %d\n",
+		       dev->bus->number);
+		return;
+	}
+
+	if (hose->io_resource.flags) {
+		res = &dev->resource[res_idx++];
+		res->start = hose->io_resource.start;
+		res->end = hose->io_resource.end;
+		res->flags = hose->io_resource.flags;
+	}
+
+	for (i = 0; i < 3; i++) {
+		res = &dev->resource[res_idx + i];
+		res->start = hose->mem_resources[i].start;
+		res->end = hose->mem_resources[i].end;
+		res->flags = hose->mem_resources[i].flags;
+	}
 }
 
-int __init add_bridge(struct device_node *dev)
+
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent);
+
+#define PCIE_LTSSM	0x404	/* PCIe Link Training and Status */
+#define PCIE_LTSSM_L0	0x16	/* L0 state */
+
+int __init mpc86xx_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -156,6 +182,7 @@
 	const int *bus_range;
 	int has_address = 0;
 	int primary = 0;
+	u16 val;
 
 	DBG("Adding PCIE host bridge %s\n", dev->full_name);
 
@@ -168,17 +195,23 @@
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 		       " bus 0\n", dev->full_name);
 
-	hose = pcibios_alloc_controller();
+	pci_assign_all_buses = 1;
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
-	/* last_busno = 0xfe cause by MPC8641 PCIE bug */
+	hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG |
+				PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
+
 	hose->first_busno = bus_range ? bus_range[0] : 0x0;
-	hose->last_busno = bus_range ? bus_range[1] : 0xfe;
+	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-	setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
+	setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4);
+
+	/* Probe the hose link training status */
+	early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val);
+	if (val < PCIE_LTSSM_L0)
+		return -ENXIO;
 
 	/* Setup the PCIE host controller. */
 	mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 0901dba..f169355 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -32,6 +32,7 @@
 #include <linux/root_dev.h>
 #include <linux/time.h>
 #include <linux/rtc.h>
+#include <linux/fsl_devices.h>
 
 #include <asm/mmu.h>
 #include <asm/reg.h>
@@ -49,6 +50,10 @@
 
 #include "sysdev/mpc8xx_pic.h"
 
+#ifdef CONFIG_PCMCIA_M8XX
+struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
 void m8xx_calibrate_decr(void);
 extern void m8xx_wdt_handler_install(bd_t *bp);
 extern int cpm_pic_init(void);
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index c36e475..5a808d6 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -22,6 +22,7 @@
 
 #include <linux/fs_enet_pd.h>
 #include <linux/fs_uart_pd.h>
+#include <linux/fsl_devices.h>
 #include <linux/mii.h>
 
 #include <asm/delay.h>
@@ -39,7 +40,7 @@
 #include <asm/prom.h>
 
 extern void cpm_reset(void);
-extern void mpc8xx_show_cpuinfo(struct seq_file*);
+extern void mpc8xx_show_cpuinfo(struct seq_file *);
 extern void mpc8xx_restart(char *cmd);
 extern void mpc8xx_calibrate_decr(void);
 extern int mpc8xx_set_rtc_time(struct rtc_time *tm);
@@ -47,9 +48,73 @@
 extern void m8xx_pic_init(void);
 extern unsigned int mpc8xx_get_irq(void);
 
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_scc3_ioports(struct fs_platform_info* ptr);
+static void init_smc1_uart_ioports(struct fs_uart_platform_info *fpi);
+static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi);
+static void init_scc3_ioports(struct fs_platform_info *ptr);
+
+#ifdef CONFIG_PCMCIA_M8XX
+static void pcmcia_hw_setup(int slot, int enable)
+{
+	unsigned *bcsr_io;
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	if (enable)
+		clrbits32(bcsr_io, BCSR1_PCCEN);
+	else
+		setbits32(bcsr_io, BCSR1_PCCEN);
+
+	iounmap(bcsr_io);
+}
+
+static int pcmcia_set_voltage(int slot, int vcc, int vpp)
+{
+	u32 reg = 0;
+	unsigned *bcsr_io;
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+	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 */
+	clrbits32(bcsr_io, 0x00610000);
+
+	/* enable new powersettings */
+	setbits32(bcsr_io, reg);
+
+	iounmap(bcsr_io);
+	return 0;
+}
+#endif
 
 void __init mpc885ads_board_setup(void)
 {
@@ -62,7 +127,7 @@
 #endif
 
 	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 
 	if (bcsr_io == NULL) {
 		printk(KERN_CRIT "Could not remap BCSR\n");
@@ -75,13 +140,13 @@
 	out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
 	clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);	/* brg1 */
 #else
-	setbits32(bcsr_io,BCSR1_RS232EN_1);
+	setbits32(bcsr_io, BCSR1_RS232EN_1);
 	out_be16(&cp->cp_smc[0].smc_smcmr, 0);
 	out_8(&cp->cp_smc[0].smc_smce, 0);
 #endif
 
 #ifdef CONFIG_SERIAL_CPM_SMC2
-	clrbits32(bcsr_io,BCSR1_RS232EN_2);
+	clrbits32(bcsr_io, BCSR1_RS232EN_2);
 	clrbits32(&cp->cp_simode, 0xe0000000 >> 1);
 	setbits32(&cp->cp_simode, 0x20000000 >> 1);	/* brg2 */
 	tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
@@ -90,7 +155,7 @@
 
 	init_smc2_uart_ioports(0);
 #else
-	setbits32(bcsr_io,BCSR1_RS232EN_2);
+	setbits32(bcsr_io, BCSR1_RS232EN_2);
 	out_be16(&cp->cp_smc[1].smc_smcmr, 0);
 	out_8(&cp->cp_smc[1].smc_smce, 0);
 #endif
@@ -99,29 +164,34 @@
 
 #ifdef CONFIG_FS_ENET
 	/* use MDC for MII (common) */
-	io_port = (iop8xx_t*)immr_map(im_ioport);
+	io_port = (iop8xx_t *) immr_map(im_ioport);
 	setbits16(&io_port->iop_pdpar, 0x0080);
 	clrbits16(&io_port->iop_pddir, 0x0080);
 
 	bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
-	clrbits32(bcsr_io,BCSR5_MII1_EN);
-	clrbits32(bcsr_io,BCSR5_MII1_RST);
+	clrbits32(bcsr_io, BCSR5_MII1_EN);
+	clrbits32(bcsr_io, BCSR5_MII1_RST);
 #ifndef CONFIG_FC_ENET_HAS_SCC
-	clrbits32(bcsr_io,BCSR5_MII2_EN);
-	clrbits32(bcsr_io,BCSR5_MII2_RST);
+	clrbits32(bcsr_io, BCSR5_MII2_EN);
+	clrbits32(bcsr_io, BCSR5_MII2_RST);
 
 #endif
 	iounmap(bcsr_io);
 	immr_unmap(io_port);
 
 #endif
+
+#ifdef CONFIG_PCMCIA_M8XX
+	/*Set up board specific hook-ups */
+	m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup;
+	m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage;
+#endif
 }
 
-
-static void init_fec1_ioports(struct fs_platform_info* ptr)
+static void init_fec1_ioports(struct fs_platform_info *ptr)
 {
-	cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-	iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+	cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm);
+	iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport);
 
 	/* configure FEC1 pins  */
 	setbits16(&io_port->iop_papar, 0xf830);
@@ -143,11 +213,10 @@
 	immr_unmap(cp);
 }
 
-
-static void init_fec2_ioports(struct fs_platform_info* ptr)
+static void init_fec2_ioports(struct fs_platform_info *ptr)
 {
-	cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-	iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+	cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm);
+	iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport);
 
 	/* configure FEC2 pins */
 	setbits32(&cp->cp_pepar, 0x0003fffc);
@@ -177,15 +246,15 @@
 	}
 }
 
-static void init_scc3_ioports(struct fs_platform_info* fpi)
+static void init_scc3_ioports(struct fs_platform_info *fpi)
 {
 	unsigned *bcsr_io;
 	iop8xx_t *io_port;
 	cpm8xx_t *cp;
 
 	bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
-	io_port = (iop8xx_t *)immr_map(im_ioport);
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	io_port = (iop8xx_t *) immr_map(im_ioport);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 
 	if (bcsr_io == NULL) {
 		printk(KERN_CRIT "Could not remap BCSR\n");
@@ -194,9 +263,9 @@
 
 	/* Enable the PHY.
 	 */
-	clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+	clrbits32(bcsr_io + 4, BCSR4_ETH10_RST);
 	udelay(1000);
-	setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+	setbits32(bcsr_io + 4, BCSR4_ETH10_RST);
 	/* Configure port A pins for Txd and Rxd.
 	 */
 	setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
@@ -212,8 +281,7 @@
 	 */
 	setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
 	clrbits32(&cp->cp_pepar, PE_ENET_TENA);
-	clrbits32(&cp->cp_pedir,
-		  PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+	clrbits32(&cp->cp_pedir, PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
 	clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
 	setbits32(&cp->cp_peso, PE_ENET_TENA);
 
@@ -237,7 +305,7 @@
 	clrbits32(&cp->cp_pedir, PE_ENET_TENA);
 	setbits32(&cp->cp_peso, PE_ENET_TENA);
 
-	setbits32(bcsr_io+4, BCSR1_ETHEN);
+	setbits32(bcsr_io + 4, BCSR1_ETHEN);
 	iounmap(bcsr_io);
 	immr_unmap(io_port);
 	immr_unmap(cp);
@@ -257,50 +325,48 @@
 	}
 }
 
-
-
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
+static void init_smc1_uart_ioports(struct fs_uart_platform_info *ptr)
 {
-        unsigned *bcsr_io;
+	unsigned *bcsr_io;
 	cpm8xx_t *cp;
 
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 	setbits32(&cp->cp_pepar, 0x000000c0);
 	clrbits32(&cp->cp_pedir, 0x000000c0);
 	clrbits32(&cp->cp_peso, 0x00000040);
 	setbits32(&cp->cp_peso, 0x00000080);
 	immr_unmap(cp);
 
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
 
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_1);
-        iounmap(bcsr_io);
+	if (bcsr_io == NULL) {
+		printk(KERN_CRIT "Could not remap BCSR1\n");
+		return;
+	}
+	clrbits32(bcsr_io, BCSR1_RS232EN_1);
+	iounmap(bcsr_io);
 }
 
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi)
+static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi)
 {
-        unsigned *bcsr_io;
+	unsigned *bcsr_io;
 	cpm8xx_t *cp;
 
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 	setbits32(&cp->cp_pepar, 0x00000c00);
 	clrbits32(&cp->cp_pedir, 0x00000c00);
 	clrbits32(&cp->cp_peso, 0x00000400);
 	setbits32(&cp->cp_peso, 0x00000800);
 	immr_unmap(cp);
 
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
 
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_2);
-        iounmap(bcsr_io);
+	if (bcsr_io == NULL) {
+		printk(KERN_CRIT "Could not remap BCSR1\n");
+		return;
+	}
+	clrbits32(bcsr_io, BCSR1_RS232EN_2);
+	iounmap(bcsr_io);
 }
 
 void init_smc_ioports(struct fs_uart_platform_info *data)
@@ -373,15 +439,11 @@
 	return 1;
 }
 
-define_machine(mpc885_ads) {
-	.name			= "MPC885 ADS",
-	.probe			= mpc885ads_probe,
-	.setup_arch		= mpc885ads_setup_arch,
-	.init_IRQ		= m8xx_pic_init,
-	.show_cpuinfo		= mpc8xx_show_cpuinfo,
-	.get_irq		= mpc8xx_get_irq,
-	.restart		= mpc8xx_restart,
-	.calibrate_decr		= mpc8xx_calibrate_decr,
-	.set_rtc_time		= mpc8xx_set_rtc_time,
-	.get_rtc_time		= mpc8xx_get_rtc_time,
-};
+define_machine(mpc885_ads)
+{
+.name = "MPC885 ADS",.probe = mpc885ads_probe,.setup_arch =
+	    mpc885ads_setup_arch,.init_IRQ =
+	    m8xx_pic_init,.show_cpuinfo = mpc8xx_show_cpuinfo,.get_irq =
+	    mpc8xx_get_irq,.restart = mpc8xx_restart,.calibrate_decr =
+	    mpc8xx_calibrate_decr,.set_rtc_time =
+	    mpc8xx_set_rtc_time,.get_rtc_time = mpc8xx_get_rtc_time,};
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 361acfa..33545d3 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -2,7 +2,7 @@
 
 choice
 	prompt "Machine type"
-	depends on PPC64 || CLASSIC32
+	depends on PPC64 || 6xx
 	default PPC_MULTIPLATFORM
 
 config PPC_MULTIPLATFORM
@@ -16,15 +16,30 @@
 	bool "Embedded 6xx/7xx/7xxx-based board"
 	depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
 
-config APUS
-	bool "Amiga-APUS"
-	depends on PPC32 && BROKEN
+config PPC_82xx
+	bool "Freescale 82xx"
+	depends on 6xx
+
+config PPC_83xx
+	bool "Freescale 83xx"
+	depends on 6xx
+	select FSL_SOC
+	select 83xx
+	select WANT_DEVICE_TREE
+
+config PPC_86xx
+	bool "Freescale 86xx"
+	depends on 6xx
+	select FSL_SOC
+	select ALTIVEC
 	help
-	  Select APUS if configuring for a PowerUP Amiga.
-	  More information is available at:
-	  <http://linux-apus.sourceforge.net/>.
+	  The Freescale E600 SoCs have 74xx cores.
 endchoice
 
+config CLASSIC32
+	def_bool y
+	depends on 6xx && PPC_MULTIPLATFORM
+
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
new file mode 100644
index 0000000..b8b5fde94
--- /dev/null
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -0,0 +1,221 @@
+config PPC64
+	bool "64-bit kernel"
+	default n
+	help
+	  This option selects whether a 32-bit or a 64-bit kernel
+	  will be built.
+
+menu "Processor support"
+choice
+	prompt "Processor Type"
+	depends on PPC32
+	default 6xx
+	help
+	  There are five families of 32 bit PowerPC chips supported.
+	  The most common ones are the desktop and server CPUs (601, 603,
+	  604, 740, 750, 74xx) CPUs from Freescale and IBM, with their
+	  embedded 52xx/82xx/83xx/86xx counterparts.
+	  The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500
+	  (85xx) each form a family of their own that is not compatible
+	  with the others.
+
+	  If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx.
+
+config 6xx
+	bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx"
+	select PPC_FPU
+
+config PPC_85xx
+	bool "Freescale 85xx"
+	select E500
+	select FSL_SOC
+	select 85xx
+	select WANT_DEVICE_TREE
+
+config PPC_8xx
+	bool "Freescale 8xx"
+	select FSL_SOC
+	select 8xx
+
+config 40x
+	bool "AMCC 40x"
+	select PPC_DCR_NATIVE
+
+config 44x
+	bool "AMCC 44x"
+	select PPC_DCR_NATIVE
+	select WANT_DEVICE_TREE
+
+config E200
+	bool "Freescale e200"
+
+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 6xx
+	bool
+
+# this is temp to handle compat with arch=ppc
+config 8xx
+	bool
+
+# this is temp to handle compat with arch=ppc
+config 83xx
+	bool
+
+# this is temp to handle compat with arch=ppc
+config 85xx
+	bool
+
+config E500
+	bool
+
+config PPC_FPU
+	bool
+	default y if PPC64
+
+config 4xx
+	bool
+	depends on 40x || 44x
+	default y
+
+config BOOKE
+	bool
+	depends on E200 || E500 || 44x
+	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
+	select RESOURCES_64BIT
+	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 CLASSIC32 || 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
+	default y
+	---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 PPC_MM_SLICES
+	bool
+	default y if HUGETLB_PAGE
+	default n
+
+config VIRT_CPU_ACCOUNTING
+	bool "Deterministic task and CPU time accounting"
+	depends on PPC64
+	default y
+	help
+	  Select this option to enable more accurate task and CPU time
+	  accounting.  This is done by reading a CPU counter on each
+	  kernel entry and exit and on transitions within the kernel
+	  between system, softirq and hardirq state, so there is a
+	  small performance impact.  This also enables accounting of
+	  stolen time on logically-partitioned systems running on
+	  IBM POWER5-based machines.
+
+	  If in doubt, say Y here.
+
+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-128)"
+	range 2 128
+	depends on SMP
+	default "32" if PPC64
+	default "4"
+
+config NOT_COHERENT_CACHE
+	bool
+	depends on 4xx || 8xx || E200
+	default y
+
+config CONFIG_CHECK_CACHE_COHERENCY
+	bool
+
+endmenu
diff --git a/arch/powerpc/platforms/apus/Kconfig b/arch/powerpc/platforms/apus/Kconfig
deleted file mode 100644
index 6bde3bf..0000000
--- a/arch/powerpc/platforms/apus/Kconfig
+++ /dev/null
@@ -1,130 +0,0 @@
-
-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/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 7fb92f2..9d7c2ef 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -102,7 +102,7 @@
 		vaddr = (unsigned long)PCI_FIX_ADDR(addr);
 
 		/* Check if it's in allowed range for  PIO */
-		if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE)
+		if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
 			return;
 
 		/* Try to find a PTE. If not, clear the paddr, we'll do
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a7f5a76..96a8f60 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -31,6 +31,7 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
+#include <linux/linux_logo.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
 #include <asm/xmon.h>
@@ -183,7 +184,7 @@
 		spu->slb_replace = 0;
 
 	spu_restart_dma(spu);
-
+	spu->stats.slb_flt++;
 	return 0;
 }
 
@@ -332,6 +333,7 @@
 	if (stat & 0x10) /* SPU mailbox threshold */
 		spu->wbox_callback(spu);
 
+	spu->stats.class2_intr++;
 	return stat ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -462,8 +464,18 @@
 }
 EXPORT_SYMBOL_GPL(spu_free);
 
+static int spu_shutdown(struct sys_device *sysdev)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+	spu_free_irqs(spu);
+	spu_destroy_spu(spu);
+	return 0;
+}
+
 struct sysdev_class spu_sysdev_class = {
-	set_kset_name("spu")
+	set_kset_name("spu"),
+	.shutdown = spu_shutdown,
 };
 
 int spu_add_sysdev_attr(struct sysdev_attribute *attr)
@@ -574,6 +586,9 @@
 	spin_unlock_irqrestore(&spu_list_lock, flags);
 	mutex_unlock(&spu_mutex);
 
+	spu->stats.utilization_state = SPU_UTIL_IDLE;
+	spu->stats.tstamp = jiffies;
+
 	goto out;
 
 out_free_irqs:
@@ -586,6 +601,45 @@
 	return ret;
 }
 
+static const char *spu_state_names[] = {
+	"user", "system", "iowait", "idle"
+};
+
+static unsigned long long spu_acct_time(struct spu *spu,
+		enum spu_utilization_state state)
+{
+	unsigned long long time = spu->stats.times[state];
+
+	if (spu->stats.utilization_state == state)
+		time += jiffies - spu->stats.tstamp;
+
+	return jiffies_to_msecs(time);
+}
+
+
+static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+	return sprintf(buf, "%s %llu %llu %llu %llu "
+		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+		spu_state_names[spu->stats.utilization_state],
+		spu_acct_time(spu, SPU_UTIL_USER),
+		spu_acct_time(spu, SPU_UTIL_SYSTEM),
+		spu_acct_time(spu, SPU_UTIL_IOWAIT),
+		spu_acct_time(spu, SPU_UTIL_IDLE),
+		spu->stats.vol_ctx_switch,
+		spu->stats.invol_ctx_switch,
+		spu->stats.slb_flt,
+		spu->stats.hash_flt,
+		spu->stats.min_flt,
+		spu->stats.maj_flt,
+		spu->stats.class2_intr,
+		spu->stats.libassist);
+}
+
+static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
+
 static int __init init_spu_base(void)
 {
 	int i, ret = 0;
@@ -603,14 +657,28 @@
 
 	ret = spu_enumerate_spus(create_spu);
 
-	if (ret) {
+	if (ret < 0) {
 		printk(KERN_WARNING "%s: Error initializing spus\n",
 			__FUNCTION__);
 		goto out_unregister_sysdev_class;
 	}
 
+	if (ret > 0) {
+		/*
+		 * We cannot put the forward declaration in
+		 * <linux/linux_logo.h> because of conflicting session type
+		 * conflicts for const and __initdata with different compiler
+		 * versions
+		 */
+		extern const struct linux_logo logo_spe_clut224;
+
+		fb_append_extra_logo(&logo_spe_clut224, ret);
+	}
+
 	xmon_register_spus(&spu_full_list);
 
+	spu_add_sysdev_attr(&attr_stat);
+
 	return 0;
 
  out_unregister_sysdev_class:
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index 1d4562a..75ed50f 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -279,6 +279,7 @@
 {
 	int ret;
 	struct device_node *node;
+	unsigned int n = 0;
 
 	ret = -ENODEV;
 	for (node = of_find_node_by_type(NULL, "spe");
@@ -289,8 +290,9 @@
 				__FUNCTION__, node->name);
 			break;
 		}
+		n++;
 	}
-	return ret;
+	return ret ? ret : n;
 }
 
 static int __init of_create_spu(struct spu *spu, void *data)
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index d32db9f..07a0e81 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -320,6 +320,12 @@
 	/* FIXME: what are the side-effects of this? */
 	prob->dma_querymask_RW = mask;
 	prob->dma_querytype_RW = mode;
+	/* In the current implementation, the SPU context is always
+	 * acquired in runnable state when new bits are added to the
+	 * mask (tagwait), so it's sufficient just to mask
+	 * dma_tagstatus_R with the 'mask' parameter here.
+	 */
+	ctx->csa.prob.dma_tagstatus_R &= mask;
 out:
 	spin_unlock(&ctx->csa.register_lock);
 
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 7c51cb5..6d7bd60 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -23,10 +23,14 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <asm/atomic.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
+
+atomic_t nr_spu_contexts = ATOMIC_INIT(0);
+
 struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
 	struct spu_context *ctx;
@@ -53,10 +57,12 @@
 	INIT_LIST_HEAD(&ctx->rq);
 	if (gang)
 		spu_gang_add_ctx(gang, ctx);
-	ctx->rt_priority = current->rt_priority;
-	ctx->policy = current->policy;
-	ctx->prio = current->prio;
-	INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
+	ctx->cpus_allowed = current->cpus_allowed;
+	spu_set_timeslice(ctx);
+	ctx->stats.execution_state = SPUCTX_UTIL_USER;
+	ctx->stats.tstamp = jiffies;
+
+	atomic_inc(&nr_spu_contexts);
 	goto out;
 out_free:
 	kfree(ctx);
@@ -76,6 +82,7 @@
 	if (ctx->gang)
 		spu_gang_remove_ctx(ctx->gang, ctx);
 	BUG_ON(!list_empty(&ctx->rq));
+	atomic_dec(&nr_spu_contexts);
 	kfree(ctx);
 }
 
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index 0f75c07..e064d0c 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -33,7 +33,8 @@
  * function. Currently, there are a few corner cases that we haven't had
  * to handle fortunately.
  */
-static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr)
+static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+		unsigned long dsisr, unsigned *flt)
 {
 	struct vm_area_struct *vma;
 	unsigned long is_write;
@@ -73,7 +74,8 @@
 			goto bad_area;
 	}
 	ret = 0;
-	switch (handle_mm_fault(mm, vma, ea, is_write)) {
+	*flt = handle_mm_fault(mm, vma, ea, is_write);
+	switch (*flt) {
 	case VM_FAULT_MINOR:
 		current->min_flt++;
 		break;
@@ -153,6 +155,7 @@
 {
 	u64 ea, dsisr, access;
 	unsigned long flags;
+	unsigned flt = 0;
 	int ret;
 
 	/*
@@ -178,9 +181,17 @@
 	if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
 		return 0;
 
+	spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT);
+
 	pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
 		dsisr, ctx->state);
 
+	ctx->stats.hash_flt++;
+	if (ctx->state == SPU_STATE_RUNNABLE) {
+		ctx->spu->stats.hash_flt++;
+		spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT);
+	}
+
 	/* we must not hold the lock when entering spu_handle_mm_fault */
 	spu_release(ctx);
 
@@ -192,7 +203,7 @@
 
 	/* hashing failed, so try the actual fault handler */
 	if (ret)
-		ret = spu_handle_mm_fault(current->mm, ea, dsisr);
+		ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
 
 	spu_acquire(ctx);
 	/*
@@ -201,11 +212,23 @@
 	 * In case of unhandled error report the problem to user space.
 	 */
 	if (!ret) {
+		if (flt == VM_FAULT_MINOR)
+			ctx->stats.min_flt++;
+		else
+			ctx->stats.maj_flt++;
+		if (ctx->state == SPU_STATE_RUNNABLE) {
+			if (flt == VM_FAULT_MINOR)
+				ctx->spu->stats.min_flt++;
+			else
+				ctx->spu->stats.maj_flt++;
+		}
+
 		if (ctx->spu)
 			ctx->ops->restart_dma(ctx);
 	} else
 		spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
 
+	spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(spufs_handle_class1);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index b1e7e2f..c2814ea 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -28,6 +28,7 @@
 #include <linux/pagemap.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
+#include <linux/seq_file.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>
@@ -39,6 +40,7 @@
 
 #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
 
+
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
 {
@@ -216,12 +218,12 @@
 #endif /* CONFIG_SPU_FS_64K_LS */
 
 static const struct file_operations spufs_mem_fops = {
-	.open	 		= spufs_mem_open,
-	.release 		= spufs_mem_release,
-	.read   		= spufs_mem_read,
-	.write   		= spufs_mem_write,
-	.llseek  		= generic_file_llseek,
-	.mmap    		= spufs_mem_mmap,
+	.open			= spufs_mem_open,
+	.release		= spufs_mem_release,
+	.read			= spufs_mem_read,
+	.write			= spufs_mem_write,
+	.llseek			= generic_file_llseek,
+	.mmap			= spufs_mem_mmap,
 #ifdef CONFIG_SPU_FS_64K_LS
 	.get_unmapped_area	= spufs_get_unmapped_area,
 #endif
@@ -1497,14 +1499,15 @@
 		if (status)
 			ret = status;
 	}
-	spu_release(ctx);
 
 	if (ret)
-		goto out;
+		goto out_unlock;
 
 	ctx->tagwait |= 1 << cmd.tag;
 	ret = size;
 
+out_unlock:
+	spu_release(ctx);
 out:
 	return ret;
 }
@@ -1515,14 +1518,14 @@
 	u32 free_elements, tagstatus;
 	unsigned int mask;
 
+	poll_wait(file, &ctx->mfc_wq, wait);
+
 	spu_acquire(ctx);
 	ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
 	free_elements = ctx->ops->get_mfc_free_elements(ctx);
 	tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
 	spu_release(ctx);
 
-	poll_wait(file, &ctx->mfc_wq, wait);
-
 	mask = 0;
 	if (free_elements & 0xffff)
 		mask |= POLLOUT | POLLWRNORM;
@@ -1797,6 +1800,29 @@
 	return 0;
 }
 
+static int spufs_caps_show(struct seq_file *s, void *private)
+{
+	struct spu_context *ctx = s->private;
+
+	if (!(ctx->flags & SPU_CREATE_NOSCHED))
+		seq_puts(s, "sched\n");
+	if (!(ctx->flags & SPU_CREATE_ISOLATE))
+		seq_puts(s, "step\n");
+	return 0;
+}
+
+static int spufs_caps_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_caps_fops = {
+	.open		= spufs_caps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
 			char __user *buf, size_t len, loff_t *pos)
 {
@@ -2014,7 +2040,105 @@
 	.read = spufs_proxydma_info_read,
 };
 
+static int spufs_show_tid(struct seq_file *s, void *private)
+{
+	struct spu_context *ctx = s->private;
+
+	seq_printf(s, "%d\n", ctx->tid);
+	return 0;
+}
+
+static int spufs_tid_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, spufs_show_tid, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_tid_fops = {
+	.open		= spufs_tid_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const char *ctx_state_names[] = {
+	"user", "system", "iowait", "loaded"
+};
+
+static unsigned long long spufs_acct_time(struct spu_context *ctx,
+		enum spuctx_execution_state state)
+{
+	unsigned long time = ctx->stats.times[state];
+
+	if (ctx->stats.execution_state == state)
+		time += jiffies - ctx->stats.tstamp;
+
+	return jiffies_to_msecs(time);
+}
+
+static unsigned long long spufs_slb_flts(struct spu_context *ctx)
+{
+	unsigned long long slb_flts = ctx->stats.slb_flt;
+
+	if (ctx->state == SPU_STATE_RUNNABLE) {
+		slb_flts += (ctx->spu->stats.slb_flt -
+			     ctx->stats.slb_flt_base);
+	}
+
+	return slb_flts;
+}
+
+static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
+{
+	unsigned long long class2_intrs = ctx->stats.class2_intr;
+
+	if (ctx->state == SPU_STATE_RUNNABLE) {
+		class2_intrs += (ctx->spu->stats.class2_intr -
+				 ctx->stats.class2_intr_base);
+	}
+
+	return class2_intrs;
+}
+
+
+static int spufs_show_stat(struct seq_file *s, void *private)
+{
+	struct spu_context *ctx = s->private;
+
+	spu_acquire(ctx);
+	seq_printf(s, "%s %llu %llu %llu %llu "
+		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+		ctx_state_names[ctx->stats.execution_state],
+		spufs_acct_time(ctx, SPUCTX_UTIL_USER),
+		spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM),
+		spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT),
+		spufs_acct_time(ctx, SPUCTX_UTIL_LOADED),
+		ctx->stats.vol_ctx_switch,
+		ctx->stats.invol_ctx_switch,
+		spufs_slb_flts(ctx),
+		ctx->stats.hash_flt,
+		ctx->stats.min_flt,
+		ctx->stats.maj_flt,
+		spufs_class2_intrs(ctx),
+		ctx->stats.libassist);
+	spu_release(ctx);
+	return 0;
+}
+
+static int spufs_stat_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_stat_fops = {
+	.open		= spufs_stat_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+
 struct tree_descr spufs_dir_contents[] = {
+	{ "capabilities", &spufs_caps_fops, 0444, },
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "regs", &spufs_regs_fops,  0666, },
 	{ "mbox", &spufs_mbox_fops, 0444, },
@@ -2046,10 +2170,13 @@
 	{ "wbox_info", &spufs_wbox_info_fops, 0444, },
 	{ "dma_info", &spufs_dma_info_fops, 0444, },
 	{ "proxydma_info", &spufs_proxydma_info_fops, 0444, },
+	{ "tid", &spufs_tid_fops, 0444, },
+	{ "stat", &spufs_stat_fops, 0444, },
 	{},
 };
 
 struct tree_descr spufs_dir_nosched_contents[] = {
+	{ "capabilities", &spufs_caps_fops, 0444, },
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "mbox", &spufs_mbox_fops, 0444, },
 	{ "ibox", &spufs_ibox_fops, 0444, },
@@ -2068,6 +2195,8 @@
 	{ "psmap", &spufs_psmap_fops, 0666, },
 	{ "phys-id", &spufs_id_ops, 0666, },
 	{ "object-id", &spufs_object_id_ops, 0666, },
+	{ "tid", &spufs_tid_fops, 0444, },
+	{ "stat", &spufs_stat_fops, 0444, },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 9807206..f37460e 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -232,10 +232,6 @@
 	return dcache_dir_close(inode, file);
 }
 
-const struct inode_operations spufs_dir_inode_operations = {
-	.lookup = simple_lookup,
-};
-
 const struct file_operations spufs_context_fops = {
 	.open		= dcache_dir_open,
 	.release	= spufs_dir_close,
@@ -269,7 +265,7 @@
 		goto out_iput;
 
 	ctx->flags = flags;
-	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	if (flags & SPU_CREATE_NOSCHED)
 		ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
@@ -386,7 +382,7 @@
 	if (!gang)
 		goto out_iput;
 
-	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 
 	d_instantiate(dentry, inode);
@@ -593,7 +589,7 @@
 	if (!inode)
 		goto out;
 
-	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	SPUFS_I(inode)->i_ctx = NULL;
 
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 5762660..58ae13b 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -29,7 +29,8 @@
 	spu = ctx->spu;
 	pte_fault = spu->dsisr &
 	    (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
-	return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
+	return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ?
+		1 : 0;
 }
 
 static int spu_setup_isolated(struct spu_context *ctx)
@@ -142,8 +143,11 @@
 			runcntl = SPU_RUNCNTL_RUNNABLE;
 		ctx->ops->runcntl_write(ctx, runcntl);
 	} else {
-		spu_start_tick(ctx);
+		unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
 		ctx->ops->npc_write(ctx, *npc);
+		if (test_thread_flag(TIF_SINGLESTEP))
+			mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
+		out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
 		ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
 	}
 
@@ -155,7 +159,6 @@
 {
 	int ret = 0;
 
-	spu_stop_tick(ctx);
 	*status = ctx->ops->status_read(ctx);
 	*npc = ctx->ops->npc_read(ctx);
 	spu_release(ctx);
@@ -298,9 +301,22 @@
 	ctx->ops->master_start(ctx);
 	ctx->event_return = 0;
 
-	ret = spu_acquire_runnable(ctx, 0);
-	if (ret)
-		return ret;
+	spu_acquire(ctx);
+	if (ctx->state == SPU_STATE_SAVED) {
+		__spu_update_sched_info(ctx);
+
+		ret = spu_activate(ctx, 0);
+		if (ret) {
+			spu_release(ctx);
+			goto out;
+		}
+	} else {
+		/*
+		 * We have to update the scheduling priority under active_mutex
+		 * to protect against find_victim().
+		 */
+		spu_update_sched_info(ctx);
+	}
 
 	ret = spu_run_init(ctx, npc);
 	if (ret) {
@@ -325,16 +341,20 @@
 
 		if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
 			ret = spu_reacquire_runnable(ctx, npc, &status);
-			if (ret) {
-				spu_stop_tick(ctx);
+			if (ret)
 				goto out2;
-			}
 			continue;
 		}
 		ret = spu_process_events(ctx);
 
 	} while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
-				      SPU_STATUS_STOPPED_BY_HALT)));
+				      SPU_STATUS_STOPPED_BY_HALT |
+				       SPU_STATUS_SINGLE_STEP)));
+
+	if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+	    (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) &&
+	    (ctx->state == SPU_STATE_RUNNABLE))
+		ctx->stats.libassist++;
 
 	ctx->ops->master_stop(ctx);
 	ret = spu_run_fini(ctx, npc, &status);
@@ -344,10 +364,15 @@
 	if ((ret == 0) ||
 	    ((ret == -ERESTARTSYS) &&
 	     ((status & SPU_STATUS_STOPPED_BY_HALT) ||
+	      (status & SPU_STATUS_SINGLE_STEP) ||
 	      ((status & SPU_STATUS_STOPPED_BY_STOP) &&
 	       (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
 		ret = status;
 
+	/* Note: we don't need to force_sig SIGTRAP on single-step
+	 * since we have TIF_SINGLESTEP set, thus the kernel will do
+	 * it upon return from the syscall anyawy
+	 */
 	if ((status & SPU_STATUS_STOPPED_BY_STOP)
 	    && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
 		force_sig(SIGTRAP, current);
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 3b831e0..e5b4dd1 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -35,6 +35,10 @@
 #include <linux/numa.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
+#include <linux/kthread.h>
+#include <linux/pid_namespace.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
@@ -43,54 +47,126 @@
 #include <asm/spu_priv1.h>
 #include "spufs.h"
 
-#define SPU_TIMESLICE	(HZ)
-
 struct spu_prio_array {
 	DECLARE_BITMAP(bitmap, MAX_PRIO);
 	struct list_head runq[MAX_PRIO];
 	spinlock_t runq_lock;
 	struct list_head active_list[MAX_NUMNODES];
 	struct mutex active_mutex[MAX_NUMNODES];
+	int nr_active[MAX_NUMNODES];
+	int nr_waiting;
 };
 
+static unsigned long spu_avenrun[3];
 static struct spu_prio_array *spu_prio;
-static struct workqueue_struct *spu_sched_wq;
+static struct task_struct *spusched_task;
+static struct timer_list spusched_timer;
 
-static inline int node_allowed(int node)
+/*
+ * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
+ */
+#define NORMAL_PRIO		120
+
+/*
+ * Frequency of the spu scheduler tick.  By default we do one SPU scheduler
+ * tick for every 10 CPU scheduler ticks.
+ */
+#define SPUSCHED_TICK		(10)
+
+/*
+ * These are the 'tuning knobs' of the scheduler:
+ *
+ * Minimum timeslice is 5 msecs (or 1 spu scheduler tick, whichever is
+ * larger), default timeslice is 100 msecs, maximum timeslice is 800 msecs.
+ */
+#define MIN_SPU_TIMESLICE	max(5 * HZ / (1000 * SPUSCHED_TICK), 1)
+#define DEF_SPU_TIMESLICE	(100 * HZ / (1000 * SPUSCHED_TICK))
+
+#define MAX_USER_PRIO		(MAX_PRIO - MAX_RT_PRIO)
+#define SCALE_PRIO(x, prio) \
+	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
+
+/*
+ * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values:
+ * [800ms ... 100ms ... 5ms]
+ *
+ * The higher a thread's priority, the bigger timeslices
+ * it gets during one round of execution. But even the lowest
+ * priority thread gets MIN_TIMESLICE worth of execution time.
+ */
+void spu_set_timeslice(struct spu_context *ctx)
 {
-	cpumask_t mask;
-
-	if (!nr_cpus_node(node))
-		return 0;
-	mask = node_to_cpumask(node);
-	if (!cpus_intersects(mask, current->cpus_allowed))
-		return 0;
-	return 1;
+	if (ctx->prio < NORMAL_PRIO)
+		ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio);
+	else
+		ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio);
 }
 
-void spu_start_tick(struct spu_context *ctx)
+/*
+ * Update scheduling information from the owning thread.
+ */
+void __spu_update_sched_info(struct spu_context *ctx)
 {
-	if (ctx->policy == SCHED_RR) {
-		/*
-		 * Make sure the exiting bit is cleared.
-		 */
-		clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
-		mb();
-		queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
-	}
+	/*
+	 * 32-Bit assignment are atomic on powerpc, and we don't care about
+	 * memory ordering here because retriving the controlling thread is
+	 * per defintion racy.
+	 */
+	ctx->tid = current->pid;
+
+	/*
+	 * We do our own priority calculations, so we normally want
+	 * ->static_prio to start with. Unfortunately thies field
+	 * contains junk for threads with a realtime scheduling
+	 * policy so we have to look at ->prio in this case.
+	 */
+	if (rt_prio(current->prio))
+		ctx->prio = current->prio;
+	else
+		ctx->prio = current->static_prio;
+	ctx->policy = current->policy;
+
+	/*
+	 * A lot of places that don't hold active_mutex poke into
+	 * cpus_allowed, including grab_runnable_context which
+	 * already holds the runq_lock.  So abuse runq_lock
+	 * to protect this field aswell.
+	 */
+	spin_lock(&spu_prio->runq_lock);
+	ctx->cpus_allowed = current->cpus_allowed;
+	spin_unlock(&spu_prio->runq_lock);
 }
 
-void spu_stop_tick(struct spu_context *ctx)
+void spu_update_sched_info(struct spu_context *ctx)
 {
-	if (ctx->policy == SCHED_RR) {
-		/*
-		 * While the work can be rearming normally setting this flag
-		 * makes sure it does not rearm itself anymore.
-		 */
-		set_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
-		mb();
-		cancel_delayed_work(&ctx->sched_work);
+	int node = ctx->spu->node;
+
+	mutex_lock(&spu_prio->active_mutex[node]);
+	__spu_update_sched_info(ctx);
+	mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
+static int __node_allowed(struct spu_context *ctx, int node)
+{
+	if (nr_cpus_node(node)) {
+		cpumask_t mask = node_to_cpumask(node);
+
+		if (cpus_intersects(mask, ctx->cpus_allowed))
+			return 1;
 	}
+
+	return 0;
+}
+
+static int node_allowed(struct spu_context *ctx, int node)
+{
+	int rval;
+
+	spin_lock(&spu_prio->runq_lock);
+	rval = __node_allowed(ctx, node);
+	spin_unlock(&spu_prio->runq_lock);
+
+	return rval;
 }
 
 /**
@@ -99,9 +175,18 @@
  */
 static void spu_add_to_active_list(struct spu *spu)
 {
-	mutex_lock(&spu_prio->active_mutex[spu->node]);
-	list_add_tail(&spu->list, &spu_prio->active_list[spu->node]);
-	mutex_unlock(&spu_prio->active_mutex[spu->node]);
+	int node = spu->node;
+
+	mutex_lock(&spu_prio->active_mutex[node]);
+	spu_prio->nr_active[node]++;
+	list_add_tail(&spu->list, &spu_prio->active_list[node]);
+	mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
+static void __spu_remove_from_active_list(struct spu *spu)
+{
+	list_del_init(&spu->list);
+	spu_prio->nr_active[spu->node]--;
 }
 
 /**
@@ -113,7 +198,7 @@
 	int node = spu->node;
 
 	mutex_lock(&spu_prio->active_mutex[node]);
-	list_del_init(&spu->list);
+	__spu_remove_from_active_list(spu);
 	mutex_unlock(&spu_prio->active_mutex[node]);
 }
 
@@ -144,6 +229,10 @@
 {
 	pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
 		 spu->number, spu->node);
+
+	ctx->stats.slb_flt_base = spu->stats.slb_flt;
+	ctx->stats.class2_intr_base = spu->stats.class2_intr;
+
 	spu->ctx = ctx;
 	spu->flags = 0;
 	ctx->spu = spu;
@@ -161,8 +250,8 @@
 	spu->timestamp = jiffies;
 	spu_cpu_affinity_set(spu, raw_smp_processor_id());
 	spu_switch_notify(spu, ctx);
-	spu_add_to_active_list(spu);
 	ctx->state = SPU_STATE_RUNNABLE;
+	spu_switch_state(spu, SPU_UTIL_SYSTEM);
 }
 
 /**
@@ -175,7 +264,8 @@
 	pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
 		 spu->pid, spu->number, spu->node);
 
-	spu_remove_from_active_list(spu);
+	spu_switch_state(spu, SPU_UTIL_IDLE);
+
 	spu_switch_notify(spu, NULL);
 	spu_unmap_mappings(ctx);
 	spu_save(&ctx->csa, spu);
@@ -192,6 +282,11 @@
 	ctx->spu = NULL;
 	spu->flags = 0;
 	spu->ctx = NULL;
+
+	ctx->stats.slb_flt +=
+		(spu->stats.slb_flt - ctx->stats.slb_flt_base);
+	ctx->stats.class2_intr +=
+		(spu->stats.class2_intr - ctx->stats.class2_intr_base);
 }
 
 /**
@@ -200,20 +295,39 @@
  */
 static void __spu_add_to_rq(struct spu_context *ctx)
 {
-	int prio = ctx->prio;
-
-	list_add_tail(&ctx->rq, &spu_prio->runq[prio]);
-	set_bit(prio, spu_prio->bitmap);
+	/*
+	 * Unfortunately this code path can be called from multiple threads
+	 * on behalf of a single context due to the way the problem state
+	 * mmap support works.
+	 *
+	 * Fortunately we need to wake up all these threads at the same time
+	 * and can simply skip the runqueue addition for every but the first
+	 * thread getting into this codepath.
+	 *
+	 * It's still quite hacky, and long-term we should proxy all other
+	 * threads through the owner thread so that spu_run is in control
+	 * of all the scheduling activity for a given context.
+	 */
+	if (list_empty(&ctx->rq)) {
+		list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
+		set_bit(ctx->prio, spu_prio->bitmap);
+		if (!spu_prio->nr_waiting++)
+			__mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+	}
 }
 
 static void __spu_del_from_rq(struct spu_context *ctx)
 {
 	int prio = ctx->prio;
 
-	if (!list_empty(&ctx->rq))
+	if (!list_empty(&ctx->rq)) {
+		if (!--spu_prio->nr_waiting)
+			del_timer(&spusched_timer);
 		list_del_init(&ctx->rq);
-	if (list_empty(&spu_prio->runq[prio]))
-		clear_bit(prio, spu_prio->bitmap);
+
+		if (list_empty(&spu_prio->runq[prio]))
+			clear_bit(prio, spu_prio->bitmap);
+	}
 }
 
 static void spu_prio_wait(struct spu_context *ctx)
@@ -244,7 +358,7 @@
 
 	for (n = 0; n < MAX_NUMNODES; n++, node++) {
 		node = (node < MAX_NUMNODES) ? node : 0;
-		if (!node_allowed(node))
+		if (!node_allowed(ctx, node))
 			continue;
 		spu = spu_alloc_node(node);
 		if (spu)
@@ -276,15 +390,15 @@
 	node = cpu_to_node(raw_smp_processor_id());
 	for (n = 0; n < MAX_NUMNODES; n++, node++) {
 		node = (node < MAX_NUMNODES) ? node : 0;
-		if (!node_allowed(node))
+		if (!node_allowed(ctx, node))
 			continue;
 
 		mutex_lock(&spu_prio->active_mutex[node]);
 		list_for_each_entry(spu, &spu_prio->active_list[node], list) {
 			struct spu_context *tmp = spu->ctx;
 
-			if (tmp->rt_priority < ctx->rt_priority &&
-			    (!victim || tmp->rt_priority < victim->rt_priority))
+			if (tmp->prio > ctx->prio &&
+			    (!victim || tmp->prio > victim->prio))
 				victim = spu->ctx;
 		}
 		mutex_unlock(&spu_prio->active_mutex[node]);
@@ -312,7 +426,10 @@
 				victim = NULL;
 				goto restart;
 			}
+			spu_remove_from_active_list(spu);
 			spu_unbind_context(spu, victim);
+			victim->stats.invol_ctx_switch++;
+			spu->stats.invol_ctx_switch++;
 			mutex_unlock(&victim->state_mutex);
 			/*
 			 * We need to break out of the wait loop in spu_run
@@ -338,22 +455,30 @@
  */
 int spu_activate(struct spu_context *ctx, unsigned long flags)
 {
-
-	if (ctx->spu)
-		return 0;
+	spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
 
 	do {
 		struct spu *spu;
 
+		/*
+		 * If there are multiple threads waiting for a single context
+		 * only one actually binds the context while the others will
+		 * only be able to acquire the state_mutex once the context
+		 * already is in runnable state.
+		 */
+		if (ctx->spu)
+			return 0;
+
 		spu = spu_get_idle(ctx);
 		/*
 		 * If this is a realtime thread we try to get it running by
 		 * preempting a lower priority thread.
 		 */
-		if (!spu && ctx->rt_priority)
+		if (!spu && rt_prio(ctx->prio))
 			spu = find_victim(ctx);
 		if (spu) {
 			spu_bind_context(spu, ctx);
+			spu_add_to_active_list(spu);
 			return 0;
 		}
 
@@ -369,23 +494,28 @@
  * Remove the highest priority context on the runqueue and return it
  * to the caller.  Returns %NULL if no runnable context was found.
  */
-static struct spu_context *grab_runnable_context(int prio)
+static struct spu_context *grab_runnable_context(int prio, int node)
 {
-	struct spu_context *ctx = NULL;
+	struct spu_context *ctx;
 	int best;
 
 	spin_lock(&spu_prio->runq_lock);
 	best = sched_find_first_bit(spu_prio->bitmap);
-	if (best < prio) {
+	while (best < prio) {
 		struct list_head *rq = &spu_prio->runq[best];
 
-		BUG_ON(list_empty(rq));
-
-		ctx = list_entry(rq->next, struct spu_context, rq);
-		__spu_del_from_rq(ctx);
+		list_for_each_entry(ctx, rq, rq) {
+			/* XXX(hch): check for affinity here aswell */
+			if (__node_allowed(ctx, node)) {
+				__spu_del_from_rq(ctx);
+				goto found;
+			}
+		}
+		best++;
 	}
+	ctx = NULL;
+ found:
 	spin_unlock(&spu_prio->runq_lock);
-
 	return ctx;
 }
 
@@ -395,9 +525,12 @@
 	struct spu_context *new = NULL;
 
 	if (spu) {
-		new = grab_runnable_context(max_prio);
+		new = grab_runnable_context(max_prio, spu->node);
 		if (new || force) {
+			spu_remove_from_active_list(spu);
 			spu_unbind_context(spu, ctx);
+			ctx->stats.vol_ctx_switch++;
+			spu->stats.vol_ctx_switch++;
 			spu_free(spu);
 			if (new)
 				wake_up(&new->stop_wq);
@@ -417,7 +550,17 @@
  */
 void spu_deactivate(struct spu_context *ctx)
 {
+	/*
+	 * We must never reach this for a nosched context,
+	 * but handle the case gracefull instead of panicing.
+	 */
+	if (ctx->flags & SPU_CREATE_NOSCHED) {
+		WARN_ON(1);
+		return;
+	}
+
 	__spu_deactivate(ctx, 1, MAX_PRIO);
+	spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
 }
 
 /**
@@ -432,56 +575,178 @@
 {
 	if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
 		mutex_lock(&ctx->state_mutex);
-		__spu_deactivate(ctx, 0, MAX_PRIO);
+		if (__spu_deactivate(ctx, 0, MAX_PRIO))
+			spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
+		else {
+			spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED);
+			spu_switch_state(ctx->spu, SPU_UTIL_USER);
+		}
 		mutex_unlock(&ctx->state_mutex);
 	}
 }
 
-void spu_sched_tick(struct work_struct *work)
+static void spusched_tick(struct spu_context *ctx)
 {
-	struct spu_context *ctx =
-		container_of(work, struct spu_context, sched_work.work);
-	int preempted;
-
-	/*
-	 * If this context is being stopped avoid rescheduling from the
-	 * scheduler tick because we would block on the state_mutex.
-	 * The caller will yield the spu later on anyway.
-	 */
-	if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
+	if (ctx->flags & SPU_CREATE_NOSCHED)
+		return;
+	if (ctx->policy == SCHED_FIFO)
 		return;
 
-	mutex_lock(&ctx->state_mutex);
-	preempted = __spu_deactivate(ctx, 0, ctx->prio + 1);
-	mutex_unlock(&ctx->state_mutex);
+	if (--ctx->time_slice)
+		return;
 
-	if (preempted) {
-		/*
-		 * We need to break out of the wait loop in spu_run manually
-		 * to ensure this context gets put on the runqueue again
-		 * ASAP.
-		 */
-		wake_up(&ctx->stop_wq);
+	/*
+	 * Unfortunately active_mutex ranks outside of state_mutex, so
+	 * we have to trylock here.  If we fail give the context another
+	 * tick and try again.
+	 */
+	if (mutex_trylock(&ctx->state_mutex)) {
+		struct spu *spu = ctx->spu;
+		struct spu_context *new;
+
+		new = grab_runnable_context(ctx->prio + 1, spu->node);
+		if (new) {
+
+			__spu_remove_from_active_list(spu);
+			spu_unbind_context(spu, ctx);
+			ctx->stats.invol_ctx_switch++;
+			spu->stats.invol_ctx_switch++;
+			spu_free(spu);
+			wake_up(&new->stop_wq);
+			/*
+			 * We need to break out of the wait loop in
+			 * spu_run manually to ensure this context
+			 * gets put on the runqueue again ASAP.
+			 */
+			wake_up(&ctx->stop_wq);
+		}
+		spu_set_timeslice(ctx);
+		mutex_unlock(&ctx->state_mutex);
 	} else {
-		spu_start_tick(ctx);
+		ctx->time_slice++;
 	}
 }
 
+/**
+ * count_active_contexts - count nr of active tasks
+ *
+ * Return the number of tasks currently running or waiting to run.
+ *
+ * Note that we don't take runq_lock / active_mutex here.  Reading
+ * a single 32bit value is atomic on powerpc, and we don't care
+ * about memory ordering issues here.
+ */
+static unsigned long count_active_contexts(void)
+{
+	int nr_active = 0, node;
+
+	for (node = 0; node < MAX_NUMNODES; node++)
+		nr_active += spu_prio->nr_active[node];
+	nr_active += spu_prio->nr_waiting;
+
+	return nr_active;
+}
+
+/**
+ * spu_calc_load - given tick count, update the avenrun load estimates.
+ * @tick:	tick count
+ *
+ * No locking against reading these values from userspace, as for
+ * the CPU loadavg code.
+ */
+static void spu_calc_load(unsigned long ticks)
+{
+	unsigned long active_tasks; /* fixed-point */
+	static int count = LOAD_FREQ;
+
+	count -= ticks;
+
+	if (unlikely(count < 0)) {
+		active_tasks = count_active_contexts() * FIXED_1;
+		do {
+			CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
+			CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
+			CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
+			count += LOAD_FREQ;
+		} while (count < 0);
+	}
+}
+
+static void spusched_wake(unsigned long data)
+{
+	mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+	wake_up_process(spusched_task);
+	spu_calc_load(SPUSCHED_TICK);
+}
+
+static int spusched_thread(void *unused)
+{
+	struct spu *spu, *next;
+	int node;
+
+	while (!kthread_should_stop()) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		for (node = 0; node < MAX_NUMNODES; node++) {
+			mutex_lock(&spu_prio->active_mutex[node]);
+			list_for_each_entry_safe(spu, next,
+						 &spu_prio->active_list[node],
+						 list)
+				spusched_tick(spu->ctx);
+			mutex_unlock(&spu_prio->active_mutex[node]);
+		}
+	}
+
+	return 0;
+}
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+static int show_spu_loadavg(struct seq_file *s, void *private)
+{
+	int a, b, c;
+
+	a = spu_avenrun[0] + (FIXED_1/200);
+	b = spu_avenrun[1] + (FIXED_1/200);
+	c = spu_avenrun[2] + (FIXED_1/200);
+
+	/*
+	 * Note that last_pid doesn't really make much sense for the
+	 * SPU loadavg (it even seems very odd on the CPU side..),
+	 * but we include it here to have a 100% compatible interface.
+	 */
+	seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
+		LOAD_INT(a), LOAD_FRAC(a),
+		LOAD_INT(b), LOAD_FRAC(b),
+		LOAD_INT(c), LOAD_FRAC(c),
+		count_active_contexts(),
+		atomic_read(&nr_spu_contexts),
+		current->nsproxy->pid_ns->last_pid);
+	return 0;
+}
+
+static int spu_loadavg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_spu_loadavg, NULL);
+}
+
+static const struct file_operations spu_loadavg_fops = {
+	.open		= spu_loadavg_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 int __init spu_sched_init(void)
 {
-	int i;
-
-	spu_sched_wq = create_singlethread_workqueue("spusched");
-	if (!spu_sched_wq)
-		return 1;
+	struct proc_dir_entry *entry;
+	int err = -ENOMEM, i;
 
 	spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
-	if (!spu_prio) {
-		printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
-		       __FUNCTION__);
-		       destroy_workqueue(spu_sched_wq);
-		return 1;
-	}
+	if (!spu_prio)
+		goto out;
+
 	for (i = 0; i < MAX_PRIO; i++) {
 		INIT_LIST_HEAD(&spu_prio->runq[i]);
 		__clear_bit(i, spu_prio->bitmap);
@@ -492,7 +757,30 @@
 		INIT_LIST_HEAD(&spu_prio->active_list[i]);
 	}
 	spin_lock_init(&spu_prio->runq_lock);
+
+	setup_timer(&spusched_timer, spusched_wake, 0);
+
+	spusched_task = kthread_run(spusched_thread, NULL, "spusched");
+	if (IS_ERR(spusched_task)) {
+		err = PTR_ERR(spusched_task);
+		goto out_free_spu_prio;
+	}
+
+	entry = create_proc_entry("spu_loadavg", 0, NULL);
+	if (!entry)
+		goto out_stop_kthread;
+	entry->proc_fops = &spu_loadavg_fops;
+
+	pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n",
+			SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE);
 	return 0;
+
+ out_stop_kthread:
+	kthread_stop(spusched_task);
+ out_free_spu_prio:
+	kfree(spu_prio);
+ out:
+	return err;
 }
 
 void __exit spu_sched_exit(void)
@@ -500,6 +788,11 @@
 	struct spu *spu, *tmp;
 	int node;
 
+	remove_proc_entry("spu_loadavg", NULL);
+
+	del_timer_sync(&spusched_timer);
+	kthread_stop(spusched_task);
+
 	for (node = 0; node < MAX_NUMNODES; node++) {
 		mutex_lock(&spu_prio->active_mutex[node]);
 		list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node],
@@ -510,5 +803,4 @@
 		mutex_unlock(&spu_prio->active_mutex[node]);
 	}
 	kfree(spu_prio);
-	destroy_workqueue(spu_sched_wq);
 }
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore.c b/arch/powerpc/platforms/cell/spufs/spu_restore.c
index 0bf723d..4e19ed7 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_restore.c
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore.c
@@ -296,7 +296,7 @@
  * This code deviates from the documented sequence in the
  * following aspects:
  *
- * 	1. The EA for LSCSA is passed from PPE in the
+ *	1. The EA for LSCSA is passed from PPE in the
  *	   signal notification channels.
  *	2. The register spill area is pulled by SPU
  *	   into LS, rather than pushed by PPE.
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save.c b/arch/powerpc/platforms/cell/spufs/spu_save.c
index 196033b..ae95cc1 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_save.c
+++ b/arch/powerpc/platforms/cell/spufs/spu_save.c
@@ -44,7 +44,7 @@
 	 *    Read the SPU_RdEventMsk channel and save to the LSCSA.
 	 */
 	offset = LSCSA_QW_OFFSET(event_mask);
-	regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask);
+	regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask);
 }
 
 static inline void save_tag_mask(void)
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 47617e8..08b3530 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/fs.h>
+#include <linux/cpumask.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
@@ -39,9 +40,17 @@
 struct spu_context_ops;
 struct spu_gang;
 
-/* ctx->sched_flags */
-enum {
-	SPU_SCHED_EXITING = 0,
+/*
+ * This is the state for spu utilization reporting to userspace.
+ * Because this state is visible to userspace it must never change and needs
+ * to be kept strictly separate from any internal state kept by the kernel.
+ */
+enum spuctx_execution_state {
+	SPUCTX_UTIL_USER = 0,
+	SPUCTX_UTIL_SYSTEM,
+	SPUCTX_UTIL_IOWAIT,
+	SPUCTX_UTIL_LOADED,
+	SPUCTX_UTIL_MAX
 };
 
 struct spu_context {
@@ -81,13 +90,34 @@
 	struct list_head gang_list;
 	struct spu_gang *gang;
 
+	/* owner thread */
+	pid_t tid;
+
 	/* scheduler fields */
- 	struct list_head rq;
-	struct delayed_work sched_work;
+	struct list_head rq;
+	unsigned int time_slice;
 	unsigned long sched_flags;
-	unsigned long rt_priority;
+	cpumask_t cpus_allowed;
 	int policy;
 	int prio;
+
+	/* statistics */
+	struct {
+		/* updates protected by ctx->state_mutex */
+		enum spuctx_execution_state execution_state;
+		unsigned long tstamp;		/* time of last ctx switch */
+		unsigned long times[SPUCTX_UTIL_MAX];
+		unsigned long long vol_ctx_switch;
+		unsigned long long invol_ctx_switch;
+		unsigned long long min_flt;
+		unsigned long long maj_flt;
+		unsigned long long hash_flt;
+		unsigned long long slb_flt;
+		unsigned long long slb_flt_base; /* # at last ctx switch */
+		unsigned long long class2_intr;
+		unsigned long long class2_intr_base; /* # at last ctx switch */
+		unsigned long long libassist;
+	} stats;
 };
 
 struct spu_gang {
@@ -177,6 +207,7 @@
 int spufs_handle_class1(struct spu_context *ctx);
 
 /* context management */
+extern atomic_t nr_spu_contexts;
 static inline void spu_acquire(struct spu_context *ctx)
 {
 	mutex_lock(&ctx->state_mutex);
@@ -200,9 +231,9 @@
 int spu_activate(struct spu_context *ctx, unsigned long flags);
 void spu_deactivate(struct spu_context *ctx);
 void spu_yield(struct spu_context *ctx);
-void spu_start_tick(struct spu_context *ctx);
-void spu_stop_tick(struct spu_context *ctx);
-void spu_sched_tick(struct work_struct *work);
+void spu_set_timeslice(struct spu_context *ctx);
+void spu_update_sched_info(struct spu_context *ctx);
+void __spu_update_sched_info(struct spu_context *ctx);
 int __init spu_sched_init(void);
 void __exit spu_sched_exit(void);
 
@@ -210,7 +241,7 @@
 
 /*
  * spufs_wait
- * 	Same as wait_event_interruptible(), except that here
+ *	Same as wait_event_interruptible(), except that here
  *	we need to call spu_release(ctx) before sleeping, and
  *	then spu_acquire(ctx) when awoken.
  */
@@ -256,4 +287,37 @@
 extern struct spufs_coredump_reader spufs_coredump_read[];
 extern int spufs_coredump_num_notes;
 
+/*
+ * This function is a little bit too large for an inline, but
+ * as fault.c is built into the kernel we can't move it out of
+ * line.
+ */
+static inline void spuctx_switch_state(struct spu_context *ctx,
+		enum spuctx_execution_state new_state)
+{
+	WARN_ON(!mutex_is_locked(&ctx->state_mutex));
+
+	if (ctx->stats.execution_state != new_state) {
+		unsigned long curtime = jiffies;
+
+		ctx->stats.times[ctx->stats.execution_state] +=
+				 curtime - ctx->stats.tstamp;
+		ctx->stats.tstamp = curtime;
+		ctx->stats.execution_state = new_state;
+	}
+}
+
+static inline void spu_switch_state(struct spu *spu,
+		enum spuctx_execution_state new_state)
+{
+	if (spu->stats.utilization_state != new_state) {
+		unsigned long curtime = jiffies;
+
+		spu->stats.times[spu->stats.utilization_state] +=
+				 curtime - spu->stats.tstamp;
+		spu->stats.tstamp = curtime;
+		spu->stats.utilization_state = new_state;
+	}
+}
+
 #endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 71a0b41..9c506ba 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -70,7 +70,7 @@
   }
 #endif				/* debug */
 
-#define POLL_WHILE_FALSE(_c) 	POLL_WHILE_TRUE(!(_c))
+#define POLL_WHILE_FALSE(_c)	POLL_WHILE_TRUE(!(_c))
 
 static inline void acquire_spu_lock(struct spu *spu)
 {
@@ -387,6 +387,19 @@
 	csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW);
 }
 
+static inline void save_ppu_tagstatus(struct spu_state *csa, struct spu *spu)
+{
+	struct spu_problem __iomem *prob = spu->problem;
+
+	/* Save the Prxy_TagStatus register in the CSA.
+	 *
+	 * It is unnecessary to restore dma_tagstatus_R, however,
+	 * dma_tagstatus_R in the CSA is accessed via backing_ops, so
+	 * we must save it.
+	 */
+	csa->prob.dma_tagstatus_R = in_be32(&prob->dma_tagstatus_R);
+}
+
 static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -1812,6 +1825,7 @@
 	save_mfc_queues(prev, spu);	/* Step 19. */
 	save_ppu_querymask(prev, spu);	/* Step 20. */
 	save_ppu_querytype(prev, spu);	/* Step 21. */
+	save_ppu_tagstatus(prev, spu);  /* NEW.     */
 	save_mfc_csr_tsq(prev, spu);	/* Step 22. */
 	save_mfc_csr_cmd(prev, spu);	/* Step 23. */
 	save_mfc_csr_ato(prev, spu);	/* Step 24. */
@@ -1930,7 +1944,7 @@
 	reset_spu_privcntl(prev, spu);	        /* Step 16. */
 	reset_spu_lslr(prev, spu);              /* Step 17. */
 	setup_mfc_sr1(prev, spu);	        /* Step 18. */
-	spu_invalidate_slbs(spu);        	/* Step 19. */
+	spu_invalidate_slbs(spu);		/* Step 19. */
 	reset_ch_part1(prev, spu);	        /* Step 20. */
 	reset_ch_part2(prev, spu);	        /* Step 21. */
 	enable_interrupts(prev, spu);	        /* Step 22. */
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
index d2c6905..22b4b4e 100644
--- a/arch/powerpc/platforms/chrp/Kconfig
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -8,4 +8,5 @@
 	select PPC_MPC106
 	select PPC_UDBG_16550
 	select PPC_NATIVE
+	select PCI
 	default y
diff --git a/arch/powerpc/platforms/chrp/Makefile b/arch/powerpc/platforms/chrp/Makefile
index 902feb1..4b3bfad 100644
--- a/arch/powerpc/platforms/chrp/Makefile
+++ b/arch/powerpc/platforms/chrp/Makefile
@@ -1,4 +1,3 @@
-obj-y				+= setup.o time.o pegasos_eth.o
-obj-$(CONFIG_PCI)		+= pci.o
+obj-y				+= setup.o time.o pegasos_eth.o pci.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_NVRAM)		+= nvram.o
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index d32fedc..3690624 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -99,7 +99,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 		| (((bus->number - hose->first_busno) & 0xff) << 16)
-		| (hose->index << 24);
+		| (hose->global_number << 24);
         int ret = -1;
 	int rval;
 
@@ -114,7 +114,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 		| (((bus->number - hose->first_busno) & 0xff) << 16)
-		| (hose->index << 24);
+		| (hose->global_number << 24);
 	int rval;
 
 	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -254,13 +254,12 @@
 			printk(" at %llx", (unsigned long long)r.start);
 		printk("\n");
 
-		hose = pcibios_alloc_controller();
+		hose = pcibios_alloc_controller(dev);
 		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];
 
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index f2d2626..bec7726 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -28,6 +28,7 @@
 	bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)"
 	select TSI108_BRIDGE
 	select PPC_UDBG_16550
+	select WANT_DEVICE_TREE
 	help
 	  Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
 	  Board with TSI108/9 bridge (Hickory/Holly)
@@ -44,6 +45,7 @@
 config TSI108_BRIDGE
 	bool
 	depends on MPC7448HPC2 || PPC_HOLLY
+	select PCI
 	select MPIC
 	select MPIC_WEIRD
 	default y
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index 3a0b4a0..6292e36 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -45,7 +45,7 @@
 
 #define HOLLY_PCI_CFG_PHYS 0x7c000000
 
-int holly_exclude_device(u_char bus, u_char devfn)
+int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index b412f00..f4d0a7a 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -54,8 +54,9 @@
 	},
 };
 
-static int __init add_bridge(struct device_node *dev)
+static int __init linkstation_add_bridge(struct device_node *dev)
 {
+#ifdef CONFIG_PCI
 	int len;
 	struct pci_controller *hose;
 	const int *bus_range;
@@ -67,18 +68,17 @@
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 				" bus 0\n", dev->full_name);
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(dev);
 	if (hose == NULL)
 		return -ENOMEM;
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
-	hose->arch_data = dev;
 	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
 
 	/* Interpret the "ranges" property */
 	/* This also maps the I/O region and sets isa_io/mem_base */
 	pci_process_bridge_OF_ranges(hose, dev, 1);
-
+#endif
 	return 0;
 }
 
@@ -92,7 +92,7 @@
 
 	/* Lookup PCI host bridges */
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		linkstation_add_bridge(np);
 
 	printk(KERN_INFO "BUFFALO Network Attached Storage Series\n");
 	printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n");
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index 4542e0c8..1e3cc69 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -54,15 +54,10 @@
 
 #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
 
-#ifndef CONFIG_PCI
-isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
-isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
-pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
-#endif
-
 extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
 
-int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
+int mpc7448_hpc2_exclude_device(struct pci_controller *hose,
+				u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
index a543a52..f7e0e0c 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
@@ -18,9 +18,4 @@
 
 #include <asm/ppcboot.h>
 
-/* Base Addresses for the PCI bus
- */
-#define MPC7448_HPC2_PCI_MEM_OFFSET	(0x00000000)
-#define MPC7448_HPC2_ISA_IO_BASE	(0x00000000)
-#define MPC7448_HPC2_ISA_MEM_BASE	(0x00000000)
 #endif				/* __PPC_PLATFORMS_MPC7448_HPC2_H */
diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h
index a843b0f..8d95fe4b 100644
--- a/arch/powerpc/platforms/iseries/call_hpt.h
+++ b/arch/powerpc/platforms/iseries/call_hpt.h
@@ -76,24 +76,25 @@
 	return compressedStatus;
 }
 
-static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
+static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
 {
 	return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
 }
 
-static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
+static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
 		u8 bitson, u8 bitsoff)
 {
 	return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
 			bitson, bitsoff);
 }
 
-static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
+static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
 {
 	HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
 }
 
-static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
+					 struct hash_pte *hpte)
 {
 	HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
 }
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
index ed44dfc..b4e2c7a 100644
--- a/arch/powerpc/platforms/iseries/htab.c
+++ b/arch/powerpc/platforms/iseries/htab.c
@@ -44,7 +44,7 @@
 			 unsigned long vflags, int psize)
 {
 	long slot;
-	hpte_t lhpte;
+	struct hash_pte lhpte;
 	int secondary = 0;
 
 	BUG_ON(psize != MMU_PAGE_4K);
@@ -99,7 +99,7 @@
 
 static unsigned long iSeries_hpte_getword0(unsigned long slot)
 {
-	hpte_t hpte;
+	struct hash_pte hpte;
 
 	HvCallHpt_get(&hpte, slot);
 	return hpte.v;
@@ -144,7 +144,7 @@
 static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
 				  unsigned long va, int psize, int local)
 {
-	hpte_t hpte;
+	struct hash_pte hpte;
 	unsigned long want_v;
 
 	iSeries_hlock(slot);
@@ -176,7 +176,7 @@
  */
 static long iSeries_hpte_find(unsigned long vpn)
 {
-	hpte_t hpte;
+	struct hash_pte hpte;
 	long slot;
 
 	/*
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 9c97422..da87162 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -742,6 +742,11 @@
 	/* Install IO hooks */
 	ppc_pci_io = iseries_pci_io;
 
+	/* iSeries has no IO space in the common sense, it needs to set
+	 * the IO base to 0
+	 */
+	pci_io_base = 0;
+
 	if (root == NULL) {
 		printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
 				"of device tree\n");
@@ -763,7 +768,7 @@
 		if (phb == NULL)
 			continue;
 
-		phb->pci_mem_offset = phb->local_number = bus;
+		phb->pci_mem_offset = bus;
 		phb->first_busno = bus;
 		phb->last_busno = bus;
 		phb->ops = &iSeries_pci_ops;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 7f5dcee..13a8b19 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -79,8 +79,6 @@
 static void iSeries_pci_final_fixup(void) { }
 #endif
 
-extern unsigned long iSeries_recal_tb;
-extern unsigned long iSeries_recal_titan;
 
 struct MemoryBlock {
 	unsigned long absStart;
@@ -292,8 +290,8 @@
 {
 	DBG(" -> iSeries_init_early()\n");
 
-	iSeries_recal_tb = get_tb();
-	iSeries_recal_titan = HvCallXm_loadTod();
+	/* Snapshot the timebase, for use in later recalibration */
+	iSeries_time_init_early();
 
 	/*
 	 * Initialize the DMA/TCE management
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 7aaa5bb..fceaae4 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -444,7 +444,7 @@
 	u3_ht = hose;
 }
 
-static int __init add_bridge(struct device_node *dev)
+static int __init maple_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -519,23 +519,6 @@
 	DBG(" <- maple_pci_irq_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: %llx; io end: %llx\n",
-		       hose->global_number,
-		       (unsigned long long)hose->io_resource.start,
-		       (unsigned long long)hose->io_resource.end);
-	}
-}
-
 void __init maple_pci_init(void)
 {
 	struct device_node *np, *root;
@@ -558,7 +541,7 @@
 			continue;
 		if ((of_device_is_compatible(np, "u4-pcie") ||
 		     of_device_is_compatible(np, "u3-agp")) &&
-		    add_bridge(np) == 0)
+		    maple_add_bridge(np) == 0)
 			of_node_get(np);
 
 		if (of_device_is_compatible(np, "u3-ht")) {
@@ -570,27 +553,9 @@
 
 	/* Now setup the HyperTransport host if we found any
 	 */
-	if (ht && add_bridge(ht) != 0)
+	if (ht && maple_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);
-        if (u4_pcie)
-                pci_setup_phb_io(u4_pcie, 0);
-
-	/* 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();
 
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 7c5076e..95cd90f 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -25,4 +25,13 @@
 	help
 	  Driver for MDIO via GPIO on PWRficient platforms
 
+config ELECTRA_IDE
+      tristate "Electra IDE driver"
+      default y
+      depends on PPC_PASEMI && ATA
+      select PATA_PLATFORM
+      help
+	This includes driver support for the Electra on-board IDE
+	interface.
+
 endmenu
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile
index 2cd2a4f..f47fcac 100644
--- a/arch/powerpc/platforms/pasemi/Makefile
+++ b/arch/powerpc/platforms/pasemi/Makefile
@@ -1,3 +1,4 @@
 obj-y	+= setup.o pci.o time.o idle.o powersave.o iommu.o
 obj-$(CONFIG_PPC_PASEMI_MDIO)	+= gpio_mdio.o
+obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
 obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c
new file mode 100644
index 0000000..12fb0c9
--- /dev/null
+++ b/arch/powerpc/platforms/pasemi/electra_ide.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.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.
+ *
+ * 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/platform_device.h>
+
+#include <asm/prom.h>
+#include <asm/system.h>
+
+/* The electra IDE interface is incredibly simple: Just a device on the localbus
+ * with interrupts hooked up to one of the GPIOs. The device tree contains the
+ * address window and interrupt mappings already, and the pata_platform driver handles
+ * the rest. We just need to hook the two up.
+ */
+
+#define MAX_IFS	4	/* really, we have only one */
+
+static struct platform_device *pdevs[MAX_IFS];
+
+static int __devinit electra_ide_init(void)
+{
+	struct device_node *np;
+	struct resource r[3];
+	int ret = 0;
+	int i;
+
+	np = of_find_compatible_node(NULL, "ide", "electra-ide");
+	i = 0;
+
+	while (np && i < MAX_IFS) {
+		memset(r, 0, sizeof(r));
+
+		/* pata_platform wants two address ranges: one for the base registers,
+		 * another for the control (altstatus). It's located at offset 0x3f6 in
+		 * the window, but the device tree only has one large register window
+		 * that covers both ranges. So we need to split it up by hand here:
+		 */
+
+		ret = of_address_to_resource(np, 0, &r[0]);
+		if (ret)
+			goto out;
+		ret = of_address_to_resource(np, 0, &r[1]);
+		if (ret)
+			goto out;
+
+		r[1].start += 0x3f6;
+		r[0].end = r[1].start-1;
+
+		r[2].start = irq_of_parse_and_map(np, 0);
+		r[2].end = irq_of_parse_and_map(np, 0);
+		r[2].flags = IORESOURCE_IRQ;
+
+		pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
+			 r[0].start, r[1].start, r[2].start);
+		pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
+		if (IS_ERR(pdevs[i])) {
+			ret = PTR_ERR(pdevs[i]);
+			pdevs[i] = NULL;
+			goto out;
+		}
+		np = of_find_compatible_node(np, "ide", "electra-ide");
+	}
+out:
+	return ret;
+}
+module_init(electra_ide_init);
+
+static void __devexit electra_ide_exit(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_IFS; i++)
+		if (pdevs[i])
+			platform_device_unregister(pdevs[i]);
+}
+module_exit(electra_ide_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra IDE driver");
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index bbc6dfc..ab1f5f6 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -132,7 +132,7 @@
 	hose->cfg_data = ioremap(0xe0000000, 0x10000000);
 }
 
-static int __init add_bridge(struct device_node *dev)
+static int __init pas_add_bridge(struct device_node *dev)
 {
 	struct pci_controller *hose;
 
@@ -150,29 +150,11 @@
 	printk(KERN_INFO "Found PA-PXP PCI host bridge.\n");
 
 	/* Interpret the "ranges" property */
-	/* This also maps the I/O region and sets isa_io/mem_base */
 	pci_process_bridge_OF_ranges(hose, dev, 1);
-	pci_setup_phb_io(hose, 1);
 
 	return 0;
 }
 
-
-static void __init pas_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 pas_pci_init(void)
 {
 	struct device_node *np, *root;
@@ -185,13 +167,11 @@
 	}
 
 	for (np = NULL; (np = of_get_next_child(root, np)) != NULL;)
-		if (np->name && !strcmp(np->name, "pxp") && !add_bridge(np))
+		if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np))
 			of_node_get(np);
 
 	of_node_put(root);
 
-	pas_fixup_phb_resources();
-
 	/* Setup the linkage between OF nodes and PHBs */
 	pci_devs_phb_init();
 
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index c5a3f61..ffe6528 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -239,7 +239,7 @@
 	return 1;
 }
 
-define_machine(pas) {
+define_machine(pasemi) {
 	.name			= "PA Semi PA6T-1682M",
 	.probe			= pas_probe,
 	.setup_arch		= pas_setup_arch,
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
index 5b7afe5..055990c 100644
--- a/arch/powerpc/platforms/powermac/Kconfig
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -2,6 +2,7 @@
 	bool "Apple PowerMac based machines"
 	depends on PPC_MULTIPLATFORM
 	select MPIC
+	select PCI
 	select PPC_INDIRECT_PCI if PPC32
 	select PPC_MPC106 if PPC32
 	select PPC_NATIVE
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 3f507ab..efdf5eb 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -42,6 +42,7 @@
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/timer.h>
+#include <linux/mutex.h>
 #include <asm/keylargo.h>
 #include <asm/uninorth.h>
 #include <asm/io.h>
@@ -84,7 +85,7 @@
 	void			*hostdata;
 	int			channel;	/* some hosts have multiple */
 	int			mode;		/* current mode */
-	struct semaphore	sem;
+	struct mutex		mutex;
 	int			opened;
 	int			polled;		/* open mode */
 	struct platform_device	*platform_dev;
@@ -104,7 +105,7 @@
 
 struct pmac_i2c_host_kw
 {
-	struct semaphore	mutex;		/* Access mutex for use by
+	struct mutex		mutex;		/* Access mutex for use by
 						 * i2c-keywest */
 	void __iomem		*base;		/* register base address */
 	int			bsteps;		/* register stepping */
@@ -375,14 +376,14 @@
 static int kw_i2c_open(struct pmac_i2c_bus *bus)
 {
 	struct pmac_i2c_host_kw *host = bus->hostdata;
-	down(&host->mutex);
+	mutex_lock(&host->mutex);
 	return 0;
 }
 
 static void kw_i2c_close(struct pmac_i2c_bus *bus)
 {
 	struct pmac_i2c_host_kw *host = bus->hostdata;
-	up(&host->mutex);
+	mutex_unlock(&host->mutex);
 }
 
 static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
@@ -498,7 +499,7 @@
 		kfree(host);
 		return NULL;
 	}
-	init_MUTEX(&host->mutex);
+	mutex_init(&host->mutex);
 	init_completion(&host->complete);
 	spin_lock_init(&host->lock);
 	init_timer(&host->timeout_timer);
@@ -571,7 +572,7 @@
 	bus->open = kw_i2c_open;
 	bus->close = kw_i2c_close;
 	bus->xfer = kw_i2c_xfer;
-	init_MUTEX(&bus->sem);
+	mutex_init(&bus->mutex);
 	if (controller == busnode)
 		bus->flags = pmac_i2c_multibus;
 	list_add(&bus->link, &pmac_i2c_busses);
@@ -798,7 +799,7 @@
 		bus->mode = pmac_i2c_mode_std;
 		bus->hostdata = bus + 1;
 		bus->xfer = pmu_i2c_xfer;
-		init_MUTEX(&bus->sem);
+		mutex_init(&bus->mutex);
 		bus->flags = pmac_i2c_multibus;
 		list_add(&bus->link, &pmac_i2c_busses);
 
@@ -921,7 +922,7 @@
 		bus->mode = pmac_i2c_mode_std;
 		bus->hostdata = bus + 1;
 		bus->xfer = smu_i2c_xfer;
-		init_MUTEX(&bus->sem);
+		mutex_init(&bus->mutex);
 		bus->flags = 0;
 		list_add(&bus->link, &pmac_i2c_busses);
 
@@ -1093,13 +1094,13 @@
 {
 	int rc;
 
-	down(&bus->sem);
+	mutex_lock(&bus->mutex);
 	bus->polled = polled || pmac_i2c_force_poll;
 	bus->opened = 1;
 	bus->mode = pmac_i2c_mode_std;
 	if (bus->open && (rc = bus->open(bus)) != 0) {
 		bus->opened = 0;
-		up(&bus->sem);
+		mutex_unlock(&bus->mutex);
 		return rc;
 	}
 	return 0;
@@ -1112,7 +1113,7 @@
 	if (bus->close)
 		bus->close(bus);
 	bus->opened = 0;
-	up(&bus->sem);
+	mutex_unlock(&bus->mutex);
 }
 EXPORT_SYMBOL_GPL(pmac_i2c_close);
 
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index c4af9e2..92586db 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -35,8 +35,6 @@
 #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;
@@ -897,7 +895,7 @@
  * "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)
+static int __init pmac_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -918,15 +916,9 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	/* XXX Different prototypes, to be merged */
-#ifdef CONFIG_PPC64
 	hose = pcibios_alloc_controller(dev);
-#else
-	hose = pcibios_alloc_controller();
-#endif
 	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;
 
@@ -1006,19 +998,6 @@
 #endif /* CONFIG_PPC32 */
 }
 
-#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;
@@ -1036,7 +1015,7 @@
 		if (strcmp(np->name, "bandit") == 0
 		    || strcmp(np->name, "chaos") == 0
 		    || strcmp(np->name, "pci") == 0) {
-			if (add_bridge(np) == 0)
+			if (pmac_add_bridge(np) == 0)
 				of_node_get(np);
 		}
 		if (strcmp(np->name, "ht") == 0) {
@@ -1050,28 +1029,9 @@
 	/* Probe HT last as it relies on the agp resources to be already
 	 * setup
 	 */
-	if (ht && add_bridge(ht) != 0)
+	if (ht && pmac_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);
-	if (u4_pcie)
-		pci_setup_phb_io(u4_pcie, 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();
 
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 40f0008..a05079b 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -7,6 +7,7 @@
 	select USB_OHCI_BIG_ENDIAN_MMIO
 	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_BIG_ENDIAN_MMIO
+	select MEMORY_HOTPLUG
 	help
 	  This option enables support for the Sony PS3 game console
 	  and other platforms using the PS3 hypervisor.
@@ -73,18 +74,12 @@
 
 config PS3_VUART
 	depends on PPC_PS3
-	bool "PS3 Virtual UART support" if PS3_ADVANCED
-	default y
-	help
-	  Include support for the PS3 Virtual UART.
-
-	  This support is required for several system services
-	  including the System Manager and AV Settings.  In
-	  general, all users will say Y.
+	tristate
 
 config PS3_PS3AV
+	depends on PPC_PS3
 	tristate "PS3 AV settings driver" if PS3_ADVANCED
-	depends on PS3_VUART
+	select PS3_VUART
 	default y
 	help
 	  Include support for the PS3 AV Settings driver.
@@ -93,13 +88,18 @@
 	  general, all users will say Y or M.
 
 config PS3_SYS_MANAGER
-	bool "PS3 System Manager driver" if PS3_ADVANCED
-	depends on PS3_VUART
-	default y
+	depends on PPC_PS3
+	tristate "PS3 System Manager driver" if PS3_ADVANCED
+	select PS3_VUART
+	default m
 	help
 	  Include support for the PS3 System Manager.
 
 	  This support is required for system control.  In
-	  general, all users will say Y.
+	  general, all users will say Y or M.
+
+config PS3_STORAGE
+	depends on PPC_PS3
+	tristate
 
 endmenu
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile
index a0048fc..ac1bdf8 100644
--- a/arch/powerpc/platforms/ps3/Makefile
+++ b/arch/powerpc/platforms/ps3/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
+obj-y += device-init.o
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
new file mode 100644
index 0000000..825ebb2
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -0,0 +1,785 @@
+/*
+ *  PS3 device registration routines.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony 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; version 2 of the License.
+ *
+ *  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/delay.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+
+#include <asm/firmware.h>
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+#include "platform.h"
+
+/**
+ * ps3_setup_gelic_device - Setup and register a gelic device instance.
+ *
+ * Allocates memory for a struct ps3_system_bus_device instance, initialises the
+ * structure members, and registers the device instance with the system bus.
+ */
+
+static int __init ps3_setup_gelic_device(
+	const struct ps3_repository_device *repo)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->dev.match_id = PS3_MATCH_ID_GELIC;
+	p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+	p->dev.bus_id = repo->bus_id;
+	p->dev.dev_id = repo->dev_id;
+	p->dev.d_region = &p->d_region;
+
+	result = ps3_repository_find_interrupt(repo,
+		PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+			__func__, __LINE__);
+		goto fail_find_interrupt;
+	}
+
+	BUG_ON(p->dev.interrupt_id != 0);
+
+	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+		PS3_DMA_OTHER, NULL, 0);
+
+	if (result) {
+		pr_debug("%s:%d ps3_dma_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_dma_init;
+	}
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result) {
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+
+fail_device_register:
+fail_dma_init:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init_refok ps3_setup_uhc_device(
+	const struct ps3_repository_device *repo, enum ps3_match_id match_id,
+	enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+		struct ps3_mmio_region m_region;
+	} *p;
+	u64 bus_addr;
+	u64 len;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->dev.match_id = match_id;
+	p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+	p->dev.bus_id = repo->bus_id;
+	p->dev.dev_id = repo->dev_id;
+	p->dev.d_region = &p->d_region;
+	p->dev.m_region = &p->m_region;
+
+	result = ps3_repository_find_interrupt(repo,
+		interrupt_type, &p->dev.interrupt_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+			__func__, __LINE__);
+		goto fail_find_interrupt;
+	}
+
+	result = ps3_repository_find_reg(repo, reg_type,
+		&bus_addr, &len);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_reg failed\n",
+			__func__, __LINE__);
+		goto fail_find_reg;
+	}
+
+	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+		PS3_DMA_INTERNAL, NULL, 0);
+
+	if (result) {
+		pr_debug("%s:%d ps3_dma_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_dma_init;
+	}
+
+	result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,
+		PS3_MMIO_4K);
+
+	if (result) {
+		pr_debug("%s:%d ps3_mmio_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_mmio_init;
+	}
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result) {
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+
+fail_device_register:
+fail_mmio_init:
+fail_dma_init:
+fail_find_reg:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_setup_ehci_device(
+	const struct ps3_repository_device *repo)
+{
+	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,
+		PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);
+}
+
+static int __init ps3_setup_ohci_device(
+	const struct ps3_repository_device *repo)
+{
+	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,
+		PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);
+}
+
+static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
+	unsigned int port_number)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+	} *p;
+
+	pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,
+		match_id, port_number);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = match_id;
+	p->dev.dev_type = PS3_DEVICE_TYPE_VUART;
+	p->dev.port_number = port_number;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,
+				       unsigned int timeout)
+{
+	int result = -1;
+	unsigned int retries = 0;
+	u64 status;
+
+	for (retries = 0; retries < timeout; retries++) {
+		result = lv1_storage_check_async_status(dev_id, tag, &status);
+		if (!result)
+			break;
+
+		msleep(1);
+	}
+
+	if (result)
+		pr_debug("%s:%u: check_async_status: %s, status %lx\n",
+			 __func__, __LINE__, ps3_result(result), status);
+
+	return result;
+}
+
+/**
+ * ps3_storage_wait_for_device - Wait for a storage device to become ready.
+ * @repo: The repository device to wait for.
+ *
+ * Uses the hypervisor's storage device notification mechanism to wait until
+ * a storage device is ready.  The device notification mechanism uses a
+ * psuedo device (id = -1) to asynchronously notify the guest when storage
+ * devices become ready.  The notification device has a block size of 512
+ * bytes.
+ */
+
+static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
+{
+	int result;
+	const u64 notification_dev_id = (u64)-1LL;
+	const unsigned int timeout = HZ;
+	u64 lpar;
+	u64 tag;
+	struct {
+		u64 operation_code;	/* must be zero */
+		u64 event_mask;		/* 1 = device ready */
+	} *notify_cmd;
+	struct {
+		u64 event_type;		/* notify_device_ready */
+		u64 bus_id;
+		u64 dev_id;
+		u64 dev_type;
+		u64 dev_port;
+	} *notify_event;
+	enum {
+		notify_device_ready = 1
+	};
+
+	pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__,
+		 __LINE__, repo->bus_id, repo->dev_id, repo->dev_type);
+
+	notify_cmd = kzalloc(512, GFP_KERNEL);
+	notify_event = (void *)notify_cmd;
+	if (!notify_cmd)
+		return -ENOMEM;
+
+	lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd));
+
+	result = lv1_open_device(repo->bus_id, notification_dev_id, 0);
+	if (result) {
+		printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,
+		       __LINE__, ps3_result(result));
+		result = -ENODEV;
+		goto fail_free;
+	}
+
+	/* Setup and write the request for device notification. */
+
+	notify_cmd->operation_code = 0;	/* must be zero */
+	notify_cmd->event_mask = 0x01;	/* device ready */
+
+	result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,
+				   &tag);
+	if (result) {
+		printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,
+		       ps3_result(result));
+		result = -ENODEV;
+		goto fail_close;
+	}
+
+	/* Wait for the write completion */
+
+	result = ps3stor_wait_for_completion(notification_dev_id, tag,
+					     timeout);
+	if (result) {
+		printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,
+		       __LINE__, ps3_result(result));
+		result = -ENODEV;
+		goto fail_close;
+	}
+
+	/* Loop here processing the requested notification events. */
+
+	result = -ENODEV;
+	while (1) {
+		memset(notify_event, 0, sizeof(*notify_event));
+
+		result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0,
+					  lpar, &tag);
+		if (result) {
+			printk(KERN_ERR "%s:%u: write failed %s\n", __func__,
+			       __LINE__, ps3_result(result));
+			break;
+		}
+
+		result = ps3stor_wait_for_completion(notification_dev_id, tag,
+						     timeout);
+		if (result) {
+			printk(KERN_ERR "%s:%u: read not completed %s\n",
+			       __func__, __LINE__, ps3_result(result));
+			break;
+		}
+
+		if (notify_event->event_type != notify_device_ready ||
+		    notify_event->bus_id != repo->bus_id) {
+			pr_debug("%s:%u: bad notify_event: event %lu, "
+				 "dev_id %lu, dev_type %lu\n",
+				 __func__, __LINE__, notify_event->event_type,
+				 notify_event->dev_id, notify_event->dev_type);
+			break;
+		}
+
+		if (notify_event->dev_id == repo->dev_id &&
+		    notify_event->dev_type == repo->dev_type) {
+			pr_debug("%s:%u: device ready: dev_id %u\n", __func__,
+				 __LINE__, repo->dev_id);
+			result = 0;
+			break;
+		}
+
+		if (notify_event->dev_id == repo->dev_id &&
+		    notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {
+			pr_debug("%s:%u: no access: dev_id %u\n", __func__,
+				 __LINE__, repo->dev_id);
+			break;
+		}
+	}
+
+fail_close:
+	lv1_close_device(repo->bus_id, notification_dev_id);
+fail_free:
+	kfree(notify_cmd);
+	pr_debug(" <- %s:%u\n", __func__, __LINE__);
+	return result;
+}
+
+static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
+				 enum ps3_match_id match_id)
+{
+	int result;
+	struct ps3_storage_device *p;
+	u64 port, blk_size, num_blocks;
+	unsigned int num_regions, i;
+
+	pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id);
+
+	result = ps3_repository_read_stor_dev_info(repo->bus_index,
+						   repo->dev_index, &port,
+						   &blk_size, &num_blocks,
+						   &num_regions);
+	if (result) {
+		printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n",
+		       __func__, __LINE__, result);
+		return -ENODEV;
+	}
+
+	pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu "
+		 "num_regions %u\n", __func__, __LINE__, repo->bus_index,
+		 repo->dev_index, port, blk_size, num_blocks, num_regions);
+
+	p = kzalloc(sizeof(struct ps3_storage_device) +
+		    num_regions * sizeof(struct ps3_storage_region),
+		    GFP_KERNEL);
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->sbd.match_id = match_id;
+	p->sbd.dev_type = PS3_DEVICE_TYPE_SB;
+	p->sbd.bus_id = repo->bus_id;
+	p->sbd.dev_id = repo->dev_id;
+	p->sbd.d_region = &p->dma_region;
+	p->blk_size = blk_size;
+	p->num_regions = num_regions;
+
+	result = ps3_repository_find_interrupt(repo,
+					       PS3_INTERRUPT_TYPE_EVENT_PORT,
+					       &p->sbd.interrupt_id);
+	if (result) {
+		printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__,
+		       __LINE__, result);
+		result = -ENODEV;
+		goto fail_find_interrupt;
+	}
+
+	/* FIXME: Arrange to only do this on a 'cold' boot */
+
+	result = ps3_storage_wait_for_device(repo);
+	if (result) {
+		printk(KERN_ERR "%s:%u: storage_notification failed %d\n",
+		       __func__, __LINE__, result);
+		result = -ENODEV;
+		goto fail_probe_notification;
+	}
+
+	for (i = 0; i < num_regions; i++) {
+		unsigned int id;
+		u64 start, size;
+
+		result = ps3_repository_read_stor_dev_region(repo->bus_index,
+							     repo->dev_index,
+							     i, &id, &start,
+							     &size);
+		if (result) {
+			printk(KERN_ERR
+			       "%s:%u: read_stor_dev_region failed %d\n",
+			       __func__, __LINE__, result);
+			result = -ENODEV;
+			goto fail_read_region;
+		}
+		pr_debug("%s:%u: region %u: id %u start %lu size %lu\n",
+			 __func__, __LINE__, i, id, start, size);
+
+		p->regions[i].id = id;
+		p->regions[i].start = start;
+		p->regions[i].size = size;
+	}
+
+	result = ps3_system_bus_device_register(&p->sbd);
+	if (result) {
+		pr_debug("%s:%u ps3_system_bus_device_register failed\n",
+			 __func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%u\n", __func__, __LINE__);
+	return 0;
+
+fail_device_register:
+fail_read_region:
+fail_probe_notification:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_vuart_devices(void)
+{
+	int result;
+	unsigned int port_number;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	result = ps3_repository_read_vuart_av_port(&port_number);
+	if (result)
+		port_number = 0; /* av default */
+
+	result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
+	WARN_ON(result);
+
+	result = ps3_repository_read_vuart_sysmgr_port(&port_number);
+	if (result)
+		port_number = 2; /* sysmgr default */
+
+	result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,
+		port_number);
+	WARN_ON(result);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_sound_devices(void)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+		struct ps3_mmio_region m_region;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = PS3_MATCH_ID_SOUND;
+	p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+	p->dev.d_region = &p->d_region;
+	p->dev.m_region = &p->m_region;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_graphics_devices(void)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
+	p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+/**
+ * ps3_register_repository_device - Register a device from the repositiory info.
+ *
+ */
+
+static int ps3_register_repository_device(
+	const struct ps3_repository_device *repo)
+{
+	int result;
+
+	switch (repo->dev_type) {
+	case PS3_DEV_TYPE_SB_GELIC:
+		result = ps3_setup_gelic_device(repo);
+		if (result) {
+			pr_debug("%s:%d ps3_setup_gelic_device failed\n",
+				__func__, __LINE__);
+		}
+		break;
+	case PS3_DEV_TYPE_SB_USB:
+
+		/* Each USB device has both an EHCI and an OHCI HC */
+
+		result = ps3_setup_ehci_device(repo);
+
+		if (result) {
+			pr_debug("%s:%d ps3_setup_ehci_device failed\n",
+				__func__, __LINE__);
+		}
+
+		result = ps3_setup_ohci_device(repo);
+
+		if (result) {
+			pr_debug("%s:%d ps3_setup_ohci_device failed\n",
+				__func__, __LINE__);
+		}
+		break;
+	case PS3_DEV_TYPE_STOR_DISK:
+		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
+
+		/* Some devices are not accessable from the Other OS lpar. */
+		if (result == -ENODEV) {
+			result = 0;
+			pr_debug("%s:%u: not accessable\n", __func__,
+				 __LINE__);
+		}
+
+		if (result)
+			pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+				 __func__, __LINE__);
+		break;
+
+	case PS3_DEV_TYPE_STOR_ROM:
+		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM);
+		if (result)
+			pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+				 __func__, __LINE__);
+		break;
+
+	case PS3_DEV_TYPE_STOR_FLASH:
+		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH);
+		if (result)
+			pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+				 __func__, __LINE__);
+		break;
+
+	default:
+		result = 0;
+		pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
+			repo->dev_type);
+	}
+
+	return result;
+}
+
+/**
+ * ps3_probe_thread - Background repository probing at system startup.
+ *
+ * This implementation only supports background probing on a single bus.
+ */
+
+static int ps3_probe_thread(void *data)
+{
+	struct ps3_repository_device *repo = data;
+	int result;
+	unsigned int ms = 250;
+
+	pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
+
+	do {
+		try_to_freeze();
+
+		pr_debug("%s:%u: probing...\n", __func__, __LINE__);
+
+		do {
+			result = ps3_repository_find_device(repo);
+
+			if (result == -ENODEV)
+				pr_debug("%s:%u: nothing new\n", __func__,
+					__LINE__);
+			else if (result)
+				pr_debug("%s:%u: find device error.\n",
+					__func__, __LINE__);
+			else {
+				pr_debug("%s:%u: found device\n", __func__,
+					__LINE__);
+				ps3_register_repository_device(repo);
+				ps3_repository_bump_device(repo);
+				ms = 250;
+			}
+		} while (!result);
+
+		pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
+
+		if ( ms > 60000)
+			break;
+
+		msleep_interruptible(ms);
+
+		/* An exponential backoff. */
+		ms <<= 1;
+
+	} while (!kthread_should_stop());
+
+	pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
+
+	return 0;
+}
+
+/**
+ * ps3_start_probe_thread - Starts the background probe thread.
+ *
+ */
+
+static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
+{
+	int result;
+	struct task_struct *task;
+	static struct ps3_repository_device repo; /* must be static */
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	memset(&repo, 0, sizeof(repo));
+
+	repo.bus_type = bus_type;
+
+	result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
+
+	if (result) {
+		printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);
+		return -ENODEV;
+	}
+
+	result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
+
+	if (result) {
+		printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,
+			result);
+		return -ENODEV;
+	}
+
+	task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type);
+
+	if (IS_ERR(task)) {
+		result = PTR_ERR(task);
+		printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,
+		       result);
+		return result;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+/**
+ * ps3_register_devices - Probe the system and register devices found.
+ *
+ * A device_initcall() routine.
+ */
+
+static int __init ps3_register_devices(void)
+{
+	int result;
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	/* ps3_repository_dump_bus_info(); */
+
+	result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
+
+	ps3_register_vuart_devices();
+
+	ps3_register_graphics_devices();
+
+	ps3_repository_find_devices(PS3_BUS_TYPE_SB,
+		ps3_register_repository_device);
+
+	ps3_register_sound_devices();
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+device_initcall(ps3_register_devices);
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index a1409e4..5d2e176 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -29,12 +29,12 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
-static hpte_t *htab;
+static struct hash_pte *htab;
 static unsigned long htab_addr;
 static unsigned char *bolttab;
 static unsigned char *inusetab;
@@ -44,8 +44,8 @@
 #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
 	_debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
 static void _debug_dump_hpte(unsigned long pa, unsigned long va,
-	unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize,
-	unsigned long slot, const char* func, int line)
+	unsigned long group, unsigned long bitmap, struct hash_pte lhpte,
+	int psize, unsigned long slot, const char* func, int line)
 {
 	DBG("%s:%d: pa     = %lxh\n", func, line, pa);
 	DBG("%s:%d: lpar   = %lxh\n", func, line,
@@ -63,7 +63,7 @@
 	unsigned long pa, unsigned long rflags, unsigned long vflags, int psize)
 {
 	unsigned long slot;
-	hpte_t lhpte;
+	struct hash_pte lhpte;
 	int secondary = 0;
 	unsigned long result;
 	unsigned long bitmap;
@@ -234,10 +234,17 @@
 
 static void ps3_hpte_clear(void)
 {
-	/* Make sure to clean up the frame buffer device first */
-	ps3fb_cleanup();
+	int result;
 
-	lv1_unmap_htab(htab_addr);
+	DBG(" -> %s:%d\n", __func__, __LINE__);
+
+	result = lv1_unmap_htab(htab_addr);
+	BUG_ON(result);
+
+	ps3_mm_shutdown();
+	ps3_mm_vas_destroy();
+
+	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
 void __init ps3_hpte_init(unsigned long htab_size)
@@ -255,7 +262,7 @@
 
 	ppc64_pft_size = __ilog2(htab_size);
 
-	bitmap_size = htab_size / sizeof(hpte_t) / 8;
+	bitmap_size = htab_size / sizeof(struct hash_pte) / 8;
 
 	bolttab = __va(lmb_alloc(bitmap_size, 1));
 	inusetab = __va(lmb_alloc(bitmap_size, 1));
@@ -273,8 +280,8 @@
 
 	result = lv1_map_htab(0, &htab_addr);
 
-	htab = (hpte_t *)__ioremap(htab_addr, htab_size,
-				   pgprot_val(PAGE_READONLY_X));
+	htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size,
+					    pgprot_val(PAGE_READONLY_X));
 
 	DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
 		htab_addr, (unsigned long)htab);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index ec9030d..67e32ec 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -30,9 +30,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 /**
@@ -78,19 +78,85 @@
 /**
  * struct ps3_private - a per cpu data structure
  * @bmp: ps3_bmp structure
- * @node: HV logical_ppe_id
- * @cpu: HV thread_id
+ * @ppe_id: HV logical_ppe_id
+ * @thread_id: HV thread_id
  */
 
 struct ps3_private {
 	struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
-	u64 node;
-	unsigned int cpu;
+	u64 ppe_id;
+	u64 thread_id;
 };
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
 
 /**
+ * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_mask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	unsigned long flags;
+
+	pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+		pd->thread_id, virq);
+
+	local_irq_save(flags);
+	clear_bit(63 - virq, &pd->bmp.mask);
+	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+	local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_unmask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	unsigned long flags;
+
+	pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+		pd->thread_id, virq);
+
+	local_irq_save(flags);
+	set_bit(63 - virq, &pd->bmp.mask);
+	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+	local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_eoi - HV end-of-interrupt.
+ * @virq: The assigned Linux virq.
+ *
+ * Calls lv1_end_of_interrupt_ext().
+ */
+
+static void ps3_chip_eoi(unsigned int virq)
+{
+	const struct ps3_private *pd = get_irq_chip_data(virq);
+	lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
+}
+
+/**
+ * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
+ */
+
+static struct irq_chip ps3_irq_chip = {
+	.typename = "ps3",
+	.mask = ps3_chip_mask,
+	.unmask = ps3_chip_unmask,
+	.eoi = ps3_chip_eoi,
+};
+
+/**
  * ps3_virq_setup - virq related setup.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
@@ -134,6 +200,8 @@
 		goto fail_set;
 	}
 
+	ps3_chip_mask(*virq);
+
 	return result;
 
 fail_set:
@@ -153,8 +221,8 @@
 {
 	const struct ps3_private *pd = get_irq_chip_data(virq);
 
-	pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
-		pd->node, pd->cpu, virq);
+	pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+		__LINE__, pd->ppe_id, pd->thread_id, virq);
 
 	set_irq_chip_data(virq, NULL);
 	irq_dispose_mapping(virq);
@@ -190,7 +258,8 @@
 
 	/* Binds outlet to cpu + virq. */
 
-	result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
+	result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq,
+		outlet, 0);
 
 	if (result) {
 		pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
@@ -222,10 +291,12 @@
 	int result;
 	const struct ps3_private *pd = get_irq_chip_data(virq);
 
-	pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
-		pd->node, pd->cpu, virq);
+	pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+		__LINE__, pd->ppe_id, pd->thread_id, virq);
 
-	result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
+	ps3_chip_mask(virq);
+
+	result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
 
 	if (result)
 		pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
@@ -282,7 +353,9 @@
 {
 	int result;
 
-	pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
+	pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
+
+	ps3_chip_mask(virq);
 
 	result = lv1_destruct_event_receive_port(virq_to_hw(virq));
 
@@ -290,17 +363,14 @@
 		pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	/* lv1_destruct_event_receive_port() destroys the IRQ plug,
-	 * so don't call ps3_irq_plug_destroy() here.
+	/*
+	 * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
+	 * calls from interrupt context (smp_call_function) when kexecing.
 	 */
 
-	result = ps3_virq_destroy(virq);
-	BUG_ON(result);
-
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
-EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
 
 int ps3_send_event_locally(unsigned int virq)
 {
@@ -311,17 +381,15 @@
  * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
- * @did: The HV device identifier read from the system repository.
- * @interrupt_id: The device interrupt id read from the system repository.
+ * @dev: The system bus device instance.
  * @virq: The assigned Linux virq.
  *
  * An event irq represents a virtual device interrupt.  The interrupt_id
  * coresponds to the software interrupt number.
  */
 
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
-	const struct ps3_device_id *did, unsigned int interrupt_id,
-	unsigned int *virq)
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+	enum ps3_cpu_binding cpu, unsigned int *virq)
 {
 	/* this should go in system-bus.c */
 
@@ -332,8 +400,8 @@
 	if (result)
 		return result;
 
-	result = lv1_connect_interrupt_event_receive_port(did->bus_id,
-		did->dev_id, virq_to_hw(*virq), interrupt_id);
+	result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
+		dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
 
 	if (result) {
 		pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
@@ -345,24 +413,24 @@
 	}
 
 	pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-		interrupt_id, *virq);
+		dev->interrupt_id, *virq);
 
 	return 0;
 }
 EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
 
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
-	unsigned int interrupt_id, unsigned int virq)
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+	unsigned int virq)
 {
 	/* this should go in system-bus.c */
 
 	int result;
 
 	pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-		interrupt_id, virq);
+		dev->interrupt_id, virq);
 
-	result = lv1_disconnect_interrupt_event_receive_port(did->bus_id,
-		did->dev_id, virq_to_hw(virq), interrupt_id);
+	result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
+		dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
 
 	if (result)
 		pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
@@ -372,6 +440,14 @@
 	result = ps3_event_receive_port_destroy(virq);
 	BUG_ON(result);
 
+	/*
+	 * ps3_event_receive_port_destroy() destroys the IRQ plug,
+	 * so don't call ps3_irq_plug_destroy() here.
+	 */
+
+	result = ps3_virq_destroy(virq);
+	BUG_ON(result);
+
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
@@ -412,16 +488,24 @@
 int ps3_io_irq_destroy(unsigned int virq)
 {
 	int result;
+	unsigned long outlet = virq_to_hw(virq);
 
-	result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+	ps3_chip_mask(virq);
+
+	/*
+	 * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
+	 * so call ps3_irq_plug_destroy() first.
+	 */
+
+	result = ps3_irq_plug_destroy(virq);
+	BUG_ON(result);
+
+	result = lv1_destruct_io_irq_outlet(outlet);
 
 	if (result)
 		pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	result = ps3_irq_plug_destroy(virq);
-	BUG_ON(result);
-
 	return result;
 }
 EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
@@ -461,11 +545,13 @@
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
 
 int ps3_vuart_irq_destroy(unsigned int virq)
 {
 	int result;
 
+	ps3_chip_mask(virq);
 	result = lv1_deconfigure_virtual_uart_irq();
 
 	if (result) {
@@ -479,6 +565,7 @@
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
 
 /**
  * ps3_spe_irq_setup - Setup an spe virq.
@@ -514,9 +601,14 @@
 
 int ps3_spe_irq_destroy(unsigned int virq)
 {
-	int result = ps3_irq_plug_destroy(virq);
+	int result;
+
+	ps3_chip_mask(virq);
+
+	result = ps3_irq_plug_destroy(virq);
 	BUG_ON(result);
-	return 0;
+
+	return result;
 }
 
 
@@ -533,7 +625,7 @@
 		*p & 0xffff);
 }
 
-static void __attribute__ ((unused)) _dump_256_bmp(const char *header,
+static void __maybe_unused _dump_256_bmp(const char *header,
 	const u64 *p, unsigned cpu, const char* func, int line)
 {
 	pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
@@ -546,86 +638,25 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&pd->bmp.lock, flags);
-	_dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line);
-	_dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+	_dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line);
+	_dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
 	spin_unlock_irqrestore(&pd->bmp.lock, flags);
 }
 
 #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd,
+static void __maybe_unused _dump_mask(struct ps3_private *pd,
 	const char* func, int line)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&pd->bmp.lock, flags);
-	_dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+	_dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
 	spin_unlock_irqrestore(&pd->bmp.lock, flags);
 }
 #else
 static void dump_bmp(struct ps3_private* pd) {};
 #endif /* defined(DEBUG) */
 
-static void ps3_chip_mask(unsigned int virq)
-{
-	struct ps3_private *pd = get_irq_chip_data(virq);
-	u64 bit = 0x8000000000000000UL >> virq;
-	u64 *p = &pd->bmp.mask;
-	u64 old;
-	unsigned long flags;
-
-	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-	local_irq_save(flags);
-	asm volatile(
-		     "1:	ldarx %0,0,%3\n"
-		     "andc	%0,%0,%2\n"
-		     "stdcx.	%0,0,%3\n"
-		     "bne-	1b"
-		     : "=&r" (old), "+m" (*p)
-		     : "r" (bit), "r" (p)
-		     : "cc" );
-
-	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-	local_irq_restore(flags);
-}
-
-static void ps3_chip_unmask(unsigned int virq)
-{
-	struct ps3_private *pd = get_irq_chip_data(virq);
-	u64 bit = 0x8000000000000000UL >> virq;
-	u64 *p = &pd->bmp.mask;
-	u64 old;
-	unsigned long flags;
-
-	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-	local_irq_save(flags);
-	asm volatile(
-		     "1:	ldarx %0,0,%3\n"
-		     "or	%0,%0,%2\n"
-		     "stdcx.	%0,0,%3\n"
-		     "bne-	1b"
-		     : "=&r" (old), "+m" (*p)
-		     : "r" (bit), "r" (p)
-		     : "cc" );
-
-	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-	local_irq_restore(flags);
-}
-
-static void ps3_chip_eoi(unsigned int virq)
-{
-	const struct ps3_private *pd = get_irq_chip_data(virq);
-	lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
-}
-
-static struct irq_chip irq_chip = {
-	.typename = "ps3",
-	.mask = ps3_chip_mask,
-	.unmask = ps3_chip_unmask,
-	.eoi = ps3_chip_eoi,
-};
-
 static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
 {
 	set_irq_chip_data(virq, NULL);
@@ -637,7 +668,7 @@
 	pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
 		virq);
 
-	set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
+	set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
 
 	return 0;
 }
@@ -657,7 +688,7 @@
 		cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
-unsigned int ps3_get_irq(void)
+static unsigned int ps3_get_irq(void)
 {
 	struct ps3_private *pd = &__get_cpu_var(ps3_private);
 	u64 x = (pd->bmp.status & pd->bmp.mask);
@@ -672,8 +703,8 @@
 	plug &= 0x3f;
 
 	if (unlikely(plug) == NO_IRQ) {
-		pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__,
-			pd->cpu);
+		pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
+			__LINE__, pd->thread_id);
 		dump_bmp(&per_cpu(ps3_private, 0));
 		dump_bmp(&per_cpu(ps3_private, 1));
 		return NO_IRQ;
@@ -703,16 +734,16 @@
 	for_each_possible_cpu(cpu) {
 		struct ps3_private *pd = &per_cpu(ps3_private, cpu);
 
-		lv1_get_logical_ppe_id(&pd->node);
-		pd->cpu = get_hard_smp_processor_id(cpu);
+		lv1_get_logical_ppe_id(&pd->ppe_id);
+		pd->thread_id = get_hard_smp_processor_id(cpu);
 		spin_lock_init(&pd->bmp.lock);
 
-		pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
-			__LINE__, pd->node, pd->cpu,
+		pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n",
+			__func__, __LINE__, pd->ppe_id, pd->thread_id,
 			ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
 
-		result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu,
-			ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
+		result = lv1_configure_irq_state_bitmap(pd->ppe_id,
+			pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
 
 		if (result)
 			pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
@@ -722,3 +753,16 @@
 
 	ppc_md.get_irq = ps3_get_irq;
 }
+
+void ps3_shutdown_IRQ(int cpu)
+{
+	int result;
+	u64 ppe_id;
+	u64 thread_id = get_hard_smp_processor_id(cpu);
+
+	lv1_get_logical_ppe_id(&ppe_id);
+	result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
+
+	DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__,
+		__LINE__, ppe_id, thread_id, cpu, ps3_result(result));
+}
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index f8a3e20..7bb3e16 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -30,9 +30,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 enum {
@@ -115,7 +115,8 @@
 };
 
 #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__)
-static void _debug_dump_map(const struct map* m, const char* func, int line)
+static void __maybe_unused _debug_dump_map(const struct map *m,
+	const char *func, int line)
 {
 	DBG("%s:%d: map.total     = %lxh\n", func, line, m->total);
 	DBG("%s:%d: map.rm.size   = %lxh\n", func, line, m->rm.size);
@@ -212,9 +213,15 @@
 
 void ps3_mm_vas_destroy(void)
 {
+	int result;
+
+	DBG("%s:%d: map.vas_id    = %lu\n", __func__, __LINE__, map.vas_id);
+
 	if (map.vas_id) {
-		lv1_select_virtual_address_space(0);
-		lv1_destruct_virtual_address_space(map.vas_id);
+		result = lv1_select_virtual_address_space(0);
+		BUG_ON(result);
+		result = lv1_destruct_virtual_address_space(map.vas_id);
+		BUG_ON(result);
 		map.vas_id = 0;
 	}
 }
@@ -232,7 +239,7 @@
  * @size is rounded down to a multiple of the vas large page size.
  */
 
-int ps3_mm_region_create(struct mem_region *r, unsigned long size)
+static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
 {
 	int result;
 	unsigned long muid;
@@ -273,10 +280,14 @@
  * @r: pointer to struct mem_region
  */
 
-void ps3_mm_region_destroy(struct mem_region *r)
+static void ps3_mm_region_destroy(struct mem_region *r)
 {
+	int result;
+
+	DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base);
 	if (r->base) {
-		lv1_release_memory(r->base);
+		result = lv1_release_memory(r->base);
+		BUG_ON(result);
 		r->size = r->base = r->offset = 0;
 		map.total = map.rm.size;
 	}
@@ -329,31 +340,34 @@
 /*============================================================================*/
 
 /**
- * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
+ * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
  * @r: pointer to dma region structure
  * @lpar_addr: HV lpar address
  */
 
-static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r,
+static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r,
 	unsigned long lpar_addr)
 {
-	BUG_ON(lpar_addr >= map.r1.base + map.r1.size);
-	return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr
-		: lpar_addr - map.r1.offset);
+	if (lpar_addr >= map.rm.size)
+		lpar_addr -= map.r1.offset;
+	BUG_ON(lpar_addr < r->offset);
+	BUG_ON(lpar_addr >= r->offset + r->len);
+	return r->bus_addr + lpar_addr - r->offset;
 }
 
 #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__)
-static void _dma_dump_region(const struct ps3_dma_region *r, const char* func,
-	int line)
+static void  __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
+	const char *func, int line)
 {
-	DBG("%s:%d: dev        %u:%u\n", func, line, r->did.bus_id,
-		r->did.dev_id);
+	DBG("%s:%d: dev        %u:%u\n", func, line, r->dev->bus_id,
+		r->dev->dev_id);
 	DBG("%s:%d: page_size  %u\n", func, line, r->page_size);
 	DBG("%s:%d: bus_addr   %lxh\n", func, line, r->bus_addr);
 	DBG("%s:%d: len        %lxh\n", func, line, r->len);
+	DBG("%s:%d: offset     %lxh\n", func, line, r->offset);
 }
 
-/**
+  /**
  * dma_chunk - A chunk of dma pages mapped by the io controller.
  * @region - The dma region that owns this chunk.
  * @lpar_addr: Starting lpar address of the area to map.
@@ -381,10 +395,11 @@
 	int line)
 {
 	DBG("%s:%d: r.dev        %u:%u\n", func, line,
-		c->region->did.bus_id, c->region->did.dev_id);
+		c->region->dev->bus_id, c->region->dev->dev_id);
 	DBG("%s:%d: r.bus_addr   %lxh\n", func, line, c->region->bus_addr);
 	DBG("%s:%d: r.page_size  %u\n", func, line, c->region->page_size);
 	DBG("%s:%d: r.len        %lxh\n", func, line, c->region->len);
+	DBG("%s:%d: r.offset     %lxh\n", func, line, c->region->offset);
 	DBG("%s:%d: c.lpar_addr  %lxh\n", func, line, c->lpar_addr);
 	DBG("%s:%d: c.bus_addr   %lxh\n", func, line, c->bus_addr);
 	DBG("%s:%d: c.len        %lxh\n", func, line, c->len);
@@ -395,39 +410,68 @@
 {
 	struct dma_chunk *c;
 	unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size);
-	unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus,
+					      1 << r->page_size);
 
 	list_for_each_entry(c, &r->chunk_list.head, link) {
 		/* intersection */
-		if (aligned_bus >= c->bus_addr
-			&& aligned_bus < c->bus_addr + c->len
-			&& aligned_bus + aligned_len <= c->bus_addr + c->len) {
+		if (aligned_bus >= c->bus_addr &&
+		    aligned_bus + aligned_len <= c->bus_addr + c->len)
 			return c;
-		}
+
 		/* below */
-		if (aligned_bus + aligned_len <= c->bus_addr) {
+		if (aligned_bus + aligned_len <= c->bus_addr)
 			continue;
-		}
+
 		/* above */
-		if (aligned_bus >= c->bus_addr + c->len) {
+		if (aligned_bus >= c->bus_addr + c->len)
 			continue;
-		}
 
 		/* we don't handle the multi-chunk case for now */
-
 		dma_dump_chunk(c);
 		BUG();
 	}
 	return NULL;
 }
 
-static int dma_free_chunk(struct dma_chunk *c)
+static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r,
+	unsigned long lpar_addr, unsigned long len)
+{
+	struct dma_chunk *c;
+	unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar,
+					      1 << r->page_size);
+
+	list_for_each_entry(c, &r->chunk_list.head, link) {
+		/* intersection */
+		if (c->lpar_addr <= aligned_lpar &&
+		    aligned_lpar < c->lpar_addr + c->len) {
+			if (aligned_lpar + aligned_len <= c->lpar_addr + c->len)
+				return c;
+			else {
+				dma_dump_chunk(c);
+				BUG();
+			}
+		}
+		/* below */
+		if (aligned_lpar + aligned_len <= c->lpar_addr) {
+			continue;
+		}
+		/* above */
+		if (c->lpar_addr + c->len <= aligned_lpar) {
+			continue;
+		}
+	}
+	return NULL;
+}
+
+static int dma_sb_free_chunk(struct dma_chunk *c)
 {
 	int result = 0;
 
 	if (c->bus_addr) {
-		result = lv1_unmap_device_dma_region(c->region->did.bus_id,
-			c->region->did.dev_id, c->bus_addr, c->len);
+		result = lv1_unmap_device_dma_region(c->region->dev->bus_id,
+			c->region->dev->dev_id, c->bus_addr, c->len);
 		BUG_ON(result);
 	}
 
@@ -435,8 +479,39 @@
 	return result;
 }
 
+static int dma_ioc0_free_chunk(struct dma_chunk *c)
+{
+	int result = 0;
+	int iopage;
+	unsigned long offset;
+	struct ps3_dma_region *r = c->region;
+
+	DBG("%s:start\n", __func__);
+	for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) {
+		offset = (1 << r->page_size) * iopage;
+		/* put INVALID entry */
+		result = lv1_put_iopte(0,
+				       c->bus_addr + offset,
+				       c->lpar_addr + offset,
+				       r->ioid,
+				       0);
+		DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__,
+		    c->bus_addr + offset,
+		    c->lpar_addr + offset,
+		    r->ioid);
+
+		if (result) {
+			DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__,
+			    __LINE__, ps3_result(result));
+		}
+	}
+	kfree(c);
+	DBG("%s:end\n", __func__);
+	return result;
+}
+
 /**
- * dma_map_pages - Maps dma pages into the io controller bus address space.
+ * dma_sb_map_pages - Maps dma pages into the io controller bus address space.
  * @r: Pointer to a struct ps3_dma_region.
  * @phys_addr: Starting physical address of the area to map.
  * @len: Length in bytes of the area to map.
@@ -446,8 +521,8 @@
  * make the HV call to add the pages into the io controller address space.
  */
 
-static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
-	unsigned long len, struct dma_chunk **c_out)
+static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+	    unsigned long len, struct dma_chunk **c_out, u64 iopte_flag)
 {
 	int result;
 	struct dma_chunk *c;
@@ -461,13 +536,13 @@
 
 	c->region = r;
 	c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
-	c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr);
+	c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr);
 	c->len = len;
 
-	result = lv1_map_device_dma_region(c->region->did.bus_id,
-		c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len,
-		0xf800000000000000UL);
-
+	BUG_ON(iopte_flag != 0xf800000000000000UL);
+	result = lv1_map_device_dma_region(c->region->dev->bus_id,
+					   c->region->dev->dev_id, c->lpar_addr,
+					   c->bus_addr, c->len, iopte_flag);
 	if (result) {
 		DBG("%s:%d: lv1_map_device_dma_region failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
@@ -487,26 +562,120 @@
 	return result;
 }
 
+static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+			      unsigned long len, struct dma_chunk **c_out,
+			      u64 iopte_flag)
+{
+	int result;
+	struct dma_chunk *c, *last;
+	int iopage, pages;
+	unsigned long offset;
+
+	DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__,
+	    phys_addr, ps3_mm_phys_to_lpar(phys_addr), len);
+	c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC);
+
+	if (!c) {
+		result = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	c->region = r;
+	c->len = len;
+	c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
+	/* allocate IO address */
+	if (list_empty(&r->chunk_list.head)) {
+		/* first one */
+		c->bus_addr = r->bus_addr;
+	} else {
+		/* derive from last bus addr*/
+		last  = list_entry(r->chunk_list.head.next,
+				   struct dma_chunk, link);
+		c->bus_addr = last->bus_addr + last->len;
+		DBG("%s: last bus=%#lx, len=%#lx\n", __func__,
+		    last->bus_addr, last->len);
+	}
+
+	/* FIXME: check whether length exceeds region size */
+
+	/* build ioptes for the area */
+	pages = len >> r->page_size;
+	DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__,
+	    r->page_size, r->len, pages, iopte_flag);
+	for (iopage = 0; iopage < pages; iopage++) {
+		offset = (1 << r->page_size) * iopage;
+		result = lv1_put_iopte(0,
+				       c->bus_addr + offset,
+				       c->lpar_addr + offset,
+				       r->ioid,
+				       iopte_flag);
+		if (result) {
+			printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region "
+				"failed: %s\n", __func__, __LINE__,
+				ps3_result(result));
+			goto fail_map;
+		}
+		DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__,
+		    iopage, c->bus_addr + offset, c->lpar_addr + offset,
+		    r->ioid);
+	}
+
+	/* be sure that last allocated one is inserted at head */
+	list_add(&c->link, &r->chunk_list.head);
+
+	*c_out = c;
+	DBG("%s: end\n", __func__);
+	return 0;
+
+fail_map:
+	for (iopage--; 0 <= iopage; iopage--) {
+		lv1_put_iopte(0,
+			      c->bus_addr + offset,
+			      c->lpar_addr + offset,
+			      r->ioid,
+			      0);
+	}
+	kfree(c);
+fail_alloc:
+	*c_out = NULL;
+	return result;
+}
+
 /**
- * dma_region_create - Create a device dma region.
+ * dma_sb_region_create - Create a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This is the lowest level dma region create routine, and is the one that
  * will make the HV call to create the region.
  */
 
-static int dma_region_create(struct ps3_dma_region* r)
+static int dma_sb_region_create(struct ps3_dma_region *r)
 {
 	int result;
 
-	r->len = _ALIGN_UP(map.total, 1 << r->page_size);
+	pr_info(" -> %s:%d:\n", __func__, __LINE__);
+
+	BUG_ON(!r);
+
+	if (!r->dev->bus_id) {
+		pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+			r->dev->bus_id, r->dev->dev_id);
+		return 0;
+	}
+
+	DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__,
+	    __LINE__, r->len, r->page_size, r->offset);
+
+	BUG_ON(!r->len);
+	BUG_ON(!r->page_size);
+	BUG_ON(!r->region_ops);
+
 	INIT_LIST_HEAD(&r->chunk_list.head);
 	spin_lock_init(&r->chunk_list.lock);
 
-	result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id,
-		r->len, r->page_size, r->region_type, &r->bus_addr);
-
-	dma_dump_region(r);
+	result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id,
+		roundup_pow_of_two(r->len), r->page_size, r->region_type,
+		&r->bus_addr);
 
 	if (result) {
 		DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n",
@@ -517,6 +686,27 @@
 	return result;
 }
 
+static int dma_ioc0_region_create(struct ps3_dma_region *r)
+{
+	int result;
+
+	INIT_LIST_HEAD(&r->chunk_list.head);
+	spin_lock_init(&r->chunk_list.lock);
+
+	result = lv1_allocate_io_segment(0,
+					 r->len,
+					 r->page_size,
+					 &r->bus_addr);
+	if (result) {
+		DBG("%s:%d: lv1_allocate_io_segment failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		r->len = r->bus_addr = 0;
+	}
+	DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__,
+	    r->len, r->page_size, r->bus_addr);
+	return result;
+}
+
 /**
  * dma_region_free - Free a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
@@ -525,31 +715,62 @@
  * will make the HV call to free the region.
  */
 
-static int dma_region_free(struct ps3_dma_region* r)
+static int dma_sb_region_free(struct ps3_dma_region *r)
 {
 	int result;
 	struct dma_chunk *c;
 	struct dma_chunk *tmp;
 
-	list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
-		list_del(&c->link);
-		dma_free_chunk(c);
+	BUG_ON(!r);
+
+	if (!r->dev->bus_id) {
+		pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+			r->dev->bus_id, r->dev->dev_id);
+		return 0;
 	}
 
-	result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id,
+	list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
+		list_del(&c->link);
+		dma_sb_free_chunk(c);
+	}
+
+	result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id,
 		r->bus_addr);
 
 	if (result)
 		DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	r->len = r->bus_addr = 0;
+	r->bus_addr = 0;
+
+	return result;
+}
+
+static int dma_ioc0_region_free(struct ps3_dma_region *r)
+{
+	int result;
+	struct dma_chunk *c, *n;
+
+	DBG("%s: start\n", __func__);
+	list_for_each_entry_safe(c, n, &r->chunk_list.head, link) {
+		list_del(&c->link);
+		dma_ioc0_free_chunk(c);
+	}
+
+	result = lv1_release_io_segment(0, r->bus_addr);
+
+	if (result)
+		DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+
+	r->bus_addr = 0;
+	DBG("%s: end\n", __func__);
 
 	return result;
 }
 
 /**
- * dma_map_area - Map an area of memory into a device dma region.
+ * dma_sb_map_area - Map an area of memory into a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @virt_addr: Starting virtual address of the area to map.
  * @len: Length in bytes of the area to map.
@@ -559,16 +780,19 @@
  * This is the common dma mapping routine.
  */
 
-static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
-	unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+	   unsigned long len, unsigned long *bus_addr,
+	   u64 iopte_flag)
 {
 	int result;
 	unsigned long flags;
 	struct dma_chunk *c;
 	unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
 		: virt_addr;
-
-	*bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+	unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+					      1 << r->page_size);
+	*bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
 
 	if (!USE_DYNAMIC_DMA) {
 		unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
@@ -588,17 +812,18 @@
 	c = dma_find_chunk(r, *bus_addr, len);
 
 	if (c) {
+		DBG("%s:%d: reusing mapped chunk", __func__, __LINE__);
+		dma_dump_chunk(c);
 		c->usage_count++;
 		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
 		return 0;
 	}
 
-	result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size),
-		_ALIGN_UP(len, 1 << r->page_size), &c);
+	result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag);
 
 	if (result) {
 		*bus_addr = 0;
-		DBG("%s:%d: dma_map_pages failed (%d)\n",
+		DBG("%s:%d: dma_sb_map_pages failed (%d)\n",
 			__func__, __LINE__, result);
 		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
 		return result;
@@ -610,8 +835,57 @@
 	return result;
 }
 
+static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+	     unsigned long len, unsigned long *bus_addr,
+	     u64 iopte_flag)
+{
+	int result;
+	unsigned long flags;
+	struct dma_chunk *c;
+	unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
+		: virt_addr;
+	unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+					      1 << r->page_size);
+
+	DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__,
+	    virt_addr, len);
+	DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__,
+	    phys_addr, aligned_phys, aligned_len);
+
+	spin_lock_irqsave(&r->chunk_list.lock, flags);
+	c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len);
+
+	if (c) {
+		/* FIXME */
+		BUG();
+		*bus_addr = c->bus_addr + phys_addr - aligned_phys;
+		c->usage_count++;
+		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+		return 0;
+	}
+
+	result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c,
+				    iopte_flag);
+
+	if (result) {
+		*bus_addr = 0;
+		DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n",
+			__func__, __LINE__, result);
+		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+		return result;
+	}
+	*bus_addr = c->bus_addr + phys_addr - aligned_phys;
+	DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__,
+	    virt_addr, phys_addr, aligned_phys, *bus_addr);
+	c->usage_count = 1;
+
+	spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+	return result;
+}
+
 /**
- * dma_unmap_area - Unmap an area of memory from a device dma region.
+ * dma_sb_unmap_area - Unmap an area of memory from a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @bus_addr: The starting ioc bus address of the area to unmap.
  * @len: Length in bytes of the area to unmap.
@@ -619,7 +893,7 @@
  * This is the common dma unmap routine.
  */
 
-int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
+static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
 	unsigned long len)
 {
 	unsigned long flags;
@@ -631,7 +905,8 @@
 	if (!c) {
 		unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
 			1 << r->page_size);
-		unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+		unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+			- aligned_bus, 1 << r->page_size);
 		DBG("%s:%d: not found: bus_addr %lxh\n",
 			__func__, __LINE__, bus_addr);
 		DBG("%s:%d: not found: len %lxh\n",
@@ -647,94 +922,166 @@
 
 	if (!c->usage_count) {
 		list_del(&c->link);
-		dma_free_chunk(c);
+		dma_sb_free_chunk(c);
 	}
 
 	spin_unlock_irqrestore(&r->chunk_list.lock, flags);
 	return 0;
 }
 
+static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
+			unsigned long bus_addr, unsigned long len)
+{
+	unsigned long flags;
+	struct dma_chunk *c;
+
+	DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len);
+	spin_lock_irqsave(&r->chunk_list.lock, flags);
+	c = dma_find_chunk(r, bus_addr, len);
+
+	if (!c) {
+		unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
+							1 << r->page_size);
+		unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+						      - aligned_bus,
+						      1 << r->page_size);
+		DBG("%s:%d: not found: bus_addr %lxh\n",
+		    __func__, __LINE__, bus_addr);
+		DBG("%s:%d: not found: len %lxh\n",
+		    __func__, __LINE__, len);
+		DBG("%s:%d: not found: aligned_bus %lxh\n",
+		    __func__, __LINE__, aligned_bus);
+		DBG("%s:%d: not found: aligned_len %lxh\n",
+		    __func__, __LINE__, aligned_len);
+		BUG();
+	}
+
+	c->usage_count--;
+
+	if (!c->usage_count) {
+		list_del(&c->link);
+		dma_ioc0_free_chunk(c);
+	}
+
+	spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+	DBG("%s: end\n", __func__);
+	return 0;
+}
+
 /**
- * dma_region_create_linear - Setup a linear dma maping for a device.
+ * dma_sb_region_create_linear - Setup a linear dma mapping for a device.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This routine creates an HV dma region for the device and maps all available
  * ram into the io controller bus address space.
  */
 
-static int dma_region_create_linear(struct ps3_dma_region *r)
+static int dma_sb_region_create_linear(struct ps3_dma_region *r)
 {
 	int result;
-	unsigned long tmp;
+	unsigned long virt_addr, len, tmp;
 
-	/* force 16M dma pages for linear mapping */
-
-	if (r->page_size != PS3_DMA_16M) {
-		pr_info("%s:%d: forcing 16M pages for linear map\n",
-			__func__, __LINE__);
-		r->page_size = PS3_DMA_16M;
+	if (r->len > 16*1024*1024) {	/* FIXME: need proper fix */
+		/* force 16M dma pages for linear mapping */
+		if (r->page_size != PS3_DMA_16M) {
+			pr_info("%s:%d: forcing 16M pages for linear map\n",
+				__func__, __LINE__);
+			r->page_size = PS3_DMA_16M;
+			r->len = _ALIGN_UP(r->len, 1 << r->page_size);
+		}
 	}
 
-	result = dma_region_create(r);
+	result = dma_sb_region_create(r);
 	BUG_ON(result);
 
-	result = dma_map_area(r, map.rm.base, map.rm.size, &tmp);
-	BUG_ON(result);
+	if (r->offset < map.rm.size) {
+		/* Map (part of) 1st RAM chunk */
+		virt_addr = map.rm.base + r->offset;
+		len = map.rm.size - r->offset;
+		if (len > r->len)
+			len = r->len;
+		result = dma_sb_map_area(r, virt_addr, len, &tmp,
+			IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+		BUG_ON(result);
+	}
 
-	if (USE_LPAR_ADDR)
-		result = dma_map_area(r, map.r1.base, map.r1.size,
-			&tmp);
-	else
-		result = dma_map_area(r, map.rm.size, map.r1.size,
-			&tmp);
-
-	BUG_ON(result);
+	if (r->offset + r->len > map.rm.size) {
+		/* Map (part of) 2nd RAM chunk */
+		virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size;
+		len = r->len;
+		if (r->offset >= map.rm.size)
+			virt_addr += r->offset - map.rm.size;
+		else
+			len -= map.rm.size - r->offset;
+		result = dma_sb_map_area(r, virt_addr, len, &tmp,
+			IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+		BUG_ON(result);
+	}
 
 	return result;
 }
 
 /**
- * dma_region_free_linear - Free a linear dma mapping for a device.
+ * dma_sb_region_free_linear - Free a linear dma mapping for a device.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This routine will unmap all mapped areas and free the HV dma region.
  */
 
-static int dma_region_free_linear(struct ps3_dma_region *r)
+static int dma_sb_region_free_linear(struct ps3_dma_region *r)
 {
 	int result;
+	unsigned long bus_addr, len, lpar_addr;
 
-	result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size);
-	BUG_ON(result);
+	if (r->offset < map.rm.size) {
+		/* Unmap (part of) 1st RAM chunk */
+		lpar_addr = map.rm.base + r->offset;
+		len = map.rm.size - r->offset;
+		if (len > r->len)
+			len = r->len;
+		bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+		result = dma_sb_unmap_area(r, bus_addr, len);
+		BUG_ON(result);
+	}
 
-	result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base),
-		map.r1.size);
-	BUG_ON(result);
+	if (r->offset + r->len > map.rm.size) {
+		/* Unmap (part of) 2nd RAM chunk */
+		lpar_addr = map.r1.base;
+		len = r->len;
+		if (r->offset >= map.rm.size)
+			lpar_addr += r->offset - map.rm.size;
+		else
+			len -= map.rm.size - r->offset;
+		bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+		result = dma_sb_unmap_area(r, bus_addr, len);
+		BUG_ON(result);
+	}
 
-	result = dma_region_free(r);
+	result = dma_sb_region_free(r);
 	BUG_ON(result);
 
 	return result;
 }
 
 /**
- * dma_map_area_linear - Map an area of memory into a device dma region.
+ * dma_sb_map_area_linear - Map an area of memory into a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @virt_addr: Starting virtual address of the area to map.
  * @len: Length in bytes of the area to map.
  * @bus_addr: A pointer to return the starting ioc bus address of the area to
  * map.
  *
- * This routine just returns the coresponding bus address.  Actual mapping
+ * This routine just returns the corresponding bus address.  Actual mapping
  * occurs in dma_region_create_linear().
  */
 
-static int dma_map_area_linear(struct ps3_dma_region *r,
-	unsigned long virt_addr, unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area_linear(struct ps3_dma_region *r,
+	unsigned long virt_addr, unsigned long len, unsigned long *bus_addr,
+	u64 iopte_flag)
 {
 	unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
 		: virt_addr;
-	*bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+	*bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
 	return 0;
 }
 
@@ -744,42 +1091,98 @@
  * @bus_addr: The starting ioc bus address of the area to unmap.
  * @len: Length in bytes of the area to unmap.
  *
- * This routine does nothing.  Unmapping occurs in dma_region_free_linear().
+ * This routine does nothing.  Unmapping occurs in dma_sb_region_free_linear().
  */
 
-static int dma_unmap_area_linear(struct ps3_dma_region *r,
+static int dma_sb_unmap_area_linear(struct ps3_dma_region *r,
 	unsigned long bus_addr, unsigned long len)
 {
 	return 0;
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_ops =  {
+	.create = dma_sb_region_create,
+	.free = dma_sb_region_free,
+	.map = dma_sb_map_area,
+	.unmap = dma_sb_unmap_area
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = {
+	.create = dma_sb_region_create_linear,
+	.free = dma_sb_region_free_linear,
+	.map = dma_sb_map_area_linear,
+	.unmap = dma_sb_unmap_area_linear
+};
+
+static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = {
+	.create = dma_ioc0_region_create,
+	.free = dma_ioc0_region_free,
+	.map = dma_ioc0_map_area,
+	.unmap = dma_ioc0_unmap_area
+};
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+	enum ps3_dma_region_type region_type, void *addr, unsigned long len)
+{
+	unsigned long lpar_addr;
+
+	lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0;
+
+	r->dev = dev;
+	r->page_size = page_size;
+	r->region_type = region_type;
+	r->offset = lpar_addr;
+	if (r->offset >= map.rm.size)
+		r->offset -= map.r1.offset;
+	r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size);
+
+	switch (dev->dev_type) {
+	case PS3_DEVICE_TYPE_SB:
+		r->region_ops =  (USE_DYNAMIC_DMA)
+			? &ps3_dma_sb_region_ops
+			: &ps3_dma_sb_region_linear_ops;
+		break;
+	case PS3_DEVICE_TYPE_IOC0:
+		r->region_ops = &ps3_dma_ioc0_region_ops;
+		break;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+	return 0;
 }
+EXPORT_SYMBOL(ps3_dma_region_init);
 
 int ps3_dma_region_create(struct ps3_dma_region *r)
 {
-	return (USE_DYNAMIC_DMA)
-		? dma_region_create(r)
-		: dma_region_create_linear(r);
+	BUG_ON(!r);
+	BUG_ON(!r->region_ops);
+	BUG_ON(!r->region_ops->create);
+	return r->region_ops->create(r);
 }
+EXPORT_SYMBOL(ps3_dma_region_create);
 
 int ps3_dma_region_free(struct ps3_dma_region *r)
 {
-	return (USE_DYNAMIC_DMA)
-		? dma_region_free(r)
-		: dma_region_free_linear(r);
+	BUG_ON(!r);
+	BUG_ON(!r->region_ops);
+	BUG_ON(!r->region_ops->free);
+	return r->region_ops->free(r);
 }
+EXPORT_SYMBOL(ps3_dma_region_free);
 
 int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
-	unsigned long len, unsigned long *bus_addr)
+	unsigned long len, unsigned long *bus_addr,
+	u64 iopte_flag)
 {
-	return (USE_DYNAMIC_DMA)
-		? dma_map_area(r, virt_addr, len, bus_addr)
-		: dma_map_area_linear(r, virt_addr, len, bus_addr);
+	return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag);
 }
 
 int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
 	unsigned long len)
 {
-	return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len)
-		: dma_unmap_area_linear(r, bus_addr, len);
+	return r->region_ops->unmap(r, bus_addr, len);
 }
 
 /*============================================================================*/
@@ -810,12 +1213,13 @@
 	BUG_ON(map.rm.base);
 	BUG_ON(!map.rm.size);
 
-	lmb_add(map.rm.base, map.rm.size);
-	lmb_analyze();
 
 	/* arrange to do this in ps3_mm_add_memory */
 	ps3_mm_region_create(&map.r1, map.total - map.rm.size);
 
+	/* correct map.total for the real total amount of memory we use */
+	map.total = map.rm.size + map.r1.size;
+
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 5c3da08..b70e474 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -133,7 +133,7 @@
 } static saved_params;
 
 #define dump_header(_a) _dump_header(_a, __func__, __LINE__)
-static void _dump_header(const struct os_area_header __iomem *h, const char* func,
+static void _dump_header(const struct os_area_header *h, const char *func,
 	int line)
 {
 	pr_debug("%s:%d: h.magic_num:         '%s'\n", func, line,
@@ -151,7 +151,7 @@
 }
 
 #define dump_params(_a) _dump_params(_a, __func__, __LINE__)
-static void _dump_params(const struct os_area_params __iomem *p, const char* func,
+static void _dump_params(const struct os_area_params *p, const char *func,
 	int line)
 {
 	pr_debug("%s:%d: p.boot_flag:       %u\n", func, line, p->boot_flag);
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index ca04f03..87d5206 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -41,6 +41,7 @@
 /* irq */
 
 void ps3_init_IRQ(void);
+void ps3_shutdown_IRQ(int cpu);
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
 
 /* smp */
@@ -82,6 +83,7 @@
 	PS3_DEV_TYPE_STOR_ROM = TYPE_ROM,	/* 5 */
 	PS3_DEV_TYPE_SB_GPIO = 6,
 	PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC,	/* 14 */
+	PS3_DEV_TYPE_NOACCESS = 255,
 };
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -129,24 +131,28 @@
 /* repository bus enumerators */
 
 struct ps3_repository_device {
+	enum ps3_bus_type bus_type;
 	unsigned int bus_index;
+	unsigned int bus_id;
+	enum ps3_dev_type dev_type;
 	unsigned int dev_index;
-	struct ps3_device_id did;
+	unsigned int dev_id;
 };
 
-int ps3_repository_find_device(enum ps3_bus_type bus_type,
-	enum ps3_dev_type dev_type,
-	const struct ps3_repository_device *start_dev,
-	struct ps3_repository_device *dev);
-static inline int ps3_repository_find_first_device(
-	enum ps3_bus_type bus_type, enum ps3_dev_type dev_type,
-	struct ps3_repository_device *dev)
+static inline struct ps3_repository_device *ps3_repository_bump_device(
+	struct ps3_repository_device *repo)
 {
-	return ps3_repository_find_device(bus_type, dev_type, NULL, dev);
+	repo->dev_index++;
+	return repo;
 }
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_device(struct ps3_repository_device *repo);
+int ps3_repository_find_devices(enum ps3_bus_type bus_type,
+	int (*callback)(const struct ps3_repository_device *repo));
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+	unsigned int *bus_index);
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id);
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len);
 
 /* repository block device info */
@@ -216,4 +222,19 @@
 int ps3_repository_read_spu_resource_id(unsigned int res_index,
 	enum ps3_spu_resource_type* resource_type, unsigned int *resource_id);
 
+/* repository vuart info */
+
+int ps3_repository_read_vuart_av_port(unsigned int *port);
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port);
+
+/* Page table entries */
+#define IOPTE_PP_W		0x8000000000000000ul /* protection: write */
+#define IOPTE_PP_R		0x4000000000000000ul /* protection: read */
+#define IOPTE_M			0x2000000000000000ul /* coherency required */
+#define IOPTE_SO_R		0x1000000000000000ul /* ordering: writes */
+#define IOPTE_SO_RW             0x1800000000000000ul /* ordering: r & w */
+#define IOPTE_RPN_Mask		0x07fffffffffff000ul /* RPN */
+#define IOPTE_H			0x0000000000000800ul /* cache hint */
+#define IOPTE_IOID_Mask		0x00000000000007fful /* ioid */
+
 #endif
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index ae586a0..8cc37cfe 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -138,7 +138,7 @@
 		pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 		dump_node_name(lpar_id, n1, n2, n3, n4);
-		return result;
+		return -ENOENT;
 	}
 
 	dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
@@ -155,7 +155,7 @@
 		pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
 			__func__, __LINE__, v2);
 
-	return result;
+	return 0;
 }
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -314,324 +314,140 @@
 		reg_index, bus_addr, len);
 }
 
-#if defined(DEBUG)
-int ps3_repository_dump_resource_info(unsigned int bus_index,
-	unsigned int dev_index)
+
+
+int ps3_repository_find_device(struct ps3_repository_device *repo)
 {
-	int result = 0;
-	unsigned int res_index;
+	int result;
+	struct ps3_repository_device tmp = *repo;
+	unsigned int num_dev;
 
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-		bus_index, dev_index);
+	BUG_ON(repo->bus_index > 10);
+	BUG_ON(repo->dev_index > 10);
 
-	for (res_index = 0; res_index < 10; res_index++) {
-		enum ps3_interrupt_type intr_type;
-		unsigned int interrupt_id;
+	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 
-		result = ps3_repository_read_dev_intr(bus_index, dev_index,
-			res_index, &intr_type, &interrupt_id);
-
-		if (result) {
-			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_intr"
-					" (%u:%u) failed\n", __func__, __LINE__,
-					bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
-			__func__, __LINE__, bus_index, dev_index, intr_type,
-			interrupt_id);
-	}
-
-	for (res_index = 0; res_index < 10; res_index++) {
-		enum ps3_reg_type reg_type;
-		u64 bus_addr;
-		u64 len;
-
-		result = ps3_repository_read_dev_reg(bus_index, dev_index,
-			res_index, &reg_type, &bus_addr, &len);
-
-		if (result) {
-			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_reg"
-					" (%u:%u) failed\n", __func__, __LINE__,
-					bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
-			__func__, __LINE__, bus_index, dev_index, reg_type,
-			bus_addr, len);
-	}
-
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
-}
-
-static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index)
-{
-	int result = 0;
-	unsigned int num_regions, region_index;
-	u64 port, blk_size, num_blocks;
-
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-		bus_index, dev_index);
-
-	result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port,
-		&blk_size, &num_blocks, &num_regions);
 	if (result) {
-		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
-			" (%u:%u) failed\n", __func__, __LINE__,
-			bus_index, dev_index);
-		goto out;
+		pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
+		return result;
 	}
 
-	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
-		 "%lu, num_regions %u\n",
-		 __func__, __LINE__, bus_index, dev_index, port,
-		 blk_size, num_blocks, num_regions);
+	pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n",
+		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
+		num_dev);
 
-	for (region_index = 0; region_index < num_regions; region_index++) {
-		unsigned int region_id;
-		u64 region_start, region_size;
-
-		result = ps3_repository_read_stor_dev_region(bus_index,
-			dev_index, region_index, &region_id, &region_start,
-			&region_size);
-		if (result) {
-			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
-				  " (%u:%u) failed\n", __func__, __LINE__,
-				  bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
-			 __func__, __LINE__, bus_index, dev_index, region_id,
-			 region_start, region_size);
+	if (tmp.dev_index >= num_dev) {
+		pr_debug("%s:%d: no device found\n", __func__, __LINE__);
+		return -ENODEV;
 	}
 
-out:
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
+	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
+		&tmp.dev_type);
+
+	if (result) {
+		pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__);
+		return result;
+	}
+
+	result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
+		&tmp.dev_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,
+		__LINE__);
+		return result;
+	}
+
+	pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n",
+		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
+
+	*repo = tmp;
+	return 0;
 }
 
-static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type,
-			    unsigned int num_dev)
+int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
+	int (*callback)(const struct ps3_repository_device *repo))
 {
 	int result = 0;
-	unsigned int dev_index;
+	struct ps3_repository_device repo;
 
-	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
+	pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
 
-	for (dev_index = 0; dev_index < num_dev; dev_index++) {
-		enum ps3_dev_type dev_type;
-		unsigned int dev_id;
+	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
 
-		result = ps3_repository_read_dev_type(bus_index, dev_index,
-			&dev_type);
-
-		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_type"
-				" (%u:%u) failed\n", __func__, __LINE__,
-				bus_index, dev_index);
-			break;
-		}
-
-		result = ps3_repository_read_dev_id(bus_index, dev_index,
-			&dev_id);
-
-		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_id"
-				" (%u:%u) failed\n", __func__, __LINE__,
-				bus_index, dev_index);
-			continue;
-		}
-
-		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
-			__LINE__, bus_index, dev_index, dev_type, dev_id);
-
-		ps3_repository_dump_resource_info(bus_index, dev_index);
-
-		if (bus_type == PS3_BUS_TYPE_STORAGE)
-			dump_stor_dev_info(bus_index, dev_index);
-	}
-
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
-}
-
-int ps3_repository_dump_bus_info(void)
-{
-	int result = 0;
-	unsigned int bus_index;
-
-	pr_debug(" -> %s:%d\n", __func__, __LINE__);
-
-	for (bus_index = 0; bus_index < 10; bus_index++) {
-		enum ps3_bus_type bus_type;
-		unsigned int bus_id;
-		unsigned int num_dev;
-
-		result = ps3_repository_read_bus_type(bus_index, &bus_type);
+		result = ps3_repository_read_bus_type(repo.bus_index,
+			&repo.bus_type);
 
 		if (result) {
 			pr_debug("%s:%d read_bus_type(%u) failed\n",
-				__func__, __LINE__, bus_index);
+				__func__, __LINE__, repo.bus_index);
 			break;
 		}
 
-		result = ps3_repository_read_bus_id(bus_index, &bus_id);
+		if (repo.bus_type != bus_type) {
+			pr_debug("%s:%d: skip, bus_type %u\n", __func__,
+				__LINE__, repo.bus_type);
+			continue;
+		}
+
+		result = ps3_repository_read_bus_id(repo.bus_index,
+			&repo.bus_id);
 
 		if (result) {
 			pr_debug("%s:%d read_bus_id(%u) failed\n",
-				__func__, __LINE__, bus_index);
+				__func__, __LINE__, repo.bus_index);
 			continue;
 		}
 
-		if (bus_index != bus_id)
-			pr_debug("%s:%d bus_index != bus_id\n",
-				__func__, __LINE__);
+		for (repo.dev_index = 0; ; repo.dev_index++) {
+			result = ps3_repository_find_device(&repo);
 
-		result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
+			if (result == -ENODEV) {
+				result = 0;
+				break;
+			} else if (result)
+				break;
 
-		if (result) {
-			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
-				__func__, __LINE__, bus_index);
-			continue;
+			result = callback(&repo);
+
+			if (result) {
+				pr_debug("%s:%d: abort at callback\n", __func__,
+					__LINE__);
+				break;
+			}
 		}
-
-		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
-			__func__, __LINE__, bus_index, bus_type, bus_id,
-			num_dev);
-
-		dump_device_info(bus_index, bus_type, num_dev);
+		break;
 	}
 
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
-#endif /* defined(DEBUG) */
 
-static int find_device(unsigned int bus_index, unsigned int num_dev,
-	unsigned int start_dev_index, enum ps3_dev_type dev_type,
-	struct ps3_repository_device *dev)
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+	unsigned int *bus_index)
 {
-	int result = 0;
-	unsigned int dev_index;
+	unsigned int i;
+	enum ps3_bus_type type;
+	int error;
 
-	pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
-
-	dev->dev_index = UINT_MAX;
-
-	for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
-		enum ps3_dev_type x;
-
-		result = ps3_repository_read_dev_type(bus_index, dev_index,
-			&x);
-
-		if (result) {
-			pr_debug("%s:%d read_dev_type failed\n",
-				__func__, __LINE__);
-			return result;
-		}
-
-		if (x == dev_type)
-			break;
-	}
-
-	if (dev_index == num_dev)
-		return -1;
-
-	pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
-		__func__, __LINE__, dev_type, dev_index);
-
-	result = ps3_repository_read_dev_id(bus_index, dev_index,
-		&dev->did.dev_id);
-
-	if (result) {
-		pr_debug("%s:%d read_dev_id failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	dev->dev_index = dev_index;
-
-	pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
-		dev->did.dev_id);
-
-	return result;
-}
-
-int ps3_repository_find_device (enum ps3_bus_type bus_type,
-	enum ps3_dev_type dev_type,
-	const struct ps3_repository_device *start_dev,
-	struct ps3_repository_device *dev)
-{
-	int result = 0;
-	unsigned int bus_index;
-	unsigned int num_dev;
-
-	pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
-		bus_type, dev_type);
-
-	BUG_ON(start_dev && start_dev->bus_index > 10);
-
-	for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
-		bus_index++) {
-		enum ps3_bus_type x;
-
-		result = ps3_repository_read_bus_type(bus_index, &x);
-
-		if (result) {
+	for (i = from; i < 10; i++) {
+		error = ps3_repository_read_bus_type(i, &type);
+		if (error) {
 			pr_debug("%s:%d read_bus_type failed\n",
 				__func__, __LINE__);
-			dev->bus_index = UINT_MAX;
-			return result;
+			*bus_index = UINT_MAX;
+			return error;
 		}
-		if (x == bus_type)
-			break;
+		if (type == bus_type) {
+			*bus_index = i;
+			return 0;
+		}
 	}
-
-	if (bus_index >= 10)
-		return -ENODEV;
-
-	pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
-		__func__, __LINE__, bus_type, bus_index);
-
-	result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
-
-	if (result) {
-		pr_debug("%s:%d read_bus_num_dev failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	result = find_device(bus_index, num_dev, start_dev
-		? start_dev->dev_index + 1 : 0, dev_type, dev);
-
-	if (result) {
-		pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
-		return result;
-	}
-
-	result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
-
-	if (result) {
-		pr_debug("%s:%d read_bus_id failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	dev->bus_index = bus_index;
-
-	pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
-		__func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
-
-	return result;
+	*bus_index = UINT_MAX;
+	return -ENODEV;
 }
 
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
 {
 	int result = 0;
@@ -645,8 +461,8 @@
 		enum ps3_interrupt_type t;
 		unsigned int id;
 
-		result = ps3_repository_read_dev_intr(dev->bus_index,
-			dev->dev_index, res_index, &t, &id);
+		result = ps3_repository_read_dev_intr(repo->bus_index,
+			repo->dev_index, res_index, &t, &id);
 
 		if (result) {
 			pr_debug("%s:%d read_dev_intr failed\n",
@@ -669,7 +485,7 @@
 	return result;
 }
 
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
 {
 	int result = 0;
@@ -684,8 +500,8 @@
 		u64 a;
 		u64 l;
 
-		result = ps3_repository_read_dev_reg(dev->bus_index,
-			dev->dev_index, res_index, &t, &a, &l);
+		result = ps3_repository_read_dev_reg(repo->bus_index,
+			repo->dev_index, res_index, &t, &a, &l);
 
 		if (result) {
 			pr_debug("%s:%d read_dev_reg failed\n",
@@ -965,6 +781,36 @@
 	return result;
 }
 
+int ps3_repository_read_vuart_av_port(unsigned int *port)
+{
+	int result;
+	u64 v1;
+
+	result = read_node(PS3_LPAR_ID_CURRENT,
+		make_first_field("bi", 0),
+		make_field("vir_uart", 0),
+		make_field("port", 0),
+		make_field("avset", 0),
+		&v1, 0);
+	*port = v1;
+	return result;
+}
+
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
+{
+	int result;
+	u64 v1;
+
+	result = read_node(PS3_LPAR_ID_CURRENT,
+		make_first_field("bi", 0),
+		make_field("vir_uart", 0),
+		make_field("port", 0),
+		make_field("sysmgr", 0),
+		&v1, 0);
+	*port = v1;
+	return result;
+}
+
 /**
   * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
   * address: lpar address of cell_ext_os_area
@@ -1026,3 +872,205 @@
 	return result ? result
 		: ps3_repository_read_tb_freq(node_id, tb_freq);
 }
+
+#if defined(DEBUG)
+
+int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
+{
+	int result = 0;
+	unsigned int res_index;
+
+	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+		repo->bus_index, repo->dev_index);
+
+	for (res_index = 0; res_index < 10; res_index++) {
+		enum ps3_interrupt_type intr_type;
+		unsigned int interrupt_id;
+
+		result = ps3_repository_read_dev_intr(repo->bus_index,
+			repo->dev_index, res_index, &intr_type, &interrupt_id);
+
+		if (result) {
+			if (result !=  LV1_NO_ENTRY)
+				pr_debug("%s:%d ps3_repository_read_dev_intr"
+					" (%u:%u) failed\n", __func__, __LINE__,
+					repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			intr_type, interrupt_id);
+	}
+
+	for (res_index = 0; res_index < 10; res_index++) {
+		enum ps3_reg_type reg_type;
+		u64 bus_addr;
+		u64 len;
+
+		result = ps3_repository_read_dev_reg(repo->bus_index,
+			repo->dev_index, res_index, &reg_type, &bus_addr, &len);
+
+		if (result) {
+			if (result !=  LV1_NO_ENTRY)
+				pr_debug("%s:%d ps3_repository_read_dev_reg"
+					" (%u:%u) failed\n", __func__, __LINE__,
+					repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			reg_type, bus_addr, len);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int dump_stor_dev_info(struct ps3_repository_device *repo)
+{
+	int result = 0;
+	unsigned int num_regions, region_index;
+	u64 port, blk_size, num_blocks;
+
+	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+		repo->bus_index, repo->dev_index);
+
+	result = ps3_repository_read_stor_dev_info(repo->bus_index,
+		repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
+	if (result) {
+		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
+			" (%u:%u) failed\n", __func__, __LINE__,
+			repo->bus_index, repo->dev_index);
+		goto out;
+	}
+
+	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
+		 "%lu, num_regions %u\n",
+		 __func__, __LINE__, repo->bus_index, repo->dev_index, port,
+		 blk_size, num_blocks, num_regions);
+
+	for (region_index = 0; region_index < num_regions; region_index++) {
+		unsigned int region_id;
+		u64 region_start, region_size;
+
+		result = ps3_repository_read_stor_dev_region(repo->bus_index,
+			repo->dev_index, region_index, &region_id,
+			&region_start, &region_size);
+		if (result) {
+			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
+				  " (%u:%u) failed\n", __func__, __LINE__,
+				  repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			region_id, region_start, region_size);
+	}
+
+out:
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int dump_device_info(struct ps3_repository_device *repo,
+	unsigned int num_dev)
+{
+	int result = 0;
+
+	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
+
+	for (repo->dev_index = 0; repo->dev_index < num_dev;
+		repo->dev_index++) {
+
+		result = ps3_repository_read_dev_type(repo->bus_index,
+			repo->dev_index, &repo->dev_type);
+
+		if (result) {
+			pr_debug("%s:%d ps3_repository_read_dev_type"
+				" (%u:%u) failed\n", __func__, __LINE__,
+				repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		result = ps3_repository_read_dev_id(repo->bus_index,
+			repo->dev_index, &repo->dev_id);
+
+		if (result) {
+			pr_debug("%s:%d ps3_repository_read_dev_id"
+				" (%u:%u) failed\n", __func__, __LINE__,
+				repo->bus_index, repo->dev_index);
+			continue;
+		}
+
+		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
+			__LINE__, repo->bus_index, repo->dev_index,
+			repo->dev_type, repo->dev_id);
+
+		ps3_repository_dump_resource_info(repo);
+
+		if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
+			dump_stor_dev_info(repo);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+int ps3_repository_dump_bus_info(void)
+{
+	int result = 0;
+	struct ps3_repository_device repo;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	memset(&repo, 0, sizeof(repo));
+
+	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
+		unsigned int num_dev;
+
+		result = ps3_repository_read_bus_type(repo.bus_index,
+			&repo.bus_type);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_type(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			break;
+		}
+
+		result = ps3_repository_read_bus_id(repo.bus_index,
+			&repo.bus_id);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_id(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			continue;
+		}
+
+		if (repo.bus_index != repo.bus_id)
+			pr_debug("%s:%d bus_index != bus_id\n",
+				__func__, __LINE__);
+
+		result = ps3_repository_read_bus_num_dev(repo.bus_index,
+			&num_dev);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			continue;
+		}
+
+		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
+			__func__, __LINE__, repo.bus_index, repo.bus_type,
+			repo.bus_id, num_dev);
+
+		dump_device_info(&repo, num_dev);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+#endif /* defined(DEBUG) */
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 9353967..aa05288 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -37,28 +37,36 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 #if !defined(CONFIG_SMP)
 static void smp_send_stop(void) {}
 #endif
 
-int ps3_get_firmware_version(union ps3_firmware_version *v)
+static union ps3_firmware_version ps3_firmware_version;
+
+void ps3_get_firmware_version(union ps3_firmware_version *v)
 {
-	int result = lv1_get_version_info(&v->raw);
-
-	if (result) {
-		v->raw = 0;
-		return -1;
-	}
-
-	return result;
+	*v = ps3_firmware_version;
 }
 EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
 
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev)
+{
+	union ps3_firmware_version x;
+
+	x.pad = 0;
+	x.major = major;
+	x.minor = minor;
+	x.rev = rev;
+
+	return (ps3_firmware_version.raw - x.raw);
+}
+EXPORT_SYMBOL_GPL(ps3_compare_firmware_version);
+
 static void ps3_power_save(void)
 {
 	/*
@@ -99,7 +107,8 @@
 	while(1);
 }
 
-#ifdef CONFIG_FB_PS3
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
+    defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
 static void prealloc(struct ps3_prealloc *p)
 {
 	if (!p->size)
@@ -115,12 +124,15 @@
 	printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
 	       p->address);
 }
+#endif
 
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE)
 struct ps3_prealloc ps3fb_videomemory = {
-    .name = "ps3fb videomemory",
-    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
-    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+	.name = "ps3fb videomemory",
+	.size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+	.align = 1024*1024		/* the GPU requires 1 MiB alignment */
 };
+EXPORT_SYMBOL_GPL(ps3fb_videomemory);
 #define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
 
 static int __init early_parse_ps3fb(char *p)
@@ -137,6 +149,30 @@
 #define prealloc_ps3fb_videomemory()	do { } while (0)
 #endif
 
+#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
+struct ps3_prealloc ps3flash_bounce_buffer = {
+	.name = "ps3flash bounce buffer",
+	.size = 256*1024,
+	.align = 256*1024
+};
+EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer);
+#define prealloc_ps3flash_bounce_buffer()	prealloc(&ps3flash_bounce_buffer)
+
+static int __init early_parse_ps3flash(char *p)
+{
+	if (!p)
+		return 1;
+
+	if (!strcmp(p, "off"))
+		ps3flash_bounce_buffer.size = 0;
+
+	return 0;
+}
+early_param("ps3flash", early_parse_ps3flash);
+#else
+#define prealloc_ps3flash_bounce_buffer()	do { } while (0)
+#endif
+
 static int ps3_set_dabr(u64 dabr)
 {
 	enum {DABR_USER = 1, DABR_KERNEL = 2,};
@@ -146,13 +182,13 @@
 
 static void __init ps3_setup_arch(void)
 {
-	union ps3_firmware_version v;
 
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
-	ps3_get_firmware_version(&v);
-	printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor,
-		v.rev);
+	lv1_get_version_info(&ps3_firmware_version.raw);
+	printk(KERN_INFO "PS3 firmware version %u.%u.%u\n",
+	       ps3_firmware_version.major, ps3_firmware_version.minor,
+	       ps3_firmware_version.rev);
 
 	ps3_spu_set_platform();
 	ps3_map_htab();
@@ -166,6 +202,8 @@
 #endif
 
 	prealloc_ps3fb_videomemory();
+	prealloc_ps3flash_bounce_buffer();
+
 	ppc_md.power_save = ps3_power_save;
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
@@ -184,7 +222,7 @@
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
 	dt_root = of_get_flat_dt_root();
-	if (!of_flat_dt_is_compatible(dt_root, "PS3"))
+	if (!of_flat_dt_is_compatible(dt_root, "sony,ps3"))
 		return 0;
 
 	powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
@@ -201,31 +239,12 @@
 #if defined(CONFIG_KEXEC)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-	DBG(" -> %s:%d\n", __func__, __LINE__);
+	int cpu = smp_processor_id();
 
-	if (secondary) {
-		int cpu;
-		for_each_online_cpu(cpu)
-			if (cpu)
-				ps3_smp_cleanup_cpu(cpu);
-	} else
-		ps3_smp_cleanup_cpu(0);
+	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
-	DBG(" <- %s:%d\n", __func__, __LINE__);
-}
-
-static void ps3_machine_kexec(struct kimage *image)
-{
-	unsigned long ppe_id;
-
-	DBG(" -> %s:%d\n", __func__, __LINE__);
-
-	lv1_get_logical_ppe_id(&ppe_id);
-	lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
-	ps3_mm_shutdown();
-	ps3_mm_vas_destroy();
-
-	default_machine_kexec(image);
+	ps3_smp_cleanup_cpu(cpu);
+	ps3_shutdown_IRQ(cpu);
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
@@ -247,7 +266,7 @@
 	.power_off			= ps3_power_off,
 #if defined(CONFIG_KEXEC)
 	.kexec_cpu_down			= ps3_kexec_cpu_down,
-	.machine_kexec			= ps3_machine_kexec,
+	.machine_kexec			= default_machine_kexec,
 	.machine_kexec_prepare		= default_machine_kexec_prepare,
 	.machine_crash_shutdown		= default_machine_crash_shutdown,
 #endif
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c
index 53416ec..f0b12f2 100644
--- a/arch/powerpc/platforms/ps3/smp.c
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -27,9 +27,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 static irqreturn_t ipi_function_handler(int irq, void *msg)
@@ -39,11 +39,11 @@
 }
 
 /**
-  * virqs - a per cpu array of virqs for ipi use
+  * ps3_ipi_virqs - a per cpu array of virqs for ipi use
   */
 
 #define MSG_COUNT 4
-static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]);
+static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
 
 static const char *names[MSG_COUNT] = {
 	"ipi call",
@@ -62,7 +62,7 @@
 		return;
 	}
 
-	virq = per_cpu(virqs, target)[msg];
+	virq = per_cpu(ps3_ipi_virqs, target)[msg];
 	result = ps3_send_event_locally(virq);
 
 	if (result)
@@ -94,13 +94,13 @@
 static void __init ps3_smp_setup_cpu(int cpu)
 {
 	int result;
-	unsigned int *virqs = per_cpu(virqs, cpu);
+	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
 	int i;
 
 	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
 	/*
-	 * Check assumptions on virqs[] indexing. If this
+	 * Check assumptions on ps3_ipi_virqs[] indexing. If this
 	 * check fails, then a different mapping of PPC_MSG_
 	 * to index needs to be setup.
 	 */
@@ -132,13 +132,13 @@
 
 void ps3_smp_cleanup_cpu(int cpu)
 {
-	unsigned int *virqs = per_cpu(virqs, cpu);
+	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
 	int i;
 
 	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
 	for (i = 0; i < MSG_COUNT; i++) {
-		free_irq(virqs[i], (void*)(long)i);
+		/* Can't call free_irq from interrupt context. */
 		ps3_event_receive_port_destroy(virqs[i]);
 		virqs[i] = NO_IRQ;
 	}
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index 651437c..502d80e 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -182,15 +182,18 @@
 {
 	struct table {char* name; unsigned long addr; unsigned long size;};
 
-	spu_pdata(spu)->shadow = __ioremap(
-		spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
-		pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED);
+	spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr,
+					       sizeof(struct spe_shadow),
+					       pgprot_val(PAGE_READONLY) |
+					       _PAGE_NO_CACHE);
 	if (!spu_pdata(spu)->shadow) {
 		pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
 		goto fail_ioremap;
 	}
 
-	spu->local_store = ioremap(spu->local_store_phys, LS_SIZE);
+	spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys,
+		LS_SIZE, _PAGE_NO_CACHE);
+
 	if (!spu->local_store) {
 		pr_debug("%s:%d: ioremap local_store failed\n",
 			__func__, __LINE__);
@@ -199,6 +202,7 @@
 
 	spu->problem = ioremap(spu->problem_phys,
 		sizeof(struct spu_problem));
+
 	if (!spu->problem) {
 		pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__);
 		goto fail_ioremap;
@@ -206,6 +210,7 @@
 
 	spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr,
 		sizeof(struct spu_priv2));
+
 	if (!spu->priv2) {
 		pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__);
 		goto fail_ioremap;
@@ -400,11 +405,13 @@
 		}
 	}
 
-	if (result)
+	if (result) {
 		printk(KERN_WARNING "%s:%d: Error initializing spus\n",
 			__func__, __LINE__);
+		return result;
+	}
 
-	return result;
+	return num_resource_id;
 }
 
 const struct spu_management_ops spu_management_ps3_ops = {
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 6bda510..4bb634a 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -30,22 +30,228 @@
 
 #include "platform.h"
 
+static struct device ps3_system_bus = {
+	.bus_id = "ps3_system",
+};
+
+/* FIXME: need device usage counters! */
+struct {
+	struct mutex mutex;
+	int sb_11; /* usb 0 */
+	int sb_12; /* usb 0 */
+	int gpu;
+} static usage_hack;
+
+static int ps3_is_device(struct ps3_system_bus_device *dev,
+			 unsigned int bus_id, unsigned int dev_id)
+{
+	return dev->bus_id == bus_id && dev->dev_id == dev_id;
+}
+
+static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	BUG_ON(!dev->bus_id);
+	mutex_lock(&usage_hack.mutex);
+
+	if (ps3_is_device(dev, 1, 1)) {
+		usage_hack.sb_11++;
+		if (usage_hack.sb_11 > 1) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	if (ps3_is_device(dev, 1, 2)) {
+		usage_hack.sb_12++;
+		if (usage_hack.sb_12 > 1) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	result = lv1_open_device(dev->bus_id, dev->dev_id, 0);
+
+	if (result) {
+		pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__,
+			__LINE__, ps3_result(result));
+			result = -EPERM;
+	}
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	BUG_ON(!dev->bus_id);
+	mutex_lock(&usage_hack.mutex);
+
+	if (ps3_is_device(dev, 1, 1)) {
+		usage_hack.sb_11--;
+		if (usage_hack.sb_11) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	if (ps3_is_device(dev, 1, 2)) {
+		usage_hack.sb_12--;
+		if (usage_hack.sb_12) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	result = lv1_close_device(dev->bus_id, dev->dev_id);
+	BUG_ON(result);
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	mutex_lock(&usage_hack.mutex);
+
+	usage_hack.gpu++;
+	if (usage_hack.gpu > 1) {
+		result = 0;
+		goto done;
+	}
+
+	result = lv1_gpu_open(0);
+
+	if (result) {
+		pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__,
+			__LINE__, ps3_result(result));
+			result = -EPERM;
+	}
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	mutex_lock(&usage_hack.mutex);
+
+	usage_hack.gpu--;
+	if (usage_hack.gpu) {
+		result = 0;
+		goto done;
+	}
+
+	result = lv1_gpu_close();
+	BUG_ON(result);
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+int ps3_open_hv_device(struct ps3_system_bus_device *dev)
+{
+	BUG_ON(!dev);
+	pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+	switch (dev->match_id) {
+	case PS3_MATCH_ID_EHCI:
+	case PS3_MATCH_ID_OHCI:
+	case PS3_MATCH_ID_GELIC:
+	case PS3_MATCH_ID_STOR_DISK:
+	case PS3_MATCH_ID_STOR_ROM:
+	case PS3_MATCH_ID_STOR_FLASH:
+		return ps3_open_hv_device_sb(dev);
+
+	case PS3_MATCH_ID_SOUND:
+	case PS3_MATCH_ID_GRAPHICS:
+		return ps3_open_hv_device_gpu(dev);
+
+	case PS3_MATCH_ID_AV_SETTINGS:
+	case PS3_MATCH_ID_SYSTEM_MANAGER:
+		pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+			__LINE__, dev->match_id);
+		pr_debug("%s:%d: bus_id: %u\n", __func__,
+			__LINE__, dev->bus_id);
+		BUG();
+		return -EINVAL;
+
+	default:
+		break;
+	}
+
+	pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+		dev->match_id);
+	BUG();
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_open_hv_device);
+
+int ps3_close_hv_device(struct ps3_system_bus_device *dev)
+{
+	BUG_ON(!dev);
+	pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+	switch (dev->match_id) {
+	case PS3_MATCH_ID_EHCI:
+	case PS3_MATCH_ID_OHCI:
+	case PS3_MATCH_ID_GELIC:
+	case PS3_MATCH_ID_STOR_DISK:
+	case PS3_MATCH_ID_STOR_ROM:
+	case PS3_MATCH_ID_STOR_FLASH:
+		return ps3_close_hv_device_sb(dev);
+
+	case PS3_MATCH_ID_SOUND:
+	case PS3_MATCH_ID_GRAPHICS:
+		return ps3_close_hv_device_gpu(dev);
+
+	case PS3_MATCH_ID_AV_SETTINGS:
+	case PS3_MATCH_ID_SYSTEM_MANAGER:
+		pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+			__LINE__, dev->match_id);
+		pr_debug("%s:%d: bus_id: %u\n", __func__,
+			__LINE__, dev->bus_id);
+		BUG();
+		return -EINVAL;
+
+	default:
+		break;
+	}
+
+	pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+		dev->match_id);
+	BUG();
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_close_hv_device);
+
 #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)
 static void _dump_mmio_region(const struct ps3_mmio_region* r,
 	const char* func, int line)
 {
-	pr_debug("%s:%d: dev       %u:%u\n", func, line, r->did.bus_id,
-		r->did.dev_id);
+	pr_debug("%s:%d: dev       %u:%u\n", func, line, r->dev->bus_id,
+		r->dev->dev_id);
 	pr_debug("%s:%d: bus_addr  %lxh\n", func, line, r->bus_addr);
 	pr_debug("%s:%d: len       %lxh\n", func, line, r->len);
 	pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr);
 }
 
-int ps3_mmio_region_create(struct ps3_mmio_region *r)
+static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r)
 {
 	int result;
 
-	result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id,
+	result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
 		r->bus_addr, r->len, r->page_size, &r->lpar_addr);
 
 	if (result) {
@@ -57,13 +263,26 @@
 	dump_mmio_region(r);
 	return result;
 }
+
+static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r)
+{
+	/* device specific; do nothing currently */
+	return 0;
+}
+
+int ps3_mmio_region_create(struct ps3_mmio_region *r)
+{
+	return r->mmio_ops->create(r);
+}
 EXPORT_SYMBOL_GPL(ps3_mmio_region_create);
 
-int ps3_free_mmio_region(struct ps3_mmio_region *r)
+static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r)
 {
 	int result;
 
-	result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id,
+	dump_mmio_region(r);
+;
+	result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
 		r->lpar_addr);
 
 	if (result)
@@ -73,14 +292,60 @@
 	r->lpar_addr = 0;
 	return result;
 }
+
+static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r)
+{
+	/* device specific; do nothing currently */
+	return 0;
+}
+
+
+int ps3_free_mmio_region(struct ps3_mmio_region *r)
+{
+	return r->mmio_ops->free(r);
+}
+
 EXPORT_SYMBOL_GPL(ps3_free_mmio_region);
 
+static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = {
+	.create = ps3_sb_mmio_region_create,
+	.free = ps3_sb_free_mmio_region
+};
+
+static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = {
+	.create = ps3_ioc0_mmio_region_create,
+	.free = ps3_ioc0_free_mmio_region
+};
+
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+	enum ps3_mmio_page_size page_size)
+{
+	r->dev = dev;
+	r->bus_addr = bus_addr;
+	r->len = len;
+	r->page_size = page_size;
+	switch (dev->dev_type) {
+	case PS3_DEVICE_TYPE_SB:
+		r->mmio_ops = &ps3_mmio_sb_region_ops;
+		break;
+	case PS3_DEVICE_TYPE_IOC0:
+		r->mmio_ops = &ps3_mmio_ioc0_region_ops;
+		break;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_mmio_region_init);
+
 static int ps3_system_bus_match(struct device *_dev,
 	struct device_driver *_drv)
 {
 	int result;
-	struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv);
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
 	result = dev->match_id == drv->match_id;
 
@@ -92,32 +357,14 @@
 
 static int ps3_system_bus_probe(struct device *_dev)
 {
-	int result;
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
-	struct ps3_system_bus_driver *drv =
-		to_ps3_system_bus_driver(_dev->driver);
+	int result = 0;
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	struct ps3_system_bus_driver *drv;
 
-	result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0);
+	BUG_ON(!dev);
+	pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
 
-	if (result) {
-		pr_debug("%s:%d: lv1_open_device failed (%d)\n",
-			__func__, __LINE__, result);
-		result = -EACCES;
-		goto clean_none;
-	}
-
-	if (dev->d_region->did.bus_id) {
-		result = ps3_dma_region_create(dev->d_region);
-
-		if (result) {
-			pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n",
-				__func__, __LINE__, result);
-			BUG_ON("check region type");
-			result = -EINVAL;
-			goto clean_device;
-		}
-	}
-
+	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
 	BUG_ON(!drv);
 
 	if (drv->probe)
@@ -126,56 +373,127 @@
 		pr_info("%s:%d: %s no probe method\n", __func__, __LINE__,
 			dev->core.bus_id);
 
-	if (result) {
-		pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__);
-		goto clean_dma;
-	}
-
-	return result;
-
-clean_dma:
-	ps3_dma_region_free(dev->d_region);
-clean_device:
-	lv1_close_device(dev->did.bus_id, dev->did.dev_id);
-clean_none:
+	pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
 	return result;
 }
 
 static int ps3_system_bus_remove(struct device *_dev)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
-	struct ps3_system_bus_driver *drv =
-		to_ps3_system_bus_driver(_dev->driver);
+	int result = 0;
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	struct ps3_system_bus_driver *drv;
+
+	BUG_ON(!dev);
+	pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
+
+	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+	BUG_ON(!drv);
 
 	if (drv->remove)
-		drv->remove(dev);
+		result = drv->remove(dev);
 	else
-		pr_info("%s:%d: %s no remove method\n", __func__, __LINE__,
-			dev->core.bus_id);
+		dev_dbg(&dev->core, "%s:%d %s: no remove method\n",
+			__func__, __LINE__, drv->core.name);
 
-	ps3_dma_region_free(dev->d_region);
-	ps3_free_mmio_region(dev->m_region);
-	lv1_close_device(dev->did.bus_id, dev->did.dev_id);
+	pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
+	return result;
+}
 
+static void ps3_system_bus_shutdown(struct device *_dev)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	struct ps3_system_bus_driver *drv;
+
+	BUG_ON(!dev);
+
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
+
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		return;
+	}
+
+	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+
+	BUG_ON(!drv);
+
+	dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__,
+		dev->core.bus_id, drv->core.name);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+	else if (drv->remove) {
+		dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n",
+			__func__, __LINE__, drv->core.name);
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n",
+			__func__, __LINE__, drv->core.name);
+		BUG();
+	}
+
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+}
+
+static int ps3_system_bus_uevent(struct device *_dev, char **envp,
+				 int num_envp, char *buffer, int buffer_size)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	int i = 0, length = 0;
+
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+			   &length, "MODALIAS=ps3:%d",
+			   dev->match_id))
+		return -ENOMEM;
+
+	envp[i] = NULL;
 	return 0;
 }
 
+static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
+	char *buf)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);
+
+	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute ps3_system_bus_dev_attrs[] = {
+	__ATTR_RO(modalias),
+	__ATTR_NULL,
+};
+
 struct bus_type ps3_system_bus_type = {
 	.name = "ps3_system_bus",
 	.match = ps3_system_bus_match,
+	.uevent = ps3_system_bus_uevent,
 	.probe = ps3_system_bus_probe,
 	.remove = ps3_system_bus_remove,
+	.shutdown = ps3_system_bus_shutdown,
+	.dev_attrs = ps3_system_bus_dev_attrs,
 };
 
-int __init ps3_system_bus_init(void)
+static int __init ps3_system_bus_init(void)
 {
 	int result;
 
 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 		return -ENODEV;
 
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	mutex_init(&usage_hack.mutex);
+
+	result = device_register(&ps3_system_bus);
+	BUG_ON(result);
+
 	result = bus_register(&ps3_system_bus_type);
 	BUG_ON(result);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
@@ -185,16 +503,13 @@
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
  */
-
 static void * ps3_alloc_coherent(struct device *_dev, size_t size,
-	dma_addr_t *dma_handle, gfp_t flag)
+				      dma_addr_t *dma_handle, gfp_t flag)
 {
 	int result;
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	unsigned long virt_addr;
 
-	BUG_ON(!dev->d_region->bus_addr);
-
 	flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
 	flag |= __GFP_ZERO;
 
@@ -205,7 +520,8 @@
 		goto clean_none;
 	}
 
-	result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle);
+	result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle,
+			     IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
 
 	if (result) {
 		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -226,7 +542,7 @@
 static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
 	dma_addr_t dma_handle)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
 	ps3_dma_unmap(dev->d_region, dma_handle, size);
 	free_pages((unsigned long)vaddr, get_order(size));
@@ -239,15 +555,16 @@
  * byte within the page as vaddr.
  */
 
-static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size,
+static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size,
 	enum dma_data_direction direction)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	int result;
 	unsigned long bus_addr;
 
 	result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
-		&bus_addr);
+			     &bus_addr,
+			     IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M);
 
 	if (result) {
 		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -257,10 +574,44 @@
 	return bus_addr;
 }
 
+static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr,
+				      size_t size,
+				      enum dma_data_direction direction)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	int result;
+	unsigned long bus_addr;
+	u64 iopte_flag;
+
+	iopte_flag = IOPTE_M;
+	switch (direction) {
+	case DMA_BIDIRECTIONAL:
+		iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW;
+		break;
+	case DMA_TO_DEVICE:
+		iopte_flag |= IOPTE_PP_R | IOPTE_SO_R;
+		break;
+	case DMA_FROM_DEVICE:
+		iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW;
+		break;
+	default:
+		/* not happned */
+		BUG();
+	};
+	result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
+			     &bus_addr, iopte_flag);
+
+	if (result) {
+		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
+			__func__, __LINE__, result);
+	}
+	return bus_addr;
+}
+
 static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
 	size_t size, enum dma_data_direction direction)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	int result;
 
 	result = ps3_dma_unmap(dev->d_region, dma_addr, size);
@@ -271,20 +622,20 @@
 	}
 }
 
-static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
+static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
 	enum dma_data_direction direction)
 {
 #if defined(CONFIG_PS3_DYNAMIC_DMA)
 	BUG_ON("do");
 	return -EPERM;
 #else
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	int i;
 
 	for (i = 0; i < nents; i++, sg++) {
 		int result = ps3_dma_map(dev->d_region,
 			page_to_phys(sg->page) + sg->offset, sg->length,
-			&sg->dma_address);
+					 &sg->dma_address, 0);
 
 		if (result) {
 			pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -299,7 +650,15 @@
 #endif
 }
 
-static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg,
+static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
+			   int nents,
+			   enum dma_data_direction direction)
+{
+	BUG();
+	return 0;
+}
+
+static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
 	int nents, enum dma_data_direction direction)
 {
 #if defined(CONFIG_PS3_DYNAMIC_DMA)
@@ -307,18 +666,34 @@
 #endif
 }
 
+static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
+			    int nents, enum dma_data_direction direction)
+{
+	BUG();
+}
+
 static int ps3_dma_supported(struct device *_dev, u64 mask)
 {
 	return mask >= DMA_32BIT_MASK;
 }
 
-static struct dma_mapping_ops ps3_dma_ops = {
+static struct dma_mapping_ops ps3_sb_dma_ops = {
 	.alloc_coherent = ps3_alloc_coherent,
 	.free_coherent = ps3_free_coherent,
-	.map_single = ps3_map_single,
+	.map_single = ps3_sb_map_single,
 	.unmap_single = ps3_unmap_single,
-	.map_sg = ps3_map_sg,
-	.unmap_sg = ps3_unmap_sg,
+	.map_sg = ps3_sb_map_sg,
+	.unmap_sg = ps3_sb_unmap_sg,
+	.dma_supported = ps3_dma_supported
+};
+
+static struct dma_mapping_ops ps3_ioc0_dma_ops = {
+	.alloc_coherent = ps3_alloc_coherent,
+	.free_coherent = ps3_free_coherent,
+	.map_single = ps3_ioc0_map_single,
+	.unmap_single = ps3_unmap_single,
+	.map_sg = ps3_ioc0_map_sg,
+	.unmap_sg = ps3_ioc0_unmap_sg,
 	.dma_supported = ps3_dma_supported
 };
 
@@ -328,7 +703,7 @@
 
 static void ps3_system_bus_release_device(struct device *_dev)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	kfree(dev);
 }
 
@@ -343,18 +718,37 @@
 int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
 {
 	int result;
-	static unsigned int dev_count = 1;
+	static unsigned int dev_ioc0_count;
+	static unsigned int dev_sb_count;
+	static unsigned int dev_vuart_count;
 
-	dev->core.parent = NULL;
+	if (!dev->core.parent)
+		dev->core.parent = &ps3_system_bus;
 	dev->core.bus = &ps3_system_bus_type;
 	dev->core.release = ps3_system_bus_release_device;
 
-	dev->core.archdata.of_node = NULL;
-	dev->core.archdata.dma_ops = &ps3_dma_ops;
-	dev->core.archdata.numa_node = 0;
+	switch (dev->dev_type) {
+	case PS3_DEVICE_TYPE_IOC0:
+		dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops;
+		snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+			"ioc0_%02x", ++dev_ioc0_count);
+		break;
+	case PS3_DEVICE_TYPE_SB:
+		dev->core.archdata.dma_ops = &ps3_sb_dma_ops;
+		snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+			"sb_%02x", ++dev_sb_count);
 
-	snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x",
-		dev_count++);
+		break;
+	case PS3_DEVICE_TYPE_VUART:
+		snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+			"vuart_%02x", ++dev_vuart_count);
+		break;
+	default:
+		BUG();
+	};
+
+	dev->core.archdata.of_node = NULL;
+	dev->core.archdata.numa_node = 0;
 
 	pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id);
 
@@ -368,9 +762,15 @@
 {
 	int result;
 
+	pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
 	drv->core.bus = &ps3_system_bus_type;
 
 	result = driver_register(&drv->core);
+	pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 	return result;
 }
 
@@ -378,7 +778,9 @@
 
 void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv)
 {
+	pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 	driver_unregister(&drv->core);
+	pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 }
 
 EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 1bae8b1..802a9cc 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -39,7 +39,7 @@
 }
 
 #define dump_time(_a) _dump_time(_a, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_time(int time, const char* func,
+static void __maybe_unused _dump_time(int time, const char *func,
 	int line)
 {
 	struct rtc_time tm;
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index ae1fc92..992ba67 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -8,7 +8,7 @@
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
-obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o
+obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
 obj-$(CONFIG_KEXEC)	+= kexec.o
 obj-$(CONFIG_PCI)	+= pci.o pci_dlpar.o
 obj-$(CONFIG_PCI_MSI)	+= msi.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 5f3e6d8..b877039 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1,6 +1,8 @@
 /*
  * eeh.c
- * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation
+ * Copyright IBM Corporation 2001, 2005, 2006
+ * Copyright Dave Engebretsen & Todd Inglett 2001
+ * Copyright Linas Vepstas 2005, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -15,6 +17,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 
 #include <linux/delay.h>
@@ -117,7 +121,6 @@
 static unsigned long ignored_check;
 static unsigned long total_mmio_ffs;
 static unsigned long false_positives;
-static unsigned long ignored_failures;
 static unsigned long slot_resets;
 
 #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
@@ -505,6 +508,7 @@
 		printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
 		       ret, dn->full_name);
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -513,6 +517,7 @@
 	 * they are empty when they don't have children. */
 	if ((rets[0] == 5) && (dn->child == NULL)) {
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -522,6 +527,7 @@
 		printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
 		       ret, dn->full_name);
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -529,6 +535,7 @@
 	/* If not the kind of error we know about, punt. */
 	if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -921,6 +928,7 @@
 	pdn->eeh_mode = 0;
 	pdn->eeh_check_count = 0;
 	pdn->eeh_freeze_count = 0;
+	pdn->eeh_false_positives = 0;
 
 	if (status && strcmp(status, "ok") != 0)
 		return NULL;	/* ignore devices with bad status */
@@ -1139,7 +1147,8 @@
 	pdn = PCI_DN(dn);
 	pdn->pcidev = dev;
 
-	pci_addr_cache_insert_device (dev);
+	pci_addr_cache_insert_device(dev);
+	eeh_sysfs_add_device(dev);
 }
 
 void eeh_add_device_tree_late(struct pci_bus *bus)
@@ -1178,6 +1187,7 @@
 	printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
 #endif
 	pci_addr_cache_remove_device(dev);
+	eeh_sysfs_remove_device(dev);
 
 	dn = pci_device_to_OF_node(dev);
 	if (PCI_DN(dn)->pcidev) {
@@ -1214,11 +1224,10 @@
 				"check not wanted=%ld\n"
 				"eeh_total_mmio_ffs=%ld\n"
 				"eeh_false_positives=%ld\n"
-				"eeh_ignored_failures=%ld\n"
 				"eeh_slot_resets=%ld\n",
 				no_device, no_dn, no_cfg_addr, 
 				ignored_check, total_mmio_ffs, 
-				false_positives, ignored_failures, 
+				false_positives,
 				slot_resets);
 	}
 
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index f2bae04..e49c815 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -2,7 +2,8 @@
  * eeh_cache.c
  * PCI address cache; allows the lookup of PCI devices based on I/O address
  *
- * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation
+ * Copyright IBM Corporation 2004
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 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
@@ -295,6 +296,8 @@
 			continue;
 		pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
 		PCI_DN(dn)->pcidev = dev;
+
+		eeh_sysfs_add_device(dev);
 	}
 
 #ifdef DEBUG
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 161a584..15e015e 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -1,6 +1,7 @@
 /*
  * PCI Error Recovery Driver for RPA-compliant PPC64 platform.
- * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
+ * Copyright IBM Corp. 2004 2005
+ * Copyright Linas Vepstas <linas@linas.org> 2004, 2005
  *
  * All rights reserved.
  *
@@ -19,8 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <linas@us.ibm.com>
- *
+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c
new file mode 100644
index 0000000..15e13b5
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c
@@ -0,0 +1,87 @@
+/*
+ * Sysfs entries for PCI Error Recovery for PAPR-compliant platform.
+ * Copyright IBM Corporation 2007
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2007
+ *
+ * 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 comments and feedback to Linas Vepstas <linas@austin.ibm.com>
+ */
+#include <linux/pci.h>
+#include <asm/ppc-pci.h>
+#include <asm/pci-bridge.h>
+#include <linux/kobject.h>
+
+/**
+ * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic
+ * @_name: name of file in sysfs directory
+ * @_memb: name of member in struct pci_dn to access
+ * @_format: printf format for display
+ *
+ * All of the attributes look very similar, so just
+ * auto-gen a cut-n-paste routine to display them.
+ */
+#define EEH_SHOW_ATTR(_name,_memb,_format)               \
+static ssize_t eeh_show_##_name(struct device *dev,      \
+		struct device_attribute *attr, char *buf)          \
+{                                                        \
+	struct pci_dev *pdev = to_pci_dev(dev);               \
+	struct device_node *dn = pci_device_to_OF_node(pdev); \
+	struct pci_dn *pdn;                                   \
+	                                                      \
+	if (!dn || PCI_DN(dn) == NULL)                        \
+		return 0;                                          \
+	                                                      \
+	pdn = PCI_DN(dn);                                     \
+	return sprintf(buf, _format "\n", pdn->_memb);        \
+}                                                        \
+static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
+
+
+EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x");
+EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d");
+EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d");
+EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d");
+
+void eeh_sysfs_add_device(struct pci_dev *pdev)
+{
+	int rc=0;
+
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+
+	if (rc)
+		printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
+}
+
+void eeh_sysfs_remove_device(struct pci_dev *pdev)
+{
+	device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+}
+
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 362dfbc..8cc6eee 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -373,12 +373,23 @@
 {
 	unsigned long size_bytes = 1UL << ppc64_pft_size;
 	unsigned long hpte_count = size_bytes >> 4;
-	unsigned long dummy1, dummy2;
+	unsigned long dummy1, dummy2, dword0;
+	long lpar_rc;
 	int i;
 
 	/* TODO: Use bulk call */
-	for (i = 0; i < hpte_count; i++)
-		plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+	for (i = 0; i < hpte_count; i++) {
+		/* dont remove HPTEs with VRMA mappings */
+		lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG,
+						&dummy1, &dummy2);
+		if (lpar_rc == H_NOT_FOUND) {
+			lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1);
+			if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK)
+				!= HPTE_V_VRMA_MASK))
+				/* Can be hpte for 1TB Seg. So remove it */
+				plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+		}
+	}
 }
 
 /*
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index ffaf6c5..47f0e08 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -110,8 +110,6 @@
 			}
 		}
 	}
-
-	eeh_add_device_tree_late(bus);
 }
 EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
 
@@ -139,6 +137,8 @@
 
 	/* Make the discovered devices available */
 	pci_bus_add_devices(child_bus);
+
+	eeh_add_device_tree_late(child_bus);
 	return 0;
 }
 
@@ -171,6 +171,7 @@
 		if (!list_empty(&bus->devices)) {
 			pcibios_fixup_new_pci_devices(bus, 0);
 			pci_bus_add_devices(bus);
+			eeh_add_device_tree_late(bus);
 		}
 	} else if (mode == PCI_PROBE_NORMAL) {
 		/* use legacy probe */
@@ -179,6 +180,7 @@
 		if (num) {
 			pcibios_fixup_new_pci_devices(bus, 1);
 			pci_bus_add_devices(bus);
+			eeh_add_device_tree_late(bus);
 		}
 
 		list_for_each_entry(dev, &bus->devices, bus_list)
@@ -200,8 +202,6 @@
 	rtas_setup_phb(phb);
 	pci_process_bridge_OF_ranges(phb, dn, 0);
 
-	pci_setup_phb_io_dynamic(phb, primary);
-
 	pci_devs_phb_init_dynamic(phb);
 
 	if (dn->child)
@@ -210,6 +210,7 @@
 	scan_phb(phb);
 	pcibios_fixup_new_pci_devices(phb->bus, 0);
 	pci_bus_add_devices(phb->bus);
+	eeh_add_device_tree_late(phb->bus);
 
 	return phb;
 }
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 2e4d10c..d003c80 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -108,6 +108,21 @@
 	return rc;
 }
 
+/* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */
+static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex,
+		unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
+{
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex);
+
+	*old_pteh_ret = retbuf[0];
+	*old_ptel_ret = retbuf[1];
+
+	return rc;
+}
+
 static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
 		unsigned long avpn)
 {
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 2729d55..61e19f7 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -33,6 +33,8 @@
 static inline void setup_kexec_cpu_down_mpic(void) { }
 #endif
 
+extern void pSeries_final_fixup(void);
+
 /* Poweron flag used for enabling auto ups restart */
 extern unsigned long rtas_poweron_auto;
 
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 5aa97af..c02f874 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -123,7 +123,7 @@
 	strcpy(np->full_name, path);
 
 	np->properties = proplist;
-	OF_MARK_DYNAMIC(np);
+	of_node_set_flag(np, OF_DYNAMIC);
 	kref_init(&np->kref);
 
 	np->parent = derive_parent(path);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index a031d99..59e69f0 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -399,6 +399,7 @@
 	 * a good time to find other work to dispatch.
 	 */
 	get_lppaca()->idle = 1;
+	get_lppaca()->donate_dedicated_cpu = 1;
 
 	/*
 	 * We come in with interrupts disabled, and need_resched()
@@ -431,6 +432,7 @@
 
 out:
 	HMT_medium();
+	get_lppaca()->donate_dedicated_cpu = 0;
 	get_lppaca()->idle = 0;
 }
 
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index f1df942..5bd90a7 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -156,9 +156,9 @@
 
 
 #ifdef CONFIG_SMP
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
-	unsigned int server;
+	int server;
 	/* For the moment only implement delivery to all cpus or one cpu */
 	cpumask_t cpumask = irq_desc[virq].affinity;
 	cpumask_t tmp = CPU_MASK_NONE;
@@ -166,22 +166,25 @@
 	if (!distribute_irqs)
 		return default_server;
 
-	if (cpus_equal(cpumask, CPU_MASK_ALL)) {
-		server = default_distrib_server;
-	} else {
+	if (!cpus_equal(cpumask, CPU_MASK_ALL)) {
 		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));
+		server = first_cpu(tmp);
+
+		if (server < NR_CPUS)
+			return get_hard_smp_processor_id(server);
+
+		if (strict_check)
+			return -1;
 	}
 
-	return server;
+	if (cpus_equal(cpu_online_map, cpu_present_map))
+		return default_distrib_server;
 
+	return default_server;
 }
 #else
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
 	return default_server;
 }
@@ -192,7 +195,7 @@
 {
 	unsigned int irq;
 	int call_status;
-	unsigned int server;
+	int server;
 
 	pr_debug("xics: unmask virq %d\n", virq);
 
@@ -201,7 +204,7 @@
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
 
-	server = get_irq_server(virq);
+	server = get_irq_server(virq, 0);
 
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
 				DEFAULT_PRIORITY);
@@ -398,8 +401,7 @@
 	unsigned int irq;
 	int status;
 	int xics_status[2];
-	unsigned long newmask;
-	cpumask_t tmp = CPU_MASK_NONE;
+	int irq_server;
 
 	irq = (unsigned int)irq_map[virq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
@@ -413,18 +415,21 @@
 		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));
+	/*
+	 * For the moment only implement delivery to all cpus or one cpu.
+	 * Get current irq_server for the given irq
+	 */
+	irq_server = get_irq_server(irq, 1);
+	if (irq_server == -1) {
+		char cpulist[128];
+		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+		printk(KERN_WARNING "xics_set_affinity: No online cpus in "
+				"the mask %s for irq %d\n", cpulist, virq);
+		return;
 	}
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
-				irq, newmask, xics_status[1]);
+				irq, irq_server, xics_status[1]);
 
 	if (status) {
 		printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index c3ce0bd..f65078c 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -5,7 +5,6 @@
 mpic-msi-obj-$(CONFIG_PCI_MSI)	+= mpic_msi.o mpic_u3msi.o
 obj-$(CONFIG_MPIC)		+= mpic.o $(mpic-msi-obj-y)
 
-obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_MPC106)	+= grackle.o
 obj-$(CONFIG_PPC_DCR)		+= dcr.o
 obj-$(CONFIG_PPC_DCR_NATIVE)	+= dcr-low.o
@@ -13,16 +12,19 @@
 obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
-obj-$(CONFIG_FSL_PCIE)		+= fsl_pcie.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
 mv64x60-$(CONFIG_PCI)		+= mv64x60_pci.o
 obj-$(CONFIG_MV64X60)		+= $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o
+obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc_cmos_setup.o
 
 # contains only the suspend handler for time
+ifeq ($(CONFIG_RTC_CLASS),)
 obj-$(CONFIG_PM)		+= timer.o
+endif
 
 ifeq ($(CONFIG_PPC_MERGE),y)
+obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
 obj-$(CONFIG_PPC_83xx)		+= ipic.o
 obj-$(CONFIG_4xx)		+= uic.o
diff --git a/arch/powerpc/sysdev/fsl_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c
deleted file mode 100644
index 041c07e..0000000
--- a/arch/powerpc/sysdev/fsl_pcie.c
+++ /dev/null
@@ -1,171 +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.
- *
- * "Temporary" MPC8548 Errata file -
- * The standard indirect_pci code should work with future silicon versions.
- */
-
-#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/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-
-#define PCI_CFG_OUT out_be32
-
-/* ERRATA PCI-Ex 14 PCIE Controller timeout */
-#define PCIE_FIX		out_be32(hose->cfg_addr+0x4, 0x0400ffff)
-
-
-static int
-indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
-		     int len, u32 *val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	volatile void __iomem *cfg_data;
-	u32 temp;
-
-	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Possible artifact of CDCpp50937 needs further investigation */
-	if (devfn != 0x0 && bus->number == 0xff)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	PCIE_FIX;
-	if (bus->number == 0xff) {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000000 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-	} else {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000001 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-	}
-
-	/*
-	 * Note: the caller has already checked that offset is
-	 * suitably aligned and that len is 1, 2 or 4.
-	 */
-	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
-	cfg_data = hose->cfg_data;
-	PCIE_FIX;
-	temp = in_le32(cfg_data);
-	switch (len) {
-	case 1:
-		*val = (temp >> (((offset & 3))*8)) & 0xff;
-		break;
-	case 2:
-		*val = (temp >> (((offset & 3))*8)) & 0xffff;
-		break;
-	default:
-		*val = temp;
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
-		      int len, u32 val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	volatile void __iomem *cfg_data;
-	u32 temp;
-
-	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Possible artifact of CDCpp50937 needs further investigation */
-	if (devfn != 0x0 && bus->number == 0xff)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	PCIE_FIX;
-	if (bus->number == 0xff) {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000000 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-	} else {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000001 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-        }
-
-	/*
-	 * Note: the caller has already checked that offset is
-	 * suitably aligned and that len is 1, 2 or 4.
-	 */
-	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
-	cfg_data = hose->cfg_data;
-	switch (len) {
-	case 1:
-		PCIE_FIX;
-		temp = in_le32(cfg_data);
-		temp = (temp & ~(0xff << ((offset & 3) * 8))) |
-			(val << ((offset & 3) * 8));
-		PCIE_FIX;
-		out_le32(cfg_data, temp);
-		break;
-	case 2:
-		PCIE_FIX;
-		temp = in_le32(cfg_data);
-		temp = (temp & ~(0xffff << ((offset & 3) * 8)));
-		temp |= (val << ((offset & 3) * 8)) ;
-		PCIE_FIX;
-		out_le32(cfg_data, temp);
-		break;
-	default:
-		PCIE_FIX;
-		out_le32(cfg_data, val);
-		break;
-	}
-	PCIE_FIX;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops indirect_pcie_ops = {
-	indirect_read_config_pcie,
-	indirect_write_config_pcie
-};
-
-void __init
-setup_indirect_pcie_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_pcie_ops;
-}
-
-void __init
-setup_indirect_pcie(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_pcie_nomap(hose, addr, data);
-}
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index cad1757..c0ddc80 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -1028,6 +1028,19 @@
 
 arch_initcall(fs_enet_of_init);
 
+static int __init fsl_pcmcia_of_init(void)
+{
+	struct device_node *np = NULL;
+	/*
+	 * Register all the devices which type is "pcmcia"
+	 */
+	while ((np = of_find_compatible_node(np,
+			"pcmcia", "fsl,pq-pcmcia")) != NULL)
+			    of_platform_device_create(np, "m8xx-pcmcia", NULL);
+	return 0;
+}
+
+arch_initcall(fsl_pcmcia_of_init);
 
 static const char *smc_regs = "regs";
 static const char *smc_pram = "pram";
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index e714884..c7e6e85 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -33,18 +33,27 @@
 	struct pci_controller *hose = bus->sysdata;
 	volatile void __iomem *cfg_data;
 	u8 cfg_type = 0;
+	u32 bus_no, reg;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 	
-	if (hose->set_cfg_type)
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_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)));
+	bus_no = (bus->number == hose->first_busno) ?
+			hose->self_busno : bus->number;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+		reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+	else
+		reg = offset & 0xfc;
+
+	PCI_CFG_OUT(hose->cfg_addr,
+		 (0x80000000 | (bus_no << 16)
+		  | (devfn << 8) | reg | cfg_type));
 
 	/*
 	 * Note: the caller has already checked that offset is
@@ -72,18 +81,33 @@
 	struct pci_controller *hose = bus->sysdata;
 	volatile void __iomem *cfg_data;
 	u8 cfg_type = 0;
+	u32 bus_no, reg;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
-	if (hose->set_cfg_type)
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_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)));
+	bus_no = (bus->number == hose->first_busno) ?
+			hose->self_busno : bus->number;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+		reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+	else
+		reg = offset & 0xfc;
+
+	PCI_CFG_OUT(hose->cfg_addr,
+		 (0x80000000 | (bus_no << 16)
+		  | (devfn << 8) | reg | cfg_type));
+
+	/* surpress setting of PCI_PRIMARY_BUS */
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
+		if ((offset == PCI_PRIMARY_BUS) &&
+			(bus->number == hose->first_busno))
+		val &= 0xffffff00;
 
 	/*
 	 * Note: the caller has already checked that offset is
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h
index afa2ee6..9fe00ee 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.h
+++ b/arch/powerpc/sysdev/mpc8xx_pic.h
@@ -4,9 +4,16 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-extern struct hw_interrupt_type mpc8xx_pic;
-
 int mpc8xx_pic_init(void);
 unsigned int mpc8xx_get_irq(void);
 
+/*
+ * Some internal interrupt registers use an 8-bit mask for the interrupt
+ * level instead of a number.
+ */
+static inline uint mk_int_int_mask(uint mask)
+{
+	return (1 << (7 - (mask/2)));
+}
+
 #endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 4b0a9c8..b618fa6 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -12,6 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/console.h>
 #include <linux/mv643xx.h>
 #include <linux/platform_device.h>
 
@@ -420,3 +421,30 @@
 	return err;
 }
 arch_initcall(mv64x60_device_setup);
+
+static int __init mv64x60_add_mpsc_console(void)
+{
+	struct device_node *np = NULL;
+	const char *prop;
+
+	prop = of_get_property(of_chosen, "linux,stdout-path", NULL);
+	if (prop == NULL)
+		goto not_mpsc;
+
+	np = of_find_node_by_path(prop);
+	if (!np)
+		goto not_mpsc;
+
+	if (!of_device_is_compatible(np, "marvell,mpsc"))
+		goto not_mpsc;
+
+	prop = of_get_property(np, "block-index", NULL);
+	if (!prop)
+		goto not_mpsc;
+
+	add_preferred_console("ttyMM", *(int *)prop, NULL);
+
+not_mpsc:
+	return 0;
+}
+console_initcall(mv64x60_add_mpsc_console);
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
index b5aef4c..45db86c 100644
--- a/arch/powerpc/sysdev/mv64x60_pci.c
+++ b/arch/powerpc/sysdev/mv64x60_pci.c
@@ -137,18 +137,15 @@
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 		       " bus 0\n", dev->full_name);
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
 
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
-
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
 	setup_indirect_pci(hose, rsrc.start, rsrc.start + 4);
-	hose->bus_offset = hose->first_busno;
+	hose->self_busno = hose->first_busno;
 
 	printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. "
 	       "Firmware bus number: %d->%d\n",
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index ac12a44..f970e54 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -40,6 +41,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
 
 int ucc_set_type(int ucc_num, struct ucc_common *regs,
 		 enum ucc_speed_type speed)
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 9143236..3df202e 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -19,6 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
@@ -70,6 +71,7 @@
 	printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
 		  (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
 }
+EXPORT_SYMBOL(ucc_fast_dump_regs);
 
 u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
 {
@@ -85,11 +87,13 @@
 	default: return QE_CR_SUBBLOCK_INVALID;
 	}
 }
+EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock);
 
 void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
 {
 	out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
 }
+EXPORT_SYMBOL(ucc_fast_transmit_on_demand);
 
 void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
@@ -110,6 +114,7 @@
 	}
 	out_be32(&uf_regs->gumr, gumr);
 }
+EXPORT_SYMBOL(ucc_fast_enable);
 
 void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
@@ -130,6 +135,7 @@
 	}
 	out_be32(&uf_regs->gumr, gumr);
 }
+EXPORT_SYMBOL(ucc_fast_disable);
 
 int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
 {
@@ -341,6 +347,7 @@
 	*uccf_ret = uccf;
 	return 0;
 }
+EXPORT_SYMBOL(ucc_fast_init);
 
 void ucc_fast_free(struct ucc_fast_private * uccf)
 {
@@ -355,3 +362,4 @@
 
 	kfree(uccf);
 }
+EXPORT_SYMBOL(ucc_fast_free);
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
new file mode 100644
index 0000000..e276048
--- /dev/null
+++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
@@ -0,0 +1,49 @@
+/*
+ * Setup code for PC-style Real-Time Clock.
+ *
+ * Author: Wade Farnsworth <wfarnsworth@mvista.com>
+ *
+ * 2007 (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/platform_device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/prom.h>
+
+static int  __init add_rtc(void)
+{
+	struct device_node *np;
+	struct platform_device *pd;
+	struct resource res;
+	int ret;
+
+	np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00");
+	if (!np)
+		return -ENODEV;
+
+	ret = of_address_to_resource(np, 0, &res);
+	of_node_put(np);
+	if (ret)
+		return ret;
+
+	/*
+	 * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h.  Verify that the
+	 * address provided by the device node matches.
+	 */
+	if (res.start != RTC_PORT(0))
+		return -EINVAL;
+
+	pd = platform_device_register_simple("rtc_cmos", -1,
+					     &res, 1);
+	if (IS_ERR(pd))
+		return PTR_ERR(pd);
+
+	return 0;
+}
+fs_initcall(add_rtc);
diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c
index 4a01748..e81e7ec 100644
--- a/arch/powerpc/sysdev/timer.c
+++ b/arch/powerpc/sysdev/timer.c
@@ -24,7 +24,12 @@
 
 	/* get current RTC time and convert to seconds */
 	get_rtc_time(&cur_rtc_tm);
-	rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time);
+	cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900,
+			      cur_rtc_tm.tm_mon + 1,
+			      cur_rtc_tm.tm_mday,
+			      cur_rtc_tm.tm_hour,
+			      cur_rtc_tm.tm_min,
+			      cur_rtc_tm.tm_sec);
 
 	diff = cur_rtc_time - suspend_rtc_time;
 
@@ -44,7 +49,12 @@
 	WARN_ON(!ppc_md.get_rtc_time);
 
 	get_rtc_time(&suspend_rtc_tm);
-	rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time);
+	suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900,
+				  suspend_rtc_tm.tm_mon + 1,
+				  suspend_rtc_tm.tm_mday,
+				  suspend_rtc_tm.tm_hour,
+				  suspend_rtc_tm.tm_min,
+				  suspend_rtc_tm.tm_sec);
 
 	return 0;
 }
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 7d3b09b..a113d80 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -72,12 +72,11 @@
 	int ret;
 
 	for (np = NULL, i = 0;
-	     (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
+	     (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL;
 	     i++) {
 		struct resource r[2];
-		struct device_node *phy;
+		struct device_node *phy, *mdio;
 		hw_info tsi_eth_data;
-		const unsigned int *id;
 		const unsigned int *phy_id;
 		const void *mac_addr;
 		const phandle *ph;
@@ -111,6 +110,13 @@
 		if (mac_addr)
 			memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
 
+		ph = of_get_property(np, "mdio-handle", NULL);
+		mdio = of_find_node_by_phandle(*ph);
+		ret = of_address_to_resource(mdio, 0, &res);
+		of_node_put(mdio);
+		if (ret)
+			goto unreg;
+
 		ph = of_get_property(np, "phy-handle", NULL);
 		phy = of_find_node_by_phandle(*ph);
 
@@ -119,20 +125,25 @@
 			goto unreg;
 		}
 
-		id = of_get_property(phy, "reg", NULL);
-		phy_id = of_get_property(phy, "phy-id", NULL);
-		ret = of_address_to_resource(phy, 0, &res);
-		if (ret) {
-			of_node_put(phy);
-			goto unreg;
-		}
+		phy_id = of_get_property(phy, "reg", NULL);
+
 		tsi_eth_data.regs = r[0].start;
 		tsi_eth_data.phyregs = res.start;
 		tsi_eth_data.phy = *phy_id;
 		tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
-		if (of_device_is_compatible(phy, "bcm54xx"))
+
+		/* Some boards with the TSI108 bridge (e.g. Holly)
+		 * have a miswiring of the ethernet PHYs which
+		 * requires a workaround.  The special
+		 * "txc-rxc-delay-disable" property enables this
+		 * workaround.  FIXME: Need to port the tsi108_eth
+		 * driver itself to phylib and use a non-misleading
+		 * name for the workaround flag - it's not actually to
+		 * do with the model of PHY in use */
+		if (of_get_property(phy, "txc-rxc-delay-disable", NULL))
 			tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
 		of_node_put(phy);
+
 		ret =
 		    platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
 					     sizeof(hw_info));
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 2153163..90db8a7 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -64,9 +64,10 @@
 			   int offset, int len, u32 val)
 {
 	volatile unsigned char *cfg_addr;
+	struct pci_controller *hose = bus->sysdata;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfunc))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfunc))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -149,10 +150,11 @@
 			  int len, u32 * val)
 {
 	volatile unsigned char *cfg_addr;
+	struct pci_controller *hose = bus->sysdata;
 	u32 temp;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -219,14 +221,12 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(dev);
 
 	if (!hose) {
 		printk("PCI Host bridge init failed\n");
 		return -ENOMEM;
 	}
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 28fdf4f..669e656 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2634,7 +2634,7 @@
 __initcall(setup_xmon_sysrq);
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-int __initdata xmon_early, xmon_off;
+static int __initdata xmon_early, xmon_off;
 
 static int __init early_parse_xmon(char *p)
 {
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index d319f9b..0da5536 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -328,7 +328,7 @@
 	mtspr   SPRN_L1CSR0,r3
 	isync
 	blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
 	mfspr	r3,SPRN_L1CSR1
 	ori	r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
 	mtspr	SPRN_L1CSR1,r3
@@ -355,7 +355,7 @@
 _GLOBAL(__flush_icache_range)
 BEGIN_FTR_SECTION
 	blr				/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	li	r5,L1_CACHE_BYTES-1
 	andc	r3,r3,r5
 	subf	r4,r3,r4
@@ -472,7 +472,7 @@
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	rlwinm	r3,r3,0,0,19			/* Get page base address */
 	li	r4,4096/L1_CACHE_BYTES	/* Number of lines in a page */
 	mtctr	r4
@@ -500,7 +500,7 @@
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	mfmsr	r10
 	rlwinm	r0,r10,0,28,26			/* clear DR */
 	mtmsr	r0
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index a416520..63f0a98 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -64,7 +64,6 @@
 
 EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(clear_user_page);
-EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(machine_check_exception);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index c79704f..967c1ef 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -526,7 +526,7 @@
 	 * 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)) {
+	if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) {
 		dcache_bsize = cur_cpu_spec->dcache_bsize;
 		icache_bsize = cur_cpu_spec->icache_bsize;
 		ucache_bsize = 0;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index aea100b..3f3b292 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -92,6 +92,7 @@
 	if (nl)
 		printk("\n");
 	show_regs(fp);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 	/* do_exit() should take care of panic'ing from an interrupt
 	 * context so we don't handle it here
@@ -619,7 +620,7 @@
 			return;
 
 		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
-		    report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
+		    report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
 			regs->nip += 4;
 			return;
 		}
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
index fa29740..4ff260b 100644
--- a/arch/ppc/mm/tlb.c
+++ b/arch/ppc/mm/tlb.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/pagemap.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 6f21110..3c56654 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -69,9 +69,6 @@
 
 TODC_ALLOC();
 
-unsigned char ucBoardRev;
-unsigned char ucBoardRevMaj, ucBoardRevMin;
-
 extern unsigned char prep_nvram_read_val(int addr);
 extern void prep_nvram_write_val(int addr,
 				 unsigned char val);
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 9569415..543795b 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -7,6 +7,7 @@
 
 wdt-mpc8xx-$(CONFIG_8xx_WDT)	+= m8xx_wdt.o
 
+obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPCBUG_NVRAM)	+= prep_nvram.o
 obj-$(CONFIG_PPC_OCP)		+= ocp.o
 obj-$(CONFIG_IBM_OCP)		+= ibm_ocp.o
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
new file mode 100644
index 0000000..83b323a
--- /dev/null
+++ b/arch/ppc/syslib/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/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c
index 1654678..ace4ec0 100644
--- a/arch/ppc/syslib/virtex_devices.c
+++ b/arch/ppc/syslib/virtex_devices.c
@@ -71,6 +71,21 @@
 	}, \
 }
 
+/*
+ * ML300/ML403 Video Device: shortcut macro for single instance
+ */
+#define XPAR_TFT(num) { \
+	.name = "xilinxfb", \
+	.id = num, \
+	.num_resources = 1, \
+	.resource = (struct resource[]) { \
+		{ \
+			.start = XPAR_TFT_##num##_BASEADDR, \
+			.end = XPAR_TFT_##num##_BASEADDR+7, \
+			.flags = IORESOURCE_IO, \
+		}, \
+	}, \
+}
 
 /* UART 8250 driver platform data table */
 struct plat_serial8250_port virtex_serial_platform_data[] = {
@@ -146,20 +161,17 @@
 	XPAR_SYSACE(1),
 #endif
 
-	/* ML300/403 reference design framebuffer */
 #if defined(XPAR_TFT_0_BASEADDR)
-	{
-		.name		= "xilinxfb",
-		.id		= 0,
-		.num_resources	= 1,
-		.resource = (struct resource[]) {
-			{
-				.start	= XPAR_TFT_0_BASEADDR,
-				.end	= XPAR_TFT_0_BASEADDR+7,
-				.flags	= IORESOURCE_IO,
-			},
-		},
-	},
+	XPAR_TFT(0),
+#endif
+#if defined(XPAR_TFT_1_BASEADDR)
+	XPAR_TFT(1),
+#endif
+#if defined(XPAR_TFT_2_BASEADDR)
+	XPAR_TFT(2),
+#endif
+#if defined(XPAR_TFT_3_BASEADDR)
+	XPAR_TFT(3),
 #endif
 };
 
diff --git a/arch/ppc/syslib/virtex_devices.h b/arch/ppc/syslib/virtex_devices.h
index 3d4be14..9f38d92 100644
--- a/arch/ppc/syslib/virtex_devices.h
+++ b/arch/ppc/syslib/virtex_devices.h
@@ -31,4 +31,11 @@
  */
 int virtex_device_fixup(struct platform_device *dev);
 
+/* SPI Controller IP */
+struct xspi_platform_data {
+	s16 bus_num;
+	u16 num_chipselect;
+	u32 speed_hz;
+};
+
 #endif  /* __ASM_VIRTEX_DEVICES_H__ */
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 2a8f087..f4503ca 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -294,7 +294,6 @@
 static int
 do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	ptrace_area parea; 
 	int copied, ret;
 
@@ -304,10 +303,7 @@
 		/* Remove high order bit from address (only for 31 bit). */
 		addr &= PSW_ADDR_INSN;
 		/* read word at location addr. */
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (copied != sizeof(tmp))
-			return -EIO;
-		return put_user(tmp, (unsigned long __force __user *) data);
+		return generic_ptrace_peekdata(child, addr, data);
 
 	case PTRACE_PEEKUSR:
 		/* read the word at location addr in the USER area. */
@@ -318,10 +314,7 @@
 		/* Remove high order bit from address (only for 31 bit). */
 		addr &= PSW_ADDR_INSN;
 		/* write the word at location addr. */
-		copied = access_process_vm(child, addr, &data, sizeof(data),1);
-		if (copied != sizeof(data))
-			return -EIO;
-		return 0;
+		return generic_ptrace_pokedata(child, addr, data);
 
 	case PTRACE_POKEUSR:
 		/* write the word at location addr in the USER area */
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index ee9186f..8ec9def 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -262,6 +262,7 @@
 	print_modules();
 	show_regs(regs);
 	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
@@ -319,7 +320,7 @@
 		else {
 			enum bug_trap_type btt;
 
-			btt = report_bug(regs->psw.addr & PSW_ADDR_INSN);
+			btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
 			if (btt == BUG_TRAP_TYPE_WARN)
 				return;
 			die(str, regs, interruption_code);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 038179e..d8ed667 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -55,8 +55,21 @@
 config GENERIC_CLOCKEVENTS
 	def_bool n
 
+config SYS_SUPPORTS_PM
+	bool
+
 config SYS_SUPPORTS_APM_EMULATION
 	bool
+	select SYS_SUPPORTS_PM
+
+config SYS_SUPPORTS_SMP
+	bool
+
+config SYS_SUPPORTS_NUMA
+	bool
+
+config SYS_SUPPORTS_PCI
+	bool
 
 config ARCH_MAY_HAVE_PC_FDC
 	bool
@@ -81,257 +94,8 @@
 
 menu "System type"
 
-config SOLUTION_ENGINE
-	bool
-
-choice
-	prompt "SuperH system type"
-	default SH_UNKNOWN
-
-config SH_SOLUTION_ENGINE
-	bool "SolutionEngine"
-	select SOLUTION_ENGINE
-	help
-	  Select SolutionEngine if configuring for a Hitachi SH7709
-	  or SH7750 evaluation board.
-
-config SH_7722_SOLUTION_ENGINE
-	bool "SolutionEngine7722"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7722
-	help
-	  Select 7722 SolutionEngine if configuring for a Hitachi SH772
-	  evaluation board.
-
-config SH_7751_SOLUTION_ENGINE
-	bool "SolutionEngine7751"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7751
-	help
-	  Select 7751 SolutionEngine if configuring for a Hitachi SH7751
-	  evaluation board.
-	  
-config SH_7780_SOLUTION_ENGINE
-	bool "SolutionEngine7780"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7780
-	help
-	  Select 7780 SolutionEngine if configuring for a Renesas SH7780
-	  evaluation board.
-
-config SH_7300_SOLUTION_ENGINE
-	bool "SolutionEngine7300"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7300
-	help
-	  Select 7300 SolutionEngine if configuring for a Hitachi
-	  SH7300(SH-Mobile V) evaluation board.
-
-config SH_7343_SOLUTION_ENGINE
-	bool "SolutionEngine7343"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7343
-	help
-	  Select 7343 SolutionEngine if configuring for a Hitachi
-	  SH7343 (SH-Mobile 3AS) evaluation board.
-
-config SH_73180_SOLUTION_ENGINE
-       bool "SolutionEngine73180"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH73180
-	help
-	  Select 73180 SolutionEngine if configuring for a Hitachi
-	  SH73180(SH-Mobile 3) evaluation board.
-
-config SH_7751_SYSTEMH
-	bool "SystemH7751R"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select SystemH if you are configuring for a Renesas SystemH
-	  7751R evaluation board.
-
-config SH_HP6XX
-	bool "HP6XX"
-	select SYS_SUPPORTS_APM_EMULATION
-	help
-	  Select HP6XX if configuring for a HP jornada HP6xx.
-	  More information (hardware only) at
-	  <http://www.hp.com/jornada/>.
-
-config SH_SATURN
-	bool "Saturn"
-	select CPU_SUBTYPE_SH7604
-	help
-	  Select Saturn if configuring for a SEGA Saturn.
-
-config SH_DREAMCAST
-	bool "Dreamcast"
-	select CPU_SUBTYPE_SH7091
-	help
-	  Select Dreamcast if configuring for a SEGA Dreamcast.
-	  More information at
-	  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
-	  Dreamcast project is at <http://linuxdc.sourceforge.net/>.
-
-config SH_MPC1211
-	bool "Interface MPC1211"
-	help
-	  CTP/PCI-SH02 is a CPU module computer that is produced
-	  by Interface Corporation.
-	  More information at <http://www.interface.co.jp>
-
-config SH_SH03
-	bool "Interface CTP/PCI-SH03"
-	help
-	  CTP/PCI-SH03 is a CPU module computer that is produced
-	  by Interface Corporation.
-	  More information at <http://www.interface.co.jp>
-
-config SH_SECUREEDGE5410
-	bool "SecureEdge5410"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select SecureEdge5410 if configuring for a SnapGear SH board.
-	  This includes both the OEM SecureEdge products as well as the
-	  SME product line.
-
-config SH_HS7751RVOIP
-	bool "HS7751RVOIP"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select HS7751RVOIP if configuring for a Renesas Technology
-	  Sales VoIP board.
-
-config SH_7710VOIPGW
-	bool "SH7710-VOIP-GW"
-	select CPU_SUBTYPE_SH7710
-	help
-	  Select this option to build a kernel for the SH7710 based
-	  VOIP GW.
-
-config SH_RTS7751R2D
-	bool "RTS7751R2D"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select RTS7751R2D if configuring for a Renesas Technology
-	  Sales SH-Graphics board.
-
-config SH_HIGHLANDER
-	bool "Highlander"
-
-config SH_EDOSK7705
-	bool "EDOSK7705"
-	select CPU_SUBTYPE_SH7705
-
-config SH_SH4202_MICRODEV
-	bool "SH4-202 MicroDev"
-	select CPU_SUBTYPE_SH4_202
-	help
-	  Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
-	  with an SH4-202 CPU.
-
-config SH_LANDISK
-	bool "LANDISK"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  I-O DATA DEVICE, INC. "LANDISK Series" support.
-
-config SH_TITAN
-	bool "TITAN"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select Titan if you are configuring for a Nimble Microsystems
-	  NetEngine NP51R.
-
-config SH_SHMIN
-	bool "SHMIN"
-	select CPU_SUBTYPE_SH7706
-	help
-	  Select SHMIN if configuring for the SHMIN board.
-
-config SH_7206_SOLUTION_ENGINE
-	bool "SolutionEngine7206"
-	select CPU_SUBTYPE_SH7206
-	help
-	  Select 7206 SolutionEngine if configuring for a Hitachi SH7206
-	  evaluation board.
-
-config SH_7619_SOLUTION_ENGINE
-	bool "SolutionEngine7619"
-	select CPU_SUBTYPE_SH7619
-	help
-	  Select 7619 SolutionEngine if configuring for a Hitachi SH7619
-	  evaluation board.
-	
-config SH_LBOX_RE2
-	bool "L-BOX RE2"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select L-BOX RE2 if configuring for the NTT COMWARE L-BOX RE2.
-
-config SH_UNKNOWN
-	bool "BareCPU"
-	help
-	  "Bare CPU" aka "unknown" means an SH-based system which is not one
-	  of the specific ones mentioned above, which means you need to enter
-	  all sorts of stuff like CONFIG_MEMORY_START because the config
-	  system doesn't already know what it is.  You get a machine vector
-	  without any platform-specific code in it, so things like the RTC may
-	  not work.
-
-	  This option is for the early stages of porting to a new machine.
-
-endchoice
-
-source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
-source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
-source "arch/sh/boards/renesas/r7780rp/Kconfig"
-
 source "arch/sh/mm/Kconfig"
 
-config CF_ENABLER
-	bool "Compact Flash Enabler support"
-	depends on SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_SH03
-	---help---
-	  Compact Flash is a small, removable mass storage device introduced
-	  in 1994 originally as a PCMCIA device.  If you say `Y' here, you
-	  compile in support for Compact Flash devices directly connected to
-	  a SuperH processor.  A Compact Flash FAQ is available at
-	  <http://www.compactflash.org/faqs/faq.htm>.
-
-	  If your board has "Directly Connected" CompactFlash at area 5 or 6,
-	  you may want to enable this option.  Then, you can use CF as
-	  primary IDE drive (only tested for SanDisk).
-
-	  If in doubt, select 'N'.
-
-choice
-	prompt "Compact Flash Connection Area"
-	depends on CF_ENABLER
-	default CF_AREA6
-
-config CF_AREA5
-	bool "Area5"
-	help
-	  If your board has "Directly Connected" CompactFlash, You should
-	  select the area where your CF is connected to.
-
-	  - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
-	  - "Area6" if it is connected to Area 6 (0x18000000)
-
-	  "Area6" will work for most boards.
-
-config CF_AREA6
-	bool "Area6"
-
-endchoice
-
-config CF_BASE_ADDR
-	hex
-	depends on CF_ENABLER
-	default "0xb8000000" if CF_AREA6
-	default "0xb4000000" if CF_AREA5
-
 menu "Processor features"
 
 choice
@@ -351,7 +115,7 @@
 
 config SH_FPU
 	bool "FPU support"
-	depends on !CPU_SH3
+	depends on CPU_SH4
 	default y
 	help
 	  Selecting this option will enable support for SH processors that
@@ -437,6 +201,209 @@
 
 endmenu
 
+menu "Board support"
+
+config SOLUTION_ENGINE
+	bool
+
+config SH_SOLUTION_ENGINE
+	bool "SolutionEngine"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7750
+	help
+	  Select SolutionEngine if configuring for a Hitachi SH7709
+	  or SH7750 evaluation board.
+
+config SH_7206_SOLUTION_ENGINE
+	bool "SolutionEngine7206"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7206
+	help
+	  Select 7206 SolutionEngine if configuring for a Hitachi SH7206
+	  evaluation board.
+
+config SH_7619_SOLUTION_ENGINE
+	bool "SolutionEngine7619"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7619
+	help
+	  Select 7619 SolutionEngine if configuring for a Hitachi SH7619
+	  evaluation board.
+	
+config SH_7722_SOLUTION_ENGINE
+	bool "SolutionEngine7722"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7722
+	help
+	  Select 7722 SolutionEngine if configuring for a Hitachi SH772
+	  evaluation board.
+
+config SH_7751_SOLUTION_ENGINE
+	bool "SolutionEngine7751"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7751
+	help
+	  Select 7751 SolutionEngine if configuring for a Hitachi SH7751
+	  evaluation board.
+	  
+config SH_7780_SOLUTION_ENGINE
+	bool "SolutionEngine7780"
+	select SOLUTION_ENGINE
+	select SYS_SUPPORTS_PCI
+	depends on CPU_SUBTYPE_SH7780
+	help
+	  Select 7780 SolutionEngine if configuring for a Renesas SH7780
+	  evaluation board.
+
+config SH_7300_SOLUTION_ENGINE
+	bool "SolutionEngine7300"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7300
+	help
+	  Select 7300 SolutionEngine if configuring for a Hitachi
+	  SH7300(SH-Mobile V) evaluation board.
+
+config SH_7343_SOLUTION_ENGINE
+	bool "SolutionEngine7343"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7343
+	help
+	  Select 7343 SolutionEngine if configuring for a Hitachi
+	  SH7343 (SH-Mobile 3AS) evaluation board.
+
+config SH_73180_SOLUTION_ENGINE
+	bool "SolutionEngine73180"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH73180
+	help
+	  Select 73180 SolutionEngine if configuring for a Hitachi
+	  SH73180(SH-Mobile 3) evaluation board.
+
+config SH_7751_SYSTEMH
+	bool "SystemH7751R"
+	depends on CPU_SUBTYPE_SH7751R
+	help
+	  Select SystemH if you are configuring for a Renesas SystemH
+	  7751R evaluation board.
+
+config SH_HP6XX
+	bool "HP6XX"
+	select SYS_SUPPORTS_APM_EMULATION
+	select HD6446X_SERIES
+	depends on CPU_SUBTYPE_SH7709
+	help
+	  Select HP6XX if configuring for a HP jornada HP6xx.
+	  More information (hardware only) at
+	  <http://www.hp.com/jornada/>.
+
+config SH_DREAMCAST
+	bool "Dreamcast"
+	select SYS_SUPPORTS_PCI
+	depends on CPU_SUBTYPE_SH7091
+	help
+	  Select Dreamcast if configuring for a SEGA Dreamcast.
+	  More information at
+	  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
+	  Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+
+config SH_MPC1211
+	bool "Interface MPC1211"
+	depends on CPU_SUBTYPE_SH7751 && BROKEN
+	help
+	  CTP/PCI-SH02 is a CPU module computer that is produced
+	  by Interface Corporation.
+	  More information at <http://www.interface.co.jp>
+
+config SH_SH03
+	bool "Interface CTP/PCI-SH03"
+	depends on CPU_SUBTYPE_SH7751 && BROKEN
+	select SYS_SUPPORTS_PCI
+	help
+	  CTP/PCI-SH03 is a CPU module computer that is produced
+	  by Interface Corporation.
+	  More information at <http://www.interface.co.jp>
+
+config SH_SECUREEDGE5410
+	bool "SecureEdge5410"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select SecureEdge5410 if configuring for a SnapGear SH board.
+	  This includes both the OEM SecureEdge products as well as the
+	  SME product line.
+
+config SH_HS7751RVOIP
+	bool "HS7751RVOIP"
+	depends on CPU_SUBTYPE_SH7751R
+	help
+	  Select HS7751RVOIP if configuring for a Renesas Technology
+	  Sales VoIP board.
+
+config SH_7710VOIPGW
+	bool "SH7710-VOIP-GW"
+	depends on CPU_SUBTYPE_SH7710
+	help
+	  Select this option to build a kernel for the SH7710 based
+	  VOIP GW.
+
+config SH_RTS7751R2D
+	bool "RTS7751R2D"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select RTS7751R2D if configuring for a Renesas Technology
+	  Sales SH-Graphics board.
+
+config SH_HIGHLANDER
+	bool "Highlander"
+	depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
+	select SYS_SUPPORTS_PCI
+
+config SH_EDOSK7705
+	bool "EDOSK7705"
+	depends on CPU_SUBTYPE_SH7705
+
+config SH_SH4202_MICRODEV
+	bool "SH4-202 MicroDev"
+	depends on CPU_SUBTYPE_SH4_202
+	help
+	  Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
+	  with an SH4-202 CPU.
+
+config SH_LANDISK
+	bool "LANDISK"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  I-O DATA DEVICE, INC. "LANDISK Series" support.
+
+config SH_TITAN
+	bool "TITAN"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select Titan if you are configuring for a Nimble Microsystems
+	  NetEngine NP51R.
+
+config SH_SHMIN
+	bool "SHMIN"
+	depends on CPU_SUBTYPE_SH7706
+	help
+	  Select SHMIN if configuring for the SHMIN board.
+
+config SH_LBOX_RE2
+	bool "L-BOX RE2"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select L-BOX RE2 if configuring for the NTT COMWARE L-BOX RE2.
+
+endmenu
+
+source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
+source "arch/sh/boards/renesas/r7780rp/Kconfig"
+
 menu "Timer and clock configuration"
 
 config SH_TMU
@@ -473,13 +440,13 @@
 	int "Peripheral clock frequency (in Hz)"
 	default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
 	default "31250000" if CPU_SUBTYPE_SH7619
+	default "32000000" if CPU_SUBTYPE_SH7722
 	default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
 			      CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
 			      CPU_SUBTYPE_SH7206
-	default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 || \
-			      CPU_SUBTYPE_SH7785
-	default "60000000" if CPU_SUBTYPE_SH7751
+	default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
 	default "66000000" if CPU_SUBTYPE_SH4_202
+	default "50000000"
 	help
 	  This option is used to specify the peripheral clock frequency.
 	  This is necessary for determining the reference clock value on
@@ -487,8 +454,10 @@
 
 config SH_CLK_MD
 	int "CPU Mode Pin Setting"
-	default 0
 	depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
+	default 6 if CPU_SUBTYPE_SH7206
+	default 5 if CPU_SUBTYPE_SH7619
+	default 0
 	help
 	  MD2 - MD0 pin setting.
 
@@ -560,6 +529,7 @@
 
 config SMP
 	bool "Symmetric multi-processing support"
+	depends on SYS_SUPPORTS_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
@@ -584,6 +554,7 @@
 	int "Maximum number of CPUs (2-32)"
 	range 2 32
 	depends on SMP
+	default "4" if CPU_SHX3
 	default "2"
 	help
 	  This allows you to specify the maximum number of CPUs which this
@@ -623,6 +594,7 @@
 
 config UBC_WAKEUP
 	bool "Wakeup UBC on startup"
+	depends on CPU_SH4
 	help
 	  Selecting this option will wakeup the User Break Controller (UBC) on
 	  startup. Although the UBC is left in an awake state when the processor
@@ -651,8 +623,8 @@
 # we're not using PCMCIA, so we make it dependent on
 # PCMCIA outright. -- PFM.
 config ISA
-	bool
-	default y if PCMCIA
+	def_bool y
+	depends on PCMCIA && HD6446X_SERIES
 	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
@@ -690,6 +662,49 @@
 	tristate "SuperHyway Bus support"
 	depends on CPU_SUBTYPE_SH4_202
 
+config CF_ENABLER
+	bool "Compact Flash Enabler support"
+	depends on SOLUTION_ENGINE || SH_SH03
+	---help---
+	  Compact Flash is a small, removable mass storage device introduced
+	  in 1994 originally as a PCMCIA device.  If you say `Y' here, you
+	  compile in support for Compact Flash devices directly connected to
+	  a SuperH processor.  A Compact Flash FAQ is available at
+	  <http://www.compactflash.org/faqs/faq.htm>.
+
+	  If your board has "Directly Connected" CompactFlash at area 5 or 6,
+	  you may want to enable this option.  Then, you can use CF as
+	  primary IDE drive (only tested for SanDisk).
+
+	  If in doubt, select 'N'.
+
+choice
+	prompt "Compact Flash Connection Area"
+	depends on CF_ENABLER
+	default CF_AREA6
+
+config CF_AREA5
+	bool "Area5"
+	help
+	  If your board has "Directly Connected" CompactFlash, You should
+	  select the area where your CF is connected to.
+
+	  - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
+	  - "Area6" if it is connected to Area 6 (0x18000000)
+
+	  "Area6" will work for most boards.
+
+config CF_AREA6
+	bool "Area6"
+
+endchoice
+
+config CF_BASE_ADDR
+	hex
+	depends on CF_ENABLER
+	default "0xb8000000" if CF_AREA6
+	default "0xb4000000" if CF_AREA5
+
 source "arch/sh/drivers/pci/Kconfig"
 
 source "drivers/pci/Kconfig"
@@ -707,7 +722,7 @@
 endmenu
 
 menu "Power management options (EXPERIMENTAL)"
-depends on EXPERIMENTAL
+depends on EXPERIMENTAL && SYS_SUPPORTS_PM
 
 source kernel/power/Kconfig
 
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index b563072..52f6a99 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -52,6 +52,10 @@
 	  select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
 	  the kernel command line option to toggle back and forth.
 
+config DEBUG_BOOTMEM
+	depends on DEBUG_KERNEL
+	bool "Debug BOOTMEM initialization"
+
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL
@@ -82,6 +86,7 @@
 	bool "Include KGDB kernel debugger"
 	select FRAME_POINTER
 	select DEBUG_INFO
+	depends on CPU_SH3 || CPU_SH4
 	help
 	  Include in-kernel hooks for kgdb, the Linux kernel source level
 	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 883b03b..77fecc6 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -34,20 +34,20 @@
 endif
 endif
 
-cflags-$(CONFIG_CPU_SH2)		:= -m2
-cflags-$(CONFIG_CPU_SH2A)		:= -m2a $(call cc-option,-m2a-nofpu,)
-cflags-$(CONFIG_CPU_SH3)		:= -m3
-cflags-$(CONFIG_CPU_SH4)		:= -m4 \
+cflags-$(CONFIG_CPU_SH2)		:= $(call cc-option,-m2,)
+cflags-$(CONFIG_CPU_SH2A)		+= $(call cc-option,-m2a,) \
+					   $(call cc-option,-m2a-nofpu,)
+cflags-$(CONFIG_CPU_SH3)		:= $(call cc-option,-m3,)
+cflags-$(CONFIG_CPU_SH4)		:= $(call cc-option,-m4,) \
 	$(call cc-option,-mno-implicit-fp,-m4-nofpu)
-cflags-$(CONFIG_CPU_SH4A)		:= $(call cc-option,-m4a,) $(call cc-option,-m4a-nofpu,)
+cflags-$(CONFIG_CPU_SH4A)		+= $(call cc-option,-m4a,) \
+					   $(call cc-option,-m4a-nofpu,)
 
 cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= -mb
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= -ml
 
 cflags-y	+= $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding
 
-cflags-$(CONFIG_SH_DSP)			+= -Wa,-dsp
-
 cflags-$(CONFIG_MORE_COMPILE_OPTIONS)	+= \
 	$(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
 
@@ -87,39 +87,37 @@
 core-$(CONFIG_SH_FPU_EMU)	+= arch/sh/math-emu/
 
 # Boards
-machdir-$(CONFIG_SH_SOLUTION_ENGINE)		:= se/770x
-machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE)	:= se/7722
-machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)	:= se/7751
-machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE)	:= se/7780
-machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)	:= se/7300
-machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)	:= se/7343
-machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)	:= se/73180
-machdir-$(CONFIG_SH_HP6XX)			:= hp6xx
-machdir-$(CONFIG_SH_SATURN)			:= saturn
-machdir-$(CONFIG_SH_DREAMCAST)			:= dreamcast
-machdir-$(CONFIG_SH_MPC1211)			:= mpc1211
-machdir-$(CONFIG_SH_SH03)			:= sh03
-machdir-$(CONFIG_SH_SECUREEDGE5410)		:= snapgear
-machdir-$(CONFIG_SH_HS7751RVOIP)		:= renesas/hs7751rvoip
-machdir-$(CONFIG_SH_RTS7751R2D)			:= renesas/rts7751r2d
-machdir-$(CONFIG_SH_7751_SYSTEMH)		:= renesas/systemh
-machdir-$(CONFIG_SH_EDOSK7705)			:= renesas/edosk7705
-machdir-$(CONFIG_SH_HIGHLANDER)			:= renesas/r7780rp
-machdir-$(CONFIG_SH_7710VOIPGW)			:= renesas/sh7710voipgw
-machdir-$(CONFIG_SH_SH4202_MICRODEV)		:= superh/microdev
-machdir-$(CONFIG_SH_LANDISK)			:= landisk
-machdir-$(CONFIG_SH_TITAN)			:= titan
-machdir-$(CONFIG_SH_SHMIN)			:= shmin
-machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE)	:= se/7206
-machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE)	:= se/7619
-machdir-$(CONFIG_SH_LBOX_RE2)			:= lboxre2
-machdir-$(CONFIG_SH_UNKNOWN)			:= unknown
+machdir-$(CONFIG_SH_SOLUTION_ENGINE)		+= se/770x
+machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE)	+= se/7722
+machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)	+= se/7751
+machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE)	+= se/7780
+machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)	+= se/7300
+machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)	+= se/7343
+machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)	+= se/73180
+machdir-$(CONFIG_SH_HP6XX)			+= hp6xx
+machdir-$(CONFIG_SH_DREAMCAST)			+= dreamcast
+machdir-$(CONFIG_SH_MPC1211)			+= mpc1211
+machdir-$(CONFIG_SH_SH03)			+= sh03
+machdir-$(CONFIG_SH_SECUREEDGE5410)		+= snapgear
+machdir-$(CONFIG_SH_HS7751RVOIP)		+= renesas/hs7751rvoip
+machdir-$(CONFIG_SH_RTS7751R2D)			+= renesas/rts7751r2d
+machdir-$(CONFIG_SH_7751_SYSTEMH)		+= renesas/systemh
+machdir-$(CONFIG_SH_EDOSK7705)			+= renesas/edosk7705
+machdir-$(CONFIG_SH_HIGHLANDER)			+= renesas/r7780rp
+machdir-$(CONFIG_SH_7710VOIPGW)			+= renesas/sh7710voipgw
+machdir-$(CONFIG_SH_SH4202_MICRODEV)		+= superh/microdev
+machdir-$(CONFIG_SH_LANDISK)			+= landisk
+machdir-$(CONFIG_SH_TITAN)			+= titan
+machdir-$(CONFIG_SH_SHMIN)			+= shmin
+machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE)	+= se/7206
+machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE)	+= se/7619
+machdir-$(CONFIG_SH_LBOX_RE2)			+= lboxre2
 
-incdir-y			:= $(notdir $(machdir-y))
-incdir-$(CONFIG_SH_HP6XX)			:= hp6xx
+incdir-y	:= $(notdir $(machdir-y))
 
 ifneq ($(machdir-y),)
-core-y				+= arch/sh/boards/$(machdir-y)/
+core-y	+= $(addprefix arch/sh/boards/, \
+	     $(filter-out ., $(patsubst %,%/,$(machdir-y))))
 endif
 
 # Companion chips
@@ -157,19 +155,31 @@
 #	Most boards have their own mach directories.  For the ones that
 #	don't, just reference the parent directory so the semantics are
 #	kept roughly the same.
+#
+#	When multiple boards are compiled in at the same time, preference
+#	for the mach link is given to whichever has a directory for its
+#	headers. However, this is only a workaround until platforms that
+#	can live in the same kernel image back away from relying on the
+#	mach link.
 
 include/asm-sh/.mach: $(wildcard include/config/sh/*.h) \
 		      include/config/auto.conf FORCE
-	@echo -n '  SYMLINK include/asm-sh/mach -> '
 	$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
-	$(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
-		echo -e 'include/asm-sh/$(incdir-y)'; \
-		ln -fsn $(incdir-prefix)$(incdir-y) \
+	$(Q)rm -f include/asm-sh/mach
+	$(Q)for i in $(incdir-y); do \
+	if [ -d $(incdir-prefix)$$i ]; then \
+		echo -n '  SYMLINK include/asm-sh/mach -> '; \
+		echo -e "include/asm-sh/$$i"; \
+		ln -fsn $(incdir-prefix)$$i \
 			include/asm-sh/mach; \
 	else \
-		echo -e 'include/asm-sh'; \
-		ln -fsn $(incdir-prefix) include/asm-sh/mach; \
-	fi
+		if [ ! -d include/asm-sh/mach ]; then \
+			echo -n '  SYMLINK include/asm-sh/mach -> '; \
+			echo -e 'include/asm-sh'; \
+			ln -fsn $(incdir-prefix) include/asm-sh/mach; \
+		fi; \
+	fi; \
+	done
 	@touch $@
 
 archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools
@@ -188,7 +198,9 @@
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
-CLEAN_FILES += include/asm-sh/machtypes.h
+CLEAN_FILES += include/asm-sh/machtypes.h \
+	       include/asm-sh/cpu include/asm-sh/.cpu \
+	       include/asm-sh/mach include/asm-sh/.mach
 
 define archhelp
 	@echo '* zImage 	           - Compressed kernel image'
diff --git a/arch/sh/boards/dreamcast/setup.c b/arch/sh/boards/dreamcast/setup.c
index f13017e..8799df6 100644
--- a/arch/sh/boards/dreamcast/setup.c
+++ b/arch/sh/boards/dreamcast/setup.c
@@ -60,7 +60,7 @@
 #endif
 }
 
-struct sh_machine_vector mv_dreamcast __initmv = {
+static struct sh_machine_vector mv_dreamcast __initmv = {
 	.mv_name		= "Sega Dreamcast",
 	.mv_setup		= dreamcast_setup,
 	.mv_irq_demux		= systemasic_irq_demux,
@@ -70,4 +70,3 @@
 	.mv_consistent_free	= dreamcast_consistent_free,
 #endif
 };
-ALIAS_MV(dreamcast)
diff --git a/arch/sh/boards/hp6xx/mach.c b/arch/sh/boards/hp6xx/mach.c
deleted file mode 100644
index 08dbba9..0000000
--- a/arch/sh/boards/hp6xx/mach.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/sh/boards/hp6xx/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the HP680
- */
-#include <asm/machvec.h>
-#include <asm/hd64461.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-struct sh_machine_vector mv_hp6xx __initmv = {
-	.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
-
-	.mv_inb = hd64461_inb,
-	.mv_inw = hd64461_inw,
-	.mv_inl = hd64461_inl,
-	.mv_outb = hd64461_outb,
-	.mv_outw = hd64461_outw,
-	.mv_outl = hd64461_outl,
-
-	.mv_inb_p = hd64461_inb_p,
-	.mv_inw_p = hd64461_inw,
-	.mv_inl_p = hd64461_inl,
-	.mv_outb_p = hd64461_outb_p,
-	.mv_outw_p = hd64461_outw,
-	.mv_outl_p = hd64461_outl,
-
-	.mv_insb = hd64461_insb,
-	.mv_insw = hd64461_insw,
-	.mv_insl = hd64461_insl,
-	.mv_outsb = hd64461_outsb,
-	.mv_outsw = hd64461_outsw,
-	.mv_outsl = hd64461_outsl,
-
-	.mv_readw = hd64461_readw,
-	.mv_writew = hd64461_writew,
-
-	.mv_irq_demux = hd64461_irq_demux,
-};
-
-ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c
index 6aeee85..7ae7089 100644
--- a/arch/sh/boards/hp6xx/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -98,10 +98,9 @@
 }
 device_initcall(hp6xx_devices_setup);
 
-struct sh_machine_vector mv_hp6xx __initmv = {
+static struct sh_machine_vector mv_hp6xx __initmv = {
 	.mv_name = "hp6xx",
 	.mv_setup = hp6xx_setup,
 	.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
 	.mv_irq_demux = hd64461_irq_demux,
 };
-ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index f953c74..eda7176 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -97,10 +97,9 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_landisk __initmv = {
+static struct sh_machine_vector mv_landisk __initmv = {
 	.mv_name = "LANDISK",
 	.mv_nr_irqs = 72,
 	.mv_setup = landisk_setup,
 	.mv_init_irq = init_landisk_IRQ,
 };
-ALIAS_MV(landisk)
diff --git a/arch/sh/boards/lboxre2/setup.c b/arch/sh/boards/lboxre2/setup.c
index 4e20f7c..9c830fd 100644
--- a/arch/sh/boards/lboxre2/setup.c
+++ b/arch/sh/boards/lboxre2/setup.c
@@ -77,9 +77,8 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_lboxre2 __initmv = {
+static struct sh_machine_vector mv_lboxre2 __initmv = {
 	.mv_name		= "L-BOX RE2",
 	.mv_nr_irqs		= 72,
 	.mv_init_irq		= init_lboxre2_IRQ,
 };
-ALIAS_MV(lboxre2)
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
index 1a0604b..8ce03e0 100644
--- a/arch/sh/boards/mpc1211/setup.c
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -338,11 +338,10 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_mpc1211 __initmv = {
+static struct sh_machine_vector mv_mpc1211 __initmv = {
 	.mv_name		= "Interface MPC-1211(CTP/PCI/MPC-SH02)",
 	.mv_setup		= mpc1211_setup,
 	.mv_nr_irqs		= 48,
 	.mv_irq_demux		= mpc1211_irq_demux,
 	.mv_init_irq		= init_mpc1211_IRQ,
 };
-ALIAS_MV(mpc1211)
diff --git a/arch/sh/boards/renesas/edosk7705/setup.c b/arch/sh/boards/renesas/edosk7705/setup.c
index ec5be01..f076c45 100644
--- a/arch/sh/boards/renesas/edosk7705/setup.c
+++ b/arch/sh/boards/renesas/edosk7705/setup.c
@@ -21,7 +21,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_edosk7705 __initmv = {
+static struct sh_machine_vector mv_edosk7705 __initmv = {
 	.mv_name		= "EDOSK7705",
 	.mv_nr_irqs		= 80,
 
@@ -41,4 +41,3 @@
 	.mv_isa_port2addr	= sh_edosk7705_isa_port2addr,
 	.mv_init_irq		= sh_edosk7705_init_irq,
 };
-ALIAS_MV(edosk7705)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
index f7d0e30..fa5fa39 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/setup.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -89,7 +89,7 @@
 	printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
 }
 
-struct sh_machine_vector mv_hs7751rvoip __initmv = {
+static struct sh_machine_vector mv_hs7751rvoip __initmv = {
 	.mv_name		= "HS7751RVoIP",
 	.mv_setup		= hs7751rvoip_setup,
 	.mv_nr_irqs		= 72,
@@ -118,4 +118,3 @@
 	.mv_init_irq		= hs7751rvoip_init_irq,
 	.mv_ioport_map		= hs7751rvoip_ioport_map,
 };
-ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/r7780rp/Kconfig b/arch/sh/boards/renesas/r7780rp/Kconfig
index 9fb1164..fc8f28e 100644
--- a/arch/sh/boards/renesas/r7780rp/Kconfig
+++ b/arch/sh/boards/renesas/r7780rp/Kconfig
@@ -6,18 +6,18 @@
 
 config SH_R7780RP
 	bool "R7780RP-1 board support"
-	select CPU_SUBTYPE_SH7780
+	depends on CPU_SUBTYPE_SH7780
 
 config SH_R7780MP
 	bool "R7780MP board support"
-	select CPU_SUBTYPE_SH7780
+	depends on CPU_SUBTYPE_SH7780
 	help
 	  Selecting this option will enable support for the mass-production
 	  version of the R7780RP. If in doubt, say Y.
 
 config SH_R7785RP
 	bool "R7785RP board support"
-	select CPU_SUBTYPE_SH7785
+	depends on CPU_SUBTYPE_SH7785
 
 endchoice
 
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index 0727ef9..5afb864 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -166,10 +166,9 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_highlander __initmv = {
+static struct sh_machine_vector mv_highlander __initmv = {
 	.mv_name		= "Highlander",
 	.mv_nr_irqs		= 109,
 	.mv_setup		= highlander_setup,
 	.mv_init_irq		= highlander_init_irq,
 };
-ALIAS_MV(highlander)
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 593f26a..656fda3 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -176,7 +176,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_rts7751r2d __initmv = {
+static struct sh_machine_vector mv_rts7751r2d __initmv = {
 	.mv_name		= "RTS7751R2D",
 	.mv_setup		= rts7751r2d_setup,
 	.mv_nr_irqs		= 72,
@@ -189,4 +189,3 @@
 	.mv_consistent_free	= voyagergx_consistent_free,
 #endif
 };
-ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c
index 180810b..2dce8bd 100644
--- a/arch/sh/boards/renesas/sh7710voipgw/setup.c
+++ b/arch/sh/boards/renesas/sh7710voipgw/setup.c
@@ -88,9 +88,8 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_sh7710voipgw __initmv = {
+static struct sh_machine_vector mv_sh7710voipgw __initmv = {
 	.mv_name		= "SH7710 VoIP Gateway",
 	.mv_nr_irqs		= 104,
 	.mv_init_irq		= sh7710voipgw_init_irq,
 };
-ALIAS_MV(sh7710voipgw)
diff --git a/arch/sh/boards/renesas/systemh/setup.c b/arch/sh/boards/renesas/systemh/setup.c
index 9361176..ee78af8 100644
--- a/arch/sh/boards/renesas/systemh/setup.c
+++ b/arch/sh/boards/renesas/systemh/setup.c
@@ -28,7 +28,7 @@
 	make_systemh_irq(0xb);	/* Ethernet interrupt */
 }
 
-struct sh_machine_vector mv_7751systemh __initmv = {
+static struct sh_machine_vector mv_7751systemh __initmv = {
 	.mv_name		= "7751 SystemH",
 	.mv_nr_irqs		= 72,
 
@@ -55,4 +55,3 @@
 
 	.mv_init_irq		= sh7751systemh_init_irq,
 };
-ALIAS_MV(7751systemh)
diff --git a/arch/sh/boards/saturn/Makefile b/arch/sh/boards/saturn/Makefile
deleted file mode 100644
index 75a3042..0000000
--- a/arch/sh/boards/saturn/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Sega Saturn specific parts of the kernel
-#
-
-obj-y	 := setup.o io.o irq.o
-
-obj-$(CONFIG_SMP) += smp.o
-
diff --git a/arch/sh/boards/saturn/io.c b/arch/sh/boards/saturn/io.c
deleted file mode 100644
index c6e4f7f..0000000
--- a/arch/sh/boards/saturn/io.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/sh/boards/saturn/io.c
- *
- * I/O routines for the Sega Saturn.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <asm/saturn/io.h>
-#include <asm/machvec.h>
-
-unsigned long saturn_isa_port2addr(unsigned long offset)
-{
-	return offset;
-}
-
-void *saturn_ioremap(unsigned long offset, unsigned long size)
-{
-	return (void *)offset;
-}
-
-void saturn_iounmap(void *addr)
-{
-}
-
diff --git a/arch/sh/boards/saturn/irq.c b/arch/sh/boards/saturn/irq.c
deleted file mode 100644
index 15d1d3f..0000000
--- a/arch/sh/boards/saturn/irq.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * arch/sh/boards/saturn/irq.c
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-/*
- * Interrupts map out as follows:
- *
- *  Vector	Name		Mask
- *
- * 	64	VBLANKIN	0x0001
- * 	65	VBLANKOUT	0x0002
- *	66	HBLANKIN	0x0004
- *	67	TIMER0		0x0008
- *	68	TIMER1		0x0010
- *	69	DSPEND		0x0020
- *	70	SOUNDREQUEST	0x0040
- *	71	SYSTEMMANAGER	0x0080
- *	72	PAD		0x0100
- *	73	LEVEL2DMAEND	0x0200
- *	74	LEVEL1DMAEND	0x0400
- *	75	LEVEL0DMAEND	0x0800
- *	76	DMAILLEGAL	0x1000
- *	77	SRITEDRAWEND	0x2000
- *	78	ABUS		0x8000
- *
- */
-#define SATURN_IRQ_MIN		64	/* VBLANKIN */
-#define SATURN_IRQ_MAX		78	/* ABUS */
-
-#define SATURN_IRQ_MASK		0xbfff
-
-static inline u32 saturn_irq_mask(unsigned int irq_nr)
-{
-	u32 mask;
-
-	mask = (1 << (irq_nr - SATURN_IRQ_MIN));
-	mask <<= (irq_nr == SATURN_IRQ_MAX);
-	mask &= SATURN_IRQ_MASK;
-
-	return mask;
-}
-
-static inline void mask_saturn_irq(unsigned int irq_nr)
-{
-	u32 mask;
-
-	mask = ctrl_inl(SATURN_IMR);
-	mask |= saturn_irq_mask(irq_nr);
-	ctrl_outl(mask, SATURN_IMR);
-}
-
-static inline void unmask_saturn_irq(unsigned int irq_nr)
-{
-	u32 mask;
-
-	mask = ctrl_inl(SATURN_IMR);
-	mask &= ~saturn_irq_mask(irq_nr);
-	ctrl_outl(mask, SATURN_IMR);
-}
-
-static void disable_saturn_irq(unsigned int irq_nr)
-{
-	mask_saturn_irq(irq_nr);
-}
-
-static void enable_saturn_irq(unsigned int irq_nr)
-{
-	unmask_saturn_irq(irq_nr);
-}
-
-static void mask_and_ack_saturn_irq(unsigned int irq_nr)
-{
-	mask_saturn_irq(irq_nr);
-}
-
-static void end_saturn_irq(unsigned int irq_nr)
-{
-	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		unmask_saturn_irq(irq_nr);
-}
-
-static unsigned int startup_saturn_irq(unsigned int irq_nr)
-{
-	unmask_saturn_irq(irq_nr);
-
-	return 0;
-}
-
-static void shutdown_saturn_irq(unsigned int irq_nr)
-{
-	mask_saturn_irq(irq_nr);
-}
-
-static struct hw_interrupt_type saturn_int = {
-	.typename	= "Saturn",
-	.enable		= enable_saturn_irq,
-	.disable	= disable_saturn_irq,
-	.ack		= mask_and_ack_saturn_irq,
-	.end		= end_saturn_irq,
-	.startup	= startup_saturn_irq,
-	.shutdown	= shutdown_saturn_irq,
-};
-
-int saturn_irq_demux(int irq_nr)
-{
-	/* FIXME */
-	return irq_nr;
-}
-
diff --git a/arch/sh/boards/saturn/setup.c b/arch/sh/boards/saturn/setup.c
deleted file mode 100644
index a3a37c9..0000000
--- a/arch/sh/boards/saturn/setup.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 
- * arch/sh/boards/saturn/setup.c
- *
- * Hardware support for the Sega Saturn.
- *
- * Copyright (c) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/io.h>
-
-extern int saturn_irq_demux(int irq_nr);
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_saturn __initmv = {
-	.mv_name		= "Sega Saturn",
-	.mv_nr_irqs		= 80,	/* Fix this later */
-
-	.mv_isa_port2addr	= saturn_isa_port2addr,
-	.mv_irq_demux		= saturn_irq_demux,
-
-	.mv_ioremap		= saturn_ioremap,
-	.mv_iounmap		= saturn_iounmap,
-};
-ALIAS_MV(saturn)
diff --git a/arch/sh/boards/saturn/smp.c b/arch/sh/boards/saturn/smp.c
deleted file mode 100644
index 7646091..0000000
--- a/arch/sh/boards/saturn/smp.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* 
- * arch/sh/boards/saturn/smp.c
- *
- * SMP support for the Sega Saturn.
- *
- * Copyright (c) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/saturn/smpc.h>
-
-extern void start_secondary(void);
-
-void __smp_send_ipi(unsigned int cpu, unsigned int action)
-{
-	/* Nothing here yet .. */
-}
-
-unsigned int __smp_probe_cpus(void)
-{
-	/*
-	 * This is just a straightforward master/slave configuration,
-	 * and probing isn't really supported..
-	 */
-	return 2;
-}
-
-/*
- * We're only allowed to do byte-access to SMPC registers. In
- * addition to which, we treat them as write-only, since
- * reading from them will return undefined data.
- */
-static inline void smpc_slave_stop(unsigned int cpu)
-{
-	smpc_barrier();
-	ctrl_outb(1, SMPC_STATUS);
-
-	ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
-	smpc_barrier();
-}
-
-static inline void smpc_slave_start(unsigned int cpu)
-{
-	ctrl_outb(1, SMPC_STATUS);
-	ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
-
-	smpc_barrier();
-}
-
-void __smp_slave_init(unsigned int cpu)
-{
-	register unsigned long vbr;
-	void **entry;
-
-	__asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
-	entry = (void **)(vbr + 0x310 + 0x94);
-
-	smpc_slave_stop(cpu);
-
-	*(void **)entry = (void *)start_secondary;
-
-	smpc_slave_start(cpu);
-}
-
diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c
index ca71487..a074b62 100644
--- a/arch/sh/boards/se/7206/setup.c
+++ b/arch/sh/boards/se/7206/setup.c
@@ -70,7 +70,7 @@
  * The Machine Vector
  */
 
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 256,
 	.mv_inb			= se7206_inb,
@@ -96,4 +96,3 @@
 
 	.mv_init_irq		= init_se7206_IRQ,
 };
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7300/setup.c b/arch/sh/boards/se/7300/setup.c
index f196095..eb469f5 100644
--- a/arch/sh/boards/se/7300/setup.c
+++ b/arch/sh/boards/se/7300/setup.c
@@ -46,7 +46,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_7300se __initmv = {
+static struct sh_machine_vector mv_7300se __initmv = {
 	.mv_name = "SolutionEngine 7300",
 	.mv_nr_irqs = 109,
 	.mv_inb = sh7300se_inb,
@@ -72,4 +72,3 @@
 
 	.mv_init_irq = init_7300se_IRQ,
 };
-ALIAS_MV(7300se)
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
index e143017..1deee85 100644
--- a/arch/sh/boards/se/73180/setup.c
+++ b/arch/sh/boards/se/73180/setup.c
@@ -46,7 +46,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_73180se __initmv = {
+static struct sh_machine_vector mv_73180se __initmv = {
 	.mv_name = "SolutionEngine 73180",
 	.mv_nr_irqs = 108,
 	.mv_inb = sh73180se_inb,
@@ -73,4 +73,3 @@
 	.mv_init_irq = init_73180se_IRQ,
 	.mv_irq_demux = shmse_irq_demux,
 };
-ALIAS_MV(73180se)
diff --git a/arch/sh/boards/se/7343/setup.c b/arch/sh/boards/se/7343/setup.c
index 3fdb16f..8fec155 100644
--- a/arch/sh/boards/se/7343/setup.c
+++ b/arch/sh/boards/se/7343/setup.c
@@ -64,7 +64,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_7343se __initmv = {
+static struct sh_machine_vector mv_7343se __initmv = {
 	.mv_name = "SolutionEngine 7343",
 	.mv_setup = sh7343se_setup,
 	.mv_nr_irqs = 108,
@@ -92,4 +92,3 @@
 	.mv_init_irq = init_7343se_IRQ,
 	.mv_irq_demux = shmse_irq_demux,
 };
-ALIAS_MV(7343se)
diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c
index 52d2c4d..1d0ef7f 100644
--- a/arch/sh/boards/se/7619/setup.c
+++ b/arch/sh/boards/se/7619/setup.c
@@ -15,8 +15,7 @@
  * The Machine Vector
  */
 
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 108,
 };
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
index c8eccff..cdb0807 100644
--- a/arch/sh/boards/se/770x/irq.c
+++ b/arch/sh/boards/se/770x/irq.c
@@ -15,46 +15,7 @@
 #include <asm/io.h>
 #include <asm/se.h>
 
-/* 
- * If the problem of make_ipr_irq is solved, 
- * this code will become unnecessary. :-) 
- */
-static void se770x_disable_ipr_irq(unsigned int irq)
-{
-	struct ipr_data *p = get_irq_chip_data(irq);
-
-	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
-}
-
-static void se770x_enable_ipr_irq(unsigned int irq)
-{
-	struct ipr_data *p = get_irq_chip_data(irq);
-
-	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
-}
-
-static struct irq_chip se770x_irq_chip = {
-	.name           = "MS770xSE-FPGA",
-	.mask           = se770x_disable_ipr_irq,
-	.unmask         = se770x_enable_ipr_irq,
-	.mask_ack       = se770x_disable_ipr_irq,
-};
-
-void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
-{
-	int i;
-
-	for (i = 0; i < nr_irqs; i++) {
-		unsigned int irq = table[i].irq;
-		disable_irq_nosync(irq);
-		set_irq_chip_and_handler_name(irq, &se770x_irq_chip,
-			handle_level_irq, "level");
-		set_irq_chip_data(irq, &table[i]);
-		se770x_enable_ipr_irq(irq);
-	}
-}
-
-static struct ipr_data se770x_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/*
 	* Super I/O (Just mimic PC):
 	*  1: keyboard
@@ -68,46 +29,67 @@
 	*/
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
 	/* This is default value */
-	{ 13, 0, 8,  0x0f-13 ,BCR_ILCRA},
-	{ 5 , 0, 4,  0x0f- 5 ,BCR_ILCRA},
-	{ 10, 0, 0,  0x0f-10, BCR_ILCRB},
-	{ 7 , 0, 4,  0x0f- 7, BCR_ILCRC},
-	{ 3 , 0, 0,  0x0f- 3, BCR_ILCRC},
-	{ 1 , 0, 12, 0x0f- 1, BCR_ILCRD},
-	{ 12, 0, 4,  0x0f-12, BCR_ILCRD}, /* LAN */
-	{ 2 , 0, 8,  0x0f- 2, BCR_ILCRE}, /* PCIRQ2 */
-	{ 6 , 0, 4,  0x0f- 6, BCR_ILCRE}, /* PCIRQ1 */
-	{ 14, 0, 0,  0x0f-14, BCR_ILCRE}, /* PCIRQ0 */
-	{ 0 , 0, 12, 0x0f   , BCR_ILCRF}, 
-	{ 4 , 0, 4,  0x0f- 4, BCR_ILCRF},
-	{ 8 , 0, 12, 0x0f- 8, BCR_ILCRG},
-	{ 9 , 0, 8,  0x0f- 9, BCR_ILCRG},
-	{ 11, 0, 4,  0x0f-11, BCR_ILCRG},
+	{ 13, 0, 8,  0x0f-13, },
+	{ 5 , 0, 4,  0x0f- 5, },
+	{ 10, 1, 0,  0x0f-10, },
+	{ 7 , 2, 4,  0x0f- 7, },
+	{ 3 , 2, 0,  0x0f- 3, },
+	{ 1 , 3, 12, 0x0f- 1, },
+	{ 12, 3, 4,  0x0f-12, }, /* LAN */
+	{ 2 , 4, 8,  0x0f- 2, }, /* PCIRQ2 */
+	{ 6 , 4, 4,  0x0f- 6, }, /* PCIRQ1 */
+	{ 14, 4, 0,  0x0f-14, }, /* PCIRQ0 */
+	{ 0 , 5, 12, 0x0f   , }, 
+	{ 4 , 5, 4,  0x0f- 4, },
+	{ 8 , 6, 12, 0x0f- 8, },
+	{ 9 , 6, 8,  0x0f- 9, },
+	{ 11, 6, 4,  0x0f-11, },
 #else
-	{ 14, 0,  8, 0x0f-14 ,BCR_ILCRA},
-	{ 12, 0,  4, 0x0f-12 ,BCR_ILCRA},
-	{  8, 0,  4, 0x0f- 8 ,BCR_ILCRB},
-	{  6, 0, 12, 0x0f- 6 ,BCR_ILCRC},
-	{  5, 0,  8, 0x0f- 5 ,BCR_ILCRC},
-	{  4, 0,  4, 0x0f- 4 ,BCR_ILCRC},
-	{  3, 0,  0, 0x0f- 3 ,BCR_ILCRC},
-	{  1, 0, 12, 0x0f- 1 ,BCR_ILCRD},
+	{ 14, 0,  8, 0x0f-14, },
+	{ 12, 0,  4, 0x0f-12, },
+	{  8, 1,  4, 0x0f- 8, },
+	{  6, 2, 12, 0x0f- 6, },
+	{  5, 2,  8, 0x0f- 5, },
+	{  4, 2,  4, 0x0f- 4, },
+	{  3, 2,  0, 0x0f- 3, },
+	{  1, 3, 12, 0x0f- 1, },
 #if defined(CONFIG_STNIC)
 	/* ST NIC */
-	{ 10, 0,  4, 0x0f-10 ,BCR_ILCRD}, 	/* LAN */
+	{ 10, 3,  4, 0x0f-10, }, 	/* LAN */
 #endif
 	/* MRSHPC IRQs setting */
-	{  0, 0, 12, 0x0f- 0 ,BCR_ILCRE},	/* PCIRQ3 */
-	{ 11, 0,  8, 0x0f-11 ,BCR_ILCRE}, 	/* PCIRQ2 */
-	{  9, 0,  4, 0x0f- 9 ,BCR_ILCRE}, 	/* PCIRQ1 */
-	{  7, 0,  0, 0x0f- 7 ,BCR_ILCRE}, 	/* PCIRQ0 */
+	{  0, 4, 12, 0x0f- 0, },	/* PCIRQ3 */
+	{ 11, 4,  8, 0x0f-11, }, 	/* PCIRQ2 */
+	{  9, 4,  4, 0x0f- 9, }, 	/* PCIRQ1 */
+	{  7, 4,  0, 0x0f- 7, }, 	/* PCIRQ0 */
 	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
 	/* NOTE: #2 and #13 are not used on PC */
-	{ 13, 0,  4, 0x0f-13 ,BCR_ILCRG}, 	/* SLOTIRQ2 */
-	{  2, 0,  0, 0x0f- 2 ,BCR_ILCRG}, 	/* SLOTIRQ1 */
+	{ 13, 6,  4, 0x0f-13, }, 	/* SLOTIRQ2 */
+	{  2, 6,  0, 0x0f- 2, }, 	/* SLOTIRQ1 */
 #endif
 };
 
+static unsigned long ipr_offsets[] = {
+	BCR_ILCRA,
+	BCR_ILCRB,
+	BCR_ILCRC,
+	BCR_ILCRD,
+	BCR_ILCRE,
+	BCR_ILCRF,
+	BCR_ILCRG,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+	.chip = {
+		.name	= "IPR-se770x",
+	},
+};
+
 /*
  * Initialize IRQ setting
  */
@@ -122,5 +104,5 @@
 	ctrl_outw(0, BCR_ILCRF);
 	ctrl_outw(0, BCR_ILCRG);
 
-	make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
index 17a2631..2962da1 100644
--- a/arch/sh/boards/se/770x/setup.c
+++ b/arch/sh/boards/se/770x/setup.c
@@ -122,7 +122,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_setup		= smsc_setup,
 #if defined(CONFIG_CPU_SH4)
@@ -160,4 +160,3 @@
 
 	.mv_init_irq		= init_se_IRQ,
 };
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7722/irq.c b/arch/sh/boards/se/7722/irq.c
index 099e5de..26cff0e 100644
--- a/arch/sh/boards/se/7722/irq.c
+++ b/arch/sh/boards/se/7722/irq.c
@@ -19,15 +19,24 @@
 #define INTC_INTMSK0             0xFFD00044
 #define INTC_INTMSKCLR0          0xFFD00064
 
+struct se7722_data {
+	unsigned char irq;
+	unsigned char ipr_idx;
+	unsigned char shift;
+	unsigned short priority;
+	unsigned long addr;
+};
+
+
 static void disable_se7722_irq(unsigned int irq)
 {
-	struct ipr_data *p = get_irq_chip_data(irq);
+	struct se7722_data *p = get_irq_chip_data(irq);
 	ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
 }
 
 static void enable_se7722_irq(unsigned int irq)
 {
-	struct ipr_data *p = get_irq_chip_data(irq);
+	struct se7722_data *p = get_irq_chip_data(irq);
 	ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
 }
 
@@ -38,7 +47,7 @@
 	.mask_ack       = disable_se7722_irq,
 };
 
-static struct ipr_data ipr_irq_table[] = {
+static struct se7722_data ipr_irq_table[] = {
 	/* irq        ,idx,sft, priority     , addr   */
 	{ MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
 	{ MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } ,
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
index 636ca6c..6cca6cb 100644
--- a/arch/sh/boards/se/7722/setup.c
+++ b/arch/sh/boards/se/7722/setup.c
@@ -137,7 +137,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_se7722 __initmv = {
+static struct sh_machine_vector mv_se7722 __initmv = {
 	.mv_name                = "Solution Engine 7722" ,
 	.mv_setup               = se7722_setup ,
 	.mv_nr_irqs		= 109 ,
@@ -145,4 +145,3 @@
 	.mv_irq_demux           = se7722_irq_demux,
 
 };
-ALIAS_MV(se7722)
diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c
index e4c63a4..c3d1259 100644
--- a/arch/sh/boards/se/7751/irq.c
+++ b/arch/sh/boards/se/7751/irq.c
@@ -14,44 +14,31 @@
 #include <asm/irq.h>
 #include <asm/se7751.h>
 
-static struct ipr_data se7751_ipr_map[] = {
-  /* Leave old Solution Engine code in for reference. */
-#if defined(CONFIG_SH_SOLUTION_ENGINE)
-	/*
-	 * Super I/O (Just mimic PC):
-	 *  1: keyboard
-	 *  3: serial 0
-	 *  4: serial 1
-	 *  5: printer
-	 *  6: floppy
-	 *  8: rtc
-	 * 12: mouse
-	 * 14: ide0
-	 */
-	{ 14, BCR_ILCRA, 2, 0x0f-14 },
-	{ 12, BCR_ILCRA, 1, 0x0f-12 },
-	{  8, BCR_ILCRB, 1, 0x0f- 8 },
-	{  6, BCR_ILCRC, 3, 0x0f- 6 },
-	{  5, BCR_ILCRC, 2, 0x0f- 5 },
-	{  4, BCR_ILCRC, 1, 0x0f- 4 },
-	{  3, BCR_ILCRC, 0, 0x0f- 3 },
-	{  1, BCR_ILCRD, 3, 0x0f- 1 },
-
-	{ 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */
-
-	{  0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */
-	{ 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */
-	{  9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */
-	{  7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */
-
-	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
-	/* NOTE: #2 and #13 are not used on PC */
-	{ 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */
-	{  2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */
-#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
-	{ 13, BCR_ILCRD, 3, 2 },
+static struct ipr_data ipr_irq_table[] = {
+	{ 13, 3, 3, 2 },
 	/* Add additional entries here as drivers are added and tested. */
-#endif
+};
+
+static unsigned long ipr_offsets[] = {
+	BCR_ILCRA,
+	BCR_ILCRB,
+	BCR_ILCRC,
+	BCR_ILCRD,
+	BCR_ILCRE,
+	BCR_ILCRF,
+	BCR_ILCRG,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-se7751",
+	},
 };
 
 /*
@@ -59,5 +46,5 @@
  */
 void __init init_7751se_IRQ(void)
 {
-	make_ipr_irq(se7751_ipr_map, ARRAY_SIZE(se7751_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
index 52c7bfa..7873d07 100644
--- a/arch/sh/boards/se/7751/setup.c
+++ b/arch/sh/boards/se/7751/setup.c
@@ -48,7 +48,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_7751se __initmv = {
+static struct sh_machine_vector mv_7751se __initmv = {
 	.mv_name		= "7751 SolutionEngine",
 	.mv_nr_irqs		= 72,
 
@@ -71,4 +71,3 @@
 
 	.mv_init_irq		= init_7751se_IRQ,
 };
-ALIAS_MV(7751se)
diff --git a/arch/sh/boards/se/7780/irq.c b/arch/sh/boards/se/7780/irq.c
index 3d0625c..8749147 100644
--- a/arch/sh/boards/se/7780/irq.c
+++ b/arch/sh/boards/se/7780/irq.c
@@ -16,28 +16,6 @@
 #include <asm/io.h>
 #include <asm/se7780.h>
 
-#define INTC_INTMSK0             0xFFD00044
-#define INTC_INTMSKCLR0          0xFFD00064
-
-static void disable_se7780_irq(unsigned int irq)
-{
-	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC_INTMSK0 + p->msk_offset);
-}
-
-static void enable_se7780_irq(unsigned int irq)
-{
-	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC_INTMSKCLR0 + p->msk_offset);
-}
-
-static struct irq_chip se7780_irq_chip __read_mostly = {
-	.name           = "SE7780",
-	.mask           = disable_se7780_irq,
-	.unmask         = enable_se7780_irq,
-	.mask_ack       = disable_se7780_irq,
-};
-
 static struct intc2_data intc2_irq_table[] = {
 	{ 2,  0, 31, 0, 31, 3 }, /* daughter board EXTINT1 */
 	{ 4,  0, 30, 0, 30, 3 }, /* daughter board EXTINT2 */
@@ -51,13 +29,24 @@
 	{ 0 , 0, 24, 0, 24, 3 }, /* SM501 */
 };
 
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0, /* N/A */
+	.msk_base	= 0xffd00044,
+	.mskclr_base	= 0xffd00064,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-se7780",
+	},
+};
+
 /*
  * Initialize IRQ setting
  */
 void __init init_se7780_IRQ(void)
 {
-	int i ;
-
 	/* enable all interrupt at FPGA */
 	ctrl_outw(0, FPGA_INTMSK1);
 	/* mask SM501 interrupt */
@@ -79,11 +68,5 @@
 	/* FPGA + 0x0A */
 	ctrl_outw((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
 
-	for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) {
-		disable_irq_nosync(intc2_irq_table[i].irq);
-		set_irq_chip_and_handler_name( intc2_irq_table[i].irq, &se7780_irq_chip,
-			handle_level_irq, "level");
-		set_irq_chip_data( intc2_irq_table[i].irq, &intc2_irq_table[i] );
-		disable_se7780_irq(intc2_irq_table[i].irq);
-	}
+	register_intc2_controller(&intc2_irq_desc);
 }
diff --git a/arch/sh/boards/se/7780/setup.c b/arch/sh/boards/se/7780/setup.c
index df7d08a..723f2fd 100644
--- a/arch/sh/boards/se/7780/setup.c
+++ b/arch/sh/boards/se/7780/setup.c
@@ -113,10 +113,9 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_se7780 __initmv = {
+static struct sh_machine_vector mv_se7780 __initmv = {
 	.mv_name                = "Solution Engine 7780" ,
 	.mv_setup               = se7780_setup ,
 	.mv_nr_irqs		= 111 ,
 	.mv_init_irq		= init_se7780_IRQ,
 };
-ALIAS_MV(se7780)
diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c
index c069c44..9c031a8 100644
--- a/arch/sh/boards/sh03/setup.c
+++ b/arch/sh/boards/sh03/setup.c
@@ -15,17 +15,33 @@
 #include <asm/sh03/sh03.h>
 #include <asm/addrspace.h>
 
-static struct ipr_data sh03_ipr_map[] = {
-	{ IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY },
-	{ IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY },
-	{ IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY },
-	{ IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY },
+static struct ipr_data ipr_irq_table[] = {
+	{ IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
+	{ IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
+	{ IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
+	{ IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
+};
+
+static unsigned long ipr_offsets[] = {
+	INTC_IPRD,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh03",
+	},
 };
 
 static void __init init_sh03_IRQ(void)
 {
 	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
-	make_ipr_irq(sh03_ipr_map, ARRAY_SIZE(sh03_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
 extern void *cf_io_base;
@@ -74,11 +90,10 @@
 }
 __initcall(sh03_devices_setup);
 
-struct sh_machine_vector mv_sh03 __initmv = {
+static struct sh_machine_vector mv_sh03 __initmv = {
 	.mv_name		= "Interface (CTP/PCI-SH03)",
 	.mv_setup		= sh03_setup,
 	.mv_nr_irqs		= 48,
 	.mv_ioport_map		= sh03_ioport_map,
 	.mv_init_irq		= init_sh03_IRQ,
 };
-ALIAS_MV(sh03)
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
index 4a9df4a..dfd1245 100644
--- a/arch/sh/boards/shmin/setup.c
+++ b/arch/sh/boards/shmin/setup.c
@@ -6,28 +6,44 @@
  * SHMIN Support.
  */
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <asm/machvec.h>
 #include <asm/shmin.h>
 #include <asm/clock.h>
-#include <asm/irq.h>
 #include <asm/io.h>
 
 #define PFC_PHCR	0xa400010eUL
 #define INTC_ICR1	0xa4000010UL
 #define INTC_IPRC	0xa4000016UL
 
-static struct ipr_data shmin_ipr_map[] = {
-	{ .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 },
-	{ .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 },
-	{ .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 },
-	{ .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 },
+static struct ipr_data ipr_irq_table[] = {
+	{ 32, 0, 0, 0 },
+	{ 33, 0, 4, 0 },
+	{ 34, 0, 8, 8 },
+	{ 35, 0, 12, 0 },
+};
+
+static unsigned long ipr_offsets[] = {
+	INTC_IPRC,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-shmin",
+	},
 };
 
 static void __init init_shmin_irq(void)
 {
 	ctrl_outw(0x2a00, PFC_PHCR);	// IRQ0-3=IRQ
 	ctrl_outw(0x0aaa, INTC_ICR1);	// IRQ0-3=IRQ-mode,Low-active.
-	make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
 static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
@@ -43,9 +59,8 @@
 
 }
 
-struct sh_machine_vector mv_shmin __initmv = {
+static struct sh_machine_vector mv_shmin __initmv = {
 	.mv_name	= "SHMIN",
 	.mv_init_irq	= init_shmin_irq,
 	.mv_ioport_map	= shmin_ioport_map,
 };
-ALIAS_MV(shmin)
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index 650fb36..84271d8 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -68,11 +68,27 @@
  * IRL3 = crypto
  */
 
-static struct ipr_data snapgear_ipr_map[] = {
-	make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
-	make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
-	make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
-	make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
+static struct ipr_data ipr_irq_table[] = {
+	{ IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
+	{ IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
+	{ IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
+	{ IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
+};
+
+static unsigned long ipr_offsets[] = {
+	INTC_IPRD,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-snapgear",
+	},
 };
 
 static void __init init_snapgear_IRQ(void)
@@ -82,7 +98,7 @@
 
 	printk("Setup SnapGear IRQ/IPR ...\n");
 
-	make_ipr_irq(snapgear_ipr_map, ARRAY_SIZE(snapgear_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
 /*
@@ -96,7 +112,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_snapgear __initmv = {
+static struct sh_machine_vector mv_snapgear __initmv = {
 	.mv_name		= "SnapGear SecureEdge5410",
 	.mv_setup		= snapgear_setup,
 	.mv_nr_irqs		= 72,
@@ -117,4 +133,3 @@
 
 	.mv_init_irq		= init_snapgear_IRQ,
 };
-ALIAS_MV(snapgear)
diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
index 6396cea..fc8cd06 100644
--- a/arch/sh/boards/superh/microdev/setup.c
+++ b/arch/sh/boards/superh/microdev/setup.c
@@ -371,7 +371,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_sh4202_microdev __initmv = {
+static struct sh_machine_vector mv_sh4202_microdev __initmv = {
 	.mv_name		= "SH4-202 MicroDev",
 	.mv_setup		= microdev_setup,
 	.mv_nr_irqs		= 72,		/* QQQ need to check this - use the MACRO */
@@ -403,4 +403,3 @@
 	.mv_heartbeat		= microdev_heartbeat,
 #endif
 };
-ALIAS_MV(sh4202_microdev)
diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c
index 6bcd939..606d25a 100644
--- a/arch/sh/boards/titan/setup.c
+++ b/arch/sh/boards/titan/setup.c
@@ -12,7 +12,7 @@
 #include <asm/titan.h>
 #include <asm/io.h>
 
-static struct ipr_data titan_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR idx, shift, prio */
 	{ TITAN_IRQ_WAN,   3, 12, 8 },	/* eth0 (WAN) */
 	{ TITAN_IRQ_LAN,   3,  8, 8 },	/* eth1 (LAN) */
@@ -20,15 +20,33 @@
 	{ TITAN_IRQ_USB,   3,  0, 8 },	/* mPCI B (bottom), USB */
 };
 
+static unsigned long ipr_offsets[] = { /* stolen from setup-sh7750.c */
+	0xffd00004UL,	/* 0: IPRA */
+	0xffd00008UL,	/* 1: IPRB */
+	0xffd0000cUL,	/* 2: IPRC */
+	0xffd00010UL,	/* 3: IPRD */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-titan",
+	},
+};
 static void __init init_titan_irq(void)
 {
 	/* enable individual interrupt mode for externals */
 	ipr_irq_enable_irlm();
 	/* register ipr irqs */
-	make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
-struct sh_machine_vector mv_titan __initmv = {
+static struct sh_machine_vector mv_titan __initmv = {
 	.mv_name =	"Titan",
 
 	.mv_inb =	titan_inb,
@@ -52,4 +70,3 @@
 
 	.mv_init_irq =	init_titan_irq,
 };
-ALIAS_MV(titan)
diff --git a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile
deleted file mode 100644
index 7d18f40..0000000
--- a/arch/sh/boards/unknown/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for unknown SH boards 
-#
-
-obj-y	 := setup.o
-
diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c
deleted file mode 100644
index bee4612..0000000
--- a/arch/sh/boards/unknown/setup.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/arch/sh/boards/unknown/setup.c
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Setup code for an unknown machine (internal peripherals only)
- *
- * This is the simplest of all boards, and serves only as a quick and dirty
- * method to start debugging a new board during bring-up until proper board
- * setup code is written.
- */
-#include <linux/init.h>
-#include <asm/machvec.h>
-
-struct sh_machine_vector mv_unknown __initmv = {
-	.mv_name		= "Unknown",
-};
-ALIAS_MV(unknown)
diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig
index 0582ca8..2e516e9 100644
--- a/arch/sh/cchips/Kconfig
+++ b/arch/sh/cchips/Kconfig
@@ -13,10 +13,8 @@
 	  are additional GPIO bits that can be used to interface to
 	  external as well.
 
-# A board must have defined HD6446X_SERIES in order to see these
 config HD6446X_SERIES
-	bool "HD6446x support"
-	default n
+	bool
 
 choice
 	prompt "HD6446x options"
@@ -25,7 +23,6 @@
 
 config HD64461
 	bool "Hitachi HD64461 companion chip support"
-	depends on CPU_SUBTYPE_SH7709
 	---help---
 	  The Hitachi HD64461 provides an interface for
 	  the SH7709 CPU, supporting a LCD controller,
@@ -40,7 +37,6 @@
 
 config HD64465
 	bool "Hitachi HD64465 companion chip support"
-	depends on CPU_SUBTYPE_SH7750
 	---help---
 	  The Hitachi HD64465 provides an interface for
 	  the SH7750 CPU, supporting a LCD controller,
diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
index 8b6b5a7..3fdd270 100644
--- a/arch/sh/configs/dreamcast_defconfig
+++ b/arch/sh/configs/dreamcast_defconfig
@@ -1,15 +1,23 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 10:51:55 2006
+# Linux kernel version: 2.6.22-rc4
+# Sat Jul  7 03:47:45 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -28,6 +36,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
@@ -35,8 +44,10 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -50,14 +61,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -93,44 +109,9 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-CONFIG_SH_DREAMCAST=y
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH4=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
-
-#
-# SH-3 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -138,79 +119,93 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
-CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
 CONFIG_CPU_SUBTYPE_SH7091=y
-CONFIG_CPU_SUBTYPE_SH7750R=y
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
 # CONFIG_CPU_SUBTYPE_SH7750S is not set
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
 
 #
-# Timer support
+# Board support
+#
+CONFIG_SH_DREAMCAST=y
+
+#
+# Timer and clock configuration
 #
 CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=49876504
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
 
 #
 # CPU Frequency scaling
@@ -232,6 +227,7 @@
 #
 # DMA support
 #
+CONFIG_SH_DMA_API=y
 CONFIG_SH_DMA=y
 CONFIG_NR_ONCHIP_DMA_CHANNELS=4
 CONFIG_NR_DMA_CHANNELS_BOOL=y
@@ -240,17 +236,23 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
 
 #
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
@@ -269,33 +271,23 @@
 # Bus options
 #
 CONFIG_PCI=y
-# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # 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_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -303,13 +295,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -327,30 +319,20 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -376,7 +358,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -394,10 +385,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -408,6 +395,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -421,13 +409,16 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
-# ATA/ATAPI/MFM/RLL support
+# Misc devices
 #
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -436,10 +427,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -455,6 +442,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -470,15 +458,7 @@
 # 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
 
 #
@@ -521,47 +501,16 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE 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_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_SC92031 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -604,17 +553,19 @@
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=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_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -660,10 +611,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -680,14 +627,8 @@
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
 CONFIG_HW_RANDOM=y
-# 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
 
@@ -695,11 +636,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -711,44 +648,51 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -763,13 +707,17 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 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_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -789,10 +737,6 @@
 # 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 is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
@@ -800,7 +744,6 @@
 # CONFIG_LOGO_SUPERH_MONO is not set
 # CONFIG_LOGO_SUPERH_VGA16 is not set
 CONFIG_LOGO_SUPERH_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -808,6 +751,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -823,10 +772,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -874,10 +819,12 @@
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -957,6 +904,11 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 CONFIG_PROFILING=y
@@ -965,17 +917,18 @@
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
+# CONFIG_SH_KGDB is not set
 
 #
 # Security options
@@ -991,8 +944,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig
new file mode 100644
index 0000000..17f7402
--- /dev/null
+++ b/arch/sh/configs/r7780mp_defconfig
@@ -0,0 +1,1223 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Mon Jun 11 10:24:57 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=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_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_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_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+# CONFIG_32BIT is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB 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=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_DSP is not set
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_SPECULATIVE_EXECUTION=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Board support
+#
+# CONFIG_SH_7780_SOLUTION_ENGINE is not set
+CONFIG_SH_HIGHLANDER=y
+# CONFIG_SH_R7780RP is not set
+CONFIG_SH_R7780MP=y
+# CONFIG_SH_R7785RP is not set
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_PCLK_FREQ=32000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+CONFIG_PUSH_SWITCH=y
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE 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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL 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
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI 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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+# 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_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+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=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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP 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_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_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP 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_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# 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
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# CONFIG_PCNET32_NAPI 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=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+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=m
+CONFIG_VIA_RHINE_MMIO=y
+# CONFIG_VIA_RHINE_NAPI is not set
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# 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
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_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_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_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
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OSS_OBSOLETE is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# 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=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_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_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=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_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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=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=y
+# 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=y
+# 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
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC 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_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT 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_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig
index 0f5ec64..5c29338 100644
--- a/arch/sh/configs/r7785rp_defconfig
+++ b/arch/sh/configs/r7785rp_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Mon Mar 12 14:26:33 2007
+# Linux kernel version: 2.6.22-rc4
+# Thu Jul 12 12:33:15 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,7 +11,9 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_PCI=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -43,6 +45,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
@@ -60,13 +63,18 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -102,55 +110,11 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-CONFIG_SH_HIGHLANDER=y
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_UNKNOWN is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_R7780MP is not set
-CONFIG_SH_R7785RP=y
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH4=y
 CONFIG_CPU_SH4A=y
 CONFIG_CPU_SHX2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -158,10 +122,7 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -170,23 +131,12 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 CONFIG_CPU_SUBTYPE_SH7785=y
-
-#
-# SH4AL-DSP Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
@@ -194,6 +144,7 @@
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x08000000
@@ -201,6 +152,12 @@
 CONFIG_32BIT=y
 # CONFIG_X2TLB is not set
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -215,17 +172,17 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
@@ -241,12 +198,22 @@
 CONFIG_CPU_HAS_PTEA=y
 
 #
+# Board support
+#
+CONFIG_SH_HIGHLANDER=y
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_R7780MP is not set
+CONFIG_SH_R7785RP=y
+
+#
 # Timer and clock configuration
 #
 CONFIG_SH_TMU=y
 CONFIG_SH_TIMER_IRQ=28
-CONFIG_NO_IDLE_HZ=y
 CONFIG_SH_PCLK_FREQ=50000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
 
 #
 # CPU Frequency scaling
@@ -261,7 +228,6 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
@@ -278,7 +244,7 @@
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_KEXEC=y
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
@@ -300,31 +266,22 @@
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # 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_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -332,7 +289,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -377,20 +333,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK 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
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 CONFIG_BRIDGE=m
@@ -417,8 +361,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
 CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -438,10 +390,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -475,12 +423,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -509,6 +455,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -554,10 +501,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
@@ -580,6 +523,7 @@
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -629,6 +573,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -644,15 +589,7 @@
 # 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
 
 #
@@ -673,10 +610,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -689,55 +623,26 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 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_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -789,6 +694,7 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -831,14 +737,8 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_DRM is not set
@@ -848,10 +748,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -864,16 +761,15 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -885,22 +781,30 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -908,7 +812,7 @@
 # CONFIG_FB_TILEBLITTING is not set
 
 #
-# Frambuffer hardware drivers
+# Frame buffer hardware drivers
 #
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
@@ -930,12 +834,11 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_VIRTUAL is not set
-
-#
-# Logo configuration
-#
 # CONFIG_LOGO is not set
 
 #
@@ -952,13 +855,10 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=m
-# CONFIG_OBSOLETE_OSS is not set
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ICH is not set
+# CONFIG_OSS_OBSOLETE is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 
 #
 # HID Devices
@@ -982,10 +882,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1026,18 +922,30 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_SH=y
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -1051,14 +959,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1157,6 +1057,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1239,7 +1140,6 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1266,6 +1166,7 @@
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_4KSTACKS is not set
@@ -1300,6 +1201,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
@@ -1328,7 +1230,9 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index 87ab908..f2f2a3c 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -1,18 +1,22 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Wed Dec  6 14:40:15 2006
+# Linux kernel version: 2.6.22-rc4
+# Fri Jun 15 19:37:46 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -34,8 +38,10 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -48,12 +54,17 @@
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
-CONFIG_SLAB=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 # CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -83,53 +94,10 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-CONFIG_SH_7206_SOLUTION_ENGINE=y
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH2=y
 CONFIG_CPU_SH2A=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
 CONFIG_CPU_SUBTYPE_SH7206=y
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -137,10 +105,7 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -149,32 +114,28 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 # CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -184,35 +145,42 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
 #
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_SH_FPU is not set
 # CONFIG_SH_FPU_EMU is not set
 # CONFIG_SH_DSP is not set
+CONFIG_CPU_HAS_IPR_IRQ=y
 
 #
-# Timer support
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7206_SOLUTION_ENGINE=y
+
+#
+# Timer and clock configuration
 #
 CONFIG_SH_CMT=y
 # CONFIG_SH_MTU2 is not set
 CONFIG_SH_TIMER_IRQ=140
-# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=33333333
 CONFIG_SH_CLK_MD=6
+# CONFIG_TICK_ONESHOT is not set
 
 #
 # CPU Frequency scaling
@@ -227,11 +195,11 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
 #
+# CONFIG_HEARTBEAT is not set
 # CONFIG_PUSH_SWITCH is not set
 
 #
@@ -239,10 +207,11 @@
 #
 CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -252,23 +221,18 @@
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
-# CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
 #
 # Bus options
 #
-# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Executable file formats
 #
 CONFIG_BINFMT_FLAT=y
@@ -277,11 +241,6 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -289,7 +248,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 # CONFIG_UNIX is not set
 # CONFIG_NET_KEY is not set
@@ -314,25 +272,14 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -358,7 +305,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -375,10 +331,6 @@
 # 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=y
@@ -393,6 +345,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -424,7 +377,6 @@
 # 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
 
 #
 # Mapping drivers for chip access
@@ -452,16 +404,13 @@
 # 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
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -471,6 +420,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -479,18 +429,13 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -499,10 +444,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -511,19 +452,6 @@
 # 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
@@ -531,10 +459,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -544,27 +468,14 @@
 CONFIG_MII=y
 # CONFIG_STNIC is not set
 CONFIG_SMC91X=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -604,6 +515,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -639,29 +551,15 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM 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
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -674,27 +572,30 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -703,6 +604,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -717,10 +624,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -802,7 +705,6 @@
 CONFIG_PROC_SYSCTL=y
 # CONFIG_SYSFS is not set
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -816,7 +718,6 @@
 # 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 is not set
 # CONFIG_VXFS_FS is not set
@@ -849,6 +750,11 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -861,14 +767,11 @@
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_UNWIND_INFO is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
 
 #
 # Security options
@@ -883,8 +786,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig
index 20ac7f4..3a3c3c1 100644
--- a/arch/sh/configs/se7619_defconfig
+++ b/arch/sh/configs/se7619_defconfig
@@ -1,18 +1,22 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Wed Dec  6 16:35:36 2006
+# Linux kernel version: 2.6.22-rc4
+# Fri Jun 15 19:43:06 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -31,8 +35,10 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -45,12 +51,17 @@
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
-CONFIG_SLAB=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 # CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -80,52 +91,9 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-CONFIG_SH_7619_SOLUTION_ENGINE=y
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 CONFIG_CPU_SUBTYPE_SH7619=y
-
-#
-# SH-2A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -133,10 +101,7 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -145,32 +110,28 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 # CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -180,34 +141,41 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 CONFIG_SH_WRITETHROUGH=y
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
 #
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_SH_FPU is not set
 # CONFIG_SH_FPU_EMU is not set
 # CONFIG_SH_DSP is not set
+CONFIG_CPU_HAS_IPR_IRQ=y
 
 #
-# Timer support
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7619_SOLUTION_ENGINE=y
+
+#
+# Timer and clock configuration
 #
 CONFIG_SH_CMT=y
 CONFIG_SH_TIMER_IRQ=86
-# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=31250000
 CONFIG_SH_CLK_MD=5
+# CONFIG_TICK_ONESHOT is not set
 
 #
 # CPU Frequency scaling
@@ -222,11 +190,11 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
 #
+# CONFIG_HEARTBEAT is not set
 # CONFIG_PUSH_SWITCH is not set
 
 #
@@ -234,10 +202,11 @@
 #
 CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -247,23 +216,18 @@
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
-# CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
 #
 # Bus options
 #
-# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Executable file formats
 #
 CONFIG_BINFMT_FLAT=y
@@ -272,11 +236,6 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 # CONFIG_NET is not set
@@ -295,10 +254,6 @@
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
@@ -313,6 +268,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -344,7 +300,6 @@
 # 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
 
 #
 # Mapping drivers for chip access
@@ -372,16 +327,13 @@
 # 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
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -391,6 +343,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -398,17 +351,12 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -417,10 +365,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -429,19 +373,6 @@
 # CONFIG_MD is not set
 
 #
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
 # ISDN subsystem
 #
 
@@ -471,6 +402,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -506,29 +438,15 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM 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
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -541,26 +459,29 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -569,6 +490,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -583,10 +510,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -668,7 +591,6 @@
 CONFIG_PROC_SYSCTL=y
 # CONFIG_SYSFS is not set
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -682,7 +604,6 @@
 # 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 is not set
 # CONFIG_VXFS_FS is not set
@@ -715,14 +636,11 @@
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_UNWIND_INFO is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
 
 #
 # Security options
@@ -737,8 +655,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig
index ca4c663..764b813 100644
--- a/arch/sh/configs/se7722_defconfig
+++ b/arch/sh/configs/se7722_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc7
-# Fri Apr 27 16:30:30 2007
+# Linux kernel version: 2.6.22-rc4
+# Wed Jun 20 18:08:04 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,7 +11,9 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -43,6 +45,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -60,14 +63,20 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -103,57 +112,12 @@
 #
 # System type
 #
-CONFIG_SOLUTION_ENGINE=y
-# CONFIG_SH_SOLUTION_ENGINE is not set
-CONFIG_SH_7722_SOLUTION_ENGINE=y
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7780_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_HIGHLANDER is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_LBOX_RE2 is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH4=y
 CONFIG_CPU_SH4A=y
 CONFIG_CPU_SH4AL_DSP=y
 CONFIG_CPU_SHX2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -162,10 +126,6 @@
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
 # CONFIG_CPU_SUBTYPE_SH7712 is not set
-
-#
-# SH-4 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -174,23 +134,11 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 # CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 CONFIG_CPU_SUBTYPE_SH7722=y
@@ -198,15 +146,21 @@
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
-# CONFIG_32BIT is not set
 # CONFIG_X2TLB is not set
 CONFIG_VSYSCALL=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=1
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=2
 CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -216,26 +170,25 @@
 # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_MEMORY_HOTPLUG is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
 
 #
 # Processor features
@@ -252,12 +205,20 @@
 CONFIG_CPU_HAS_PTEA=y
 
 #
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7722_SOLUTION_ENGINE=y
+
+#
 # Timer and clock configuration
 #
 CONFIG_SH_TMU=y
 CONFIG_SH_TIMER_IRQ=16
-CONFIG_NO_IDLE_HZ=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 
 #
 # CPU Frequency scaling
@@ -272,7 +233,6 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
@@ -290,7 +250,6 @@
 CONFIG_HZ=250
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
-# CONFIG_SMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
@@ -307,7 +266,11 @@
 #
 # Bus options
 #
-# CONFIG_PCI is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -315,22 +278,12 @@
 # CONFIG_PCCARD is not set
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -338,7 +291,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -375,20 +327,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK 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
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -414,7 +354,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -432,10 +381,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -464,10 +409,7 @@
 #
 # Misc devices
 #
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -496,6 +438,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -511,10 +454,6 @@
 #
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_PATA_PLATFORM=y
@@ -525,19 +464,6 @@
 # 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
@@ -545,10 +471,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -558,27 +480,14 @@
 CONFIG_MII=y
 # CONFIG_STNIC is not set
 CONFIG_SMC91X=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -627,6 +536,7 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -667,14 +577,8 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -682,10 +586,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -698,16 +598,15 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -719,16 +618,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -757,10 +659,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -800,18 +698,30 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_SH=y
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -825,14 +735,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -937,23 +839,24 @@
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
 
 #
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_SH_KGDB is not set
 
 #
@@ -973,8 +876,10 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig
new file mode 100644
index 0000000..219bad5
--- /dev/null
+++ b/arch/sh/configs/shx3_defconfig
@@ -0,0 +1,756 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Wed Jun 20 14:09:27 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=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_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_UTS_NS is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX3=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+CONFIG_CPU_SUBTYPE_SHX3=y
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB 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=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Board support
+#
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 ip=192.168.1.2:::255.255.255.0 root=/dev/nfs nfsroot=192.168.1.1:/exports/devel/rfs/mobiler noaliencache earlyprintk=bios ignore_loglevel"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+# CONFIG_NET 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
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# Misc devices
+#
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_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_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# 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 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_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
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# 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_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SLAB_LEAK=y
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_LOCKDEP=y
+CONFIG_DEBUG_LOCKDEP=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 99935f9..3338980 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -36,23 +36,6 @@
 	  support. Setting this to a higher value allows for cascading DMACs
 	  with additional channels.
 
-config DMA_PAGE_OPS
-	bool "Use DMAC for page copy/clear"
-	depends on SH_DMA && BROKEN
-	help
-	  Selecting this option will use a dual-address mode configured channel
-	  in the SH DMAC for copy_page()/clear_page(). Primarily a performance
-	  hack.
-
-config DMA_PAGE_OPS_CHANNEL
-	depends on DMA_PAGE_OPS
-	int "DMA channel for sh memory-manager page copy/clear"
-	default "3"
-	help
-	  This allows the specification of the dual address dma channel,
-	  in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
-	  are dual-address capable.
-
 config SH_DMABRG
 	bool "SH7760 DMABRG support"
 	depends on CPU_SUBTYPE_SH7760
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
index 6d1cbbe..fbc6f2c 100644
--- a/arch/sh/drivers/pci/Kconfig
+++ b/arch/sh/drivers/pci/Kconfig
@@ -1,5 +1,6 @@
 config PCI
 	bool "PCI support"
+	depends on SYS_SUPPORTS_PCI
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 9104b62..1f141a8 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -4,10 +4,9 @@
 
 extra-y	:= head.o init_task.o vmlinux.lds
 
-obj-y	:= process.o signal.o traps.o irq.o \
-	ptrace.o setup.o time.o sys_sh.o semaphore.o \
-	io.o io_generic.o sh_ksyms.o syscalls.o \
-	debugtraps.o
+obj-y	:= debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \
+	   semaphore.o setup.o signal.o sys_sh.o syscalls.o \
+	   time.o topology.o traps.o
 
 obj-y				+= cpu/ timers/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
@@ -17,7 +16,7 @@
 obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
 obj-$(CONFIG_SH_KGDB)		+= kgdb_stub.o kgdb_jmp.o
 obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
-obj-$(CONFIG_MODULES)		+= module.o
+obj-$(CONFIG_MODULES)		+= sh_ksyms.o module.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
index ebc73b8..1c3b996 100644
--- a/arch/sh/kernel/cf-enabler.c
+++ b/arch/sh/kernel/cf-enabler.c
@@ -75,11 +75,7 @@
 #if defined(CONFIG_CPU_SH4)
 	allocate_cf_area();
 #endif
-#if defined(CONFIG_SH_UNKNOWN)
-	/* This should be done in each board's init_xxx_irq. */
-	make_imask_irq(14);
-	disable_irq(14);
-#endif
+
 	return 0;
 }
 
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 6451ad6..9172e97 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -21,8 +21,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
 #include <asm/io.h>
-
-extern void detect_cpu_and_cache_system(void);
+#include <asm/ubc.h>
 
 /*
  * Generic wrapper for command line arguments to disable on-chip
@@ -152,15 +151,6 @@
 	flags |= CCR_CACHE_CB;
 #endif
 
-#ifdef CONFIG_SH_OCRAM
-	/* Turn on OCRAM -- halve the OC */
-	flags |= CCR_CACHE_ORA;
-	current_cpu_data.dcache.sets >>= 1;
-
-	current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
-				    current_cpu_data.dcache.linesz;
-#endif
-
 	ctrl_outl(flags, CCR);
 	back_to_P1();
 }
@@ -269,7 +259,6 @@
 	}
 #endif
 
-#ifdef CONFIG_UBC_WAKEUP
 	/*
 	 * Some brain-damaged loaders decided it would be a good idea to put
 	 * the UBC to sleep. This causes some issues when it comes to things
@@ -277,7 +266,5 @@
 	 * we wake it up and hope that all is well.
 	 */
 	ubc_wakeup();
-#endif
-
 	speculative_execution_init();
 }
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index d8e22f4..cc52213 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -13,36 +13,31 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <asm/smp.h>
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define INTC2_BASE	0xfe080000
-#define INTC2_INTMSK	(INTC2_BASE + 0x40)
-#define INTC2_INTMSKCLR	(INTC2_BASE + 0x60)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7785)
-#define INTC2_BASE	0xffd40000
-#define INTC2_INTMSK	(INTC2_BASE + 0x38)
-#define INTC2_INTMSKCLR	(INTC2_BASE + 0x3c)
-#endif
+static inline struct intc2_desc *get_intc2_desc(unsigned int irq)
+{
+	struct irq_chip *chip = get_irq_chip(irq);
+	return (void *)((char *)chip - offsetof(struct intc2_desc, chip));
+}
 
 static void disable_intc2_irq(unsigned int irq)
 {
 	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
+	struct intc2_desc *d = get_intc2_desc(irq);
+
+	ctrl_outl(1 << p->msk_shift, d->msk_base + p->msk_offset +
+				     (hard_smp_processor_id() * 4));
 }
 
 static void enable_intc2_irq(unsigned int irq)
 {
 	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
-}
+	struct intc2_desc *d = get_intc2_desc(irq);
 
-static struct irq_chip intc2_irq_chip = {
-	.name		= "INTC2",
-	.mask		= disable_intc2_irq,
-	.unmask		= enable_intc2_irq,
-	.mask_ack	= disable_intc2_irq,
-};
+	ctrl_outl(1 << p->msk_shift, d->mskclr_base + p->msk_offset +
+				     (hard_smp_processor_id() * 4));
+}
 
 /*
  * Setup an INTC2 style interrupt.
@@ -56,30 +51,36 @@
  *
  * in the intc2_data table.
  */
-void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
+void register_intc2_controller(struct intc2_desc *desc)
 {
 	int i;
 
-	for (i = 0; i < nr_irqs; i++) {
+	desc->chip.mask = disable_intc2_irq;
+	desc->chip.unmask = enable_intc2_irq;
+	desc->chip.mask_ack = disable_intc2_irq;
+
+	for (i = 0; i < desc->nr_irqs; i++) {
 		unsigned long ipr, flags;
-		struct intc2_data *p = table + i;
+		struct intc2_data *p = desc->intc2_data + i;
 
 		disable_irq_nosync(p->irq);
 
-		/* Set the priority level */
-		local_irq_save(flags);
+		if (desc->prio_base) {
+			/* Set the priority level */
+			local_irq_save(flags);
 
-		ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
-		ipr &= ~(0xf << p->ipr_shift);
-		ipr |= p->priority << p->ipr_shift;
-		ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
+			ipr = ctrl_inl(desc->prio_base + p->ipr_offset);
+			ipr &= ~(0xf << p->ipr_shift);
+			ipr |= p->priority << p->ipr_shift;
+			ctrl_outl(ipr, desc->prio_base + p->ipr_offset);
 
-		local_irq_restore(flags);
+			local_irq_restore(flags);
+		}
 
-		set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
+		set_irq_chip_and_handler_name(p->irq, &desc->chip,
 					      handle_level_irq, "level");
 		set_irq_chip_data(p->irq, p);
 
-		enable_intc2_irq(p->irq);
+		disable_intc2_irq(p->irq);
 	}
 }
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 210280b..98e84f4 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -22,58 +22,57 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 
+static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
+{
+	struct irq_chip *chip = get_irq_chip(irq);
+	return (void *)((char *)chip - offsetof(struct ipr_desc, chip));
+}
+
 static void disable_ipr_irq(unsigned int irq)
 {
 	struct ipr_data *p = get_irq_chip_data(irq);
+	unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
 	/* Set the priority in IPR to 0 */
-	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
+	ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr);
 }
 
 static void enable_ipr_irq(unsigned int irq)
 {
 	struct ipr_data *p = get_irq_chip_data(irq);
+	unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
 	/* Set priority in IPR back to original value */
-	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
+	ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr);
 }
 
-static struct irq_chip ipr_irq_chip = {
-	.name		= "IPR",
-	.mask		= disable_ipr_irq,
-	.unmask		= enable_ipr_irq,
-	.mask_ack	= disable_ipr_irq,
-};
+/*
+ * The shift value is now the number of bits to shift, not the number of
+ * bits/4. This is to make it easier to read the value directly from the
+ * datasheets. The IPR address is calculated using the ipr_offset table.
+ */
 
-unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
-unsigned int map_ipridx_to_addr(int idx)
-{
-	return 0;
-}
-
-void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
+void register_ipr_controller(struct ipr_desc *desc)
 {
 	int i;
 
-	for (i = 0; i < nr_irqs; i++) {
-		unsigned int irq = table[i].irq;
+	desc->chip.mask = disable_ipr_irq;
+	desc->chip.unmask = enable_ipr_irq;
+	desc->chip.mask_ack = disable_ipr_irq;
 
-		if (!irq)
-			irq = table[i].irq = i;
+	for (i = 0; i < desc->nr_irqs; i++) {
+		struct ipr_data *p = desc->ipr_data + i;
 
-		/* could the IPR index be mapped, if not we ignore this */
-		if (!table[i].addr) {
-			table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
-			if (!table[i].addr)
-				continue;
-		}
+		BUG_ON(p->ipr_idx >= desc->nr_offsets);
+		BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
 
-		disable_irq_nosync(irq);
-		set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
+		disable_irq_nosync(p->irq);
+		set_irq_chip_and_handler_name(p->irq, &desc->chip,
 				      handle_level_irq, "level");
-		set_irq_chip_data(irq, &table[i]);
-		enable_ipr_irq(irq);
+		set_irq_chip_data(p->irq, p);
+		disable_ipr_irq(p->irq);
 	}
 }
-EXPORT_SYMBOL(make_ipr_irq);
+
+EXPORT_SYMBOL(register_ipr_controller);
 
 #if !defined(CONFIG_CPU_HAS_PINT_IRQ)
 int ipr_irq_demux(int irq)
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index c16dc8f..ee8f1fe 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -311,6 +311,7 @@
 	rte
 	 nop
 
+	.align 2
 #ifdef CONFIG_TRACE_IRQFLAGS
 1:     .long   trace_hardirqs_off
 #endif
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index 108e81b..abbf174 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -9,23 +9,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
-
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 
 int __init detect_cpu_and_cache_system(void)
 {
-#if defined(CONFIG_CPU_SUBTYPE_SH7604)
-	current_cpu_data.type			= CPU_SH7604;
-	current_cpu_data.dcache.ways		= 4;
-	current_cpu_data.dcache.way_incr	= (1<<10);
-	current_cpu_data.dcache.sets		= 64;
-	current_cpu_data.dcache.entry_shift	= 4;
-	current_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
-	current_cpu_data.dcache.flags		= 0;
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
 	current_cpu_data.type			= CPU_SH7619;
 	current_cpu_data.dcache.ways		= 4;
 	current_cpu_data.dcache.way_incr	= (1<<12);
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index f83ff8a..1a107fe 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -52,7 +52,7 @@
 }
 __initcall(sh7619_devices_setup);
 
-static struct ipr_data sh7619_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	{ 86, 0,  4, 2 },	/* CMI0 */
 	{ 88, 1, 12, 3 },	/* SCIF0_ERI */
 	{ 89, 1, 12, 3 },	/* SCIF0_RXI */
@@ -68,7 +68,7 @@
 	{ 99, 1,  4, 3 },	/* SCIF2_TXI */
 };
 
-static unsigned int ipr_offsets[] = {
+static unsigned long ipr_offsets[] = {
 	0xf8080000,	/* IPRC */
 	0xf8080002,	/* IPRD */
 	0xf8080004,	/* IPRE */
@@ -76,15 +76,19 @@
 	0xf8080008,	/* IPRG */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7619",
+	},
+};
 
 void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index 4ed9110..b6e3a63 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -57,7 +57,7 @@
 }
 __initcall(sh7206_devices_setup);
 
-static struct ipr_data sh7206_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	{ 140,  7, 12, 2 },	/* CMI0 */
 	{ 164,  8,  4, 2 },	/* MTU2_TGI1A */
 	{ 240, 13, 12, 3 },	/* SCIF0_BRI */
@@ -78,7 +78,7 @@
 	{ 255, 13,  0, 3 },	/* SCIF3_TXI */
 };
 
-static unsigned int ipr_offsets[] = {
+static unsigned long ipr_offsets[] = {
 	0xfffe0818,	/* IPR01 */
 	0xfffe081a,	/* IPR02 */
 	0,		/* unused */
@@ -95,15 +95,19 @@
 	0xfffe0c10,	/* IPR14 */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7206",
+	},
+};
 
 void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index b0b59d4..d8e1229 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -340,8 +340,27 @@
 general_exception:
 	mov.l	1f, k2
 	mov.l	2f, k3
+#ifdef CONFIG_CPU_SUBTYPE_SHX3
+	mov.l	@k2, k2
+
+	! Is EXPEVT larger than 0x800?
+	mov	#0x8, k0
+	shll8	k0
+	cmp/hs	k0, k2
+	bf	0f
+
+	! then add 0x580 (k2 is 0xd80 or 0xda0)
+	mov	#0x58, k0
+	shll2	k0
+	shll2	k0
+	add	k0, k2
+0:
+	bra	handle_exception
+	 nop
+#else
 	bra	handle_exception
 	 mov.l	@k2, k2
+#endif
 	.align	2
 1:	.long	EXPEVT
 2:	.long	ret_from_exception
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index 1983fb7..a55b8ce 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -48,7 +48,7 @@
 }
 __initcall(sh7705_devices_setup);
 
-static struct ipr_data sh7705_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0,  8, 2 }, /* TMU1 TUNI */
@@ -70,25 +70,29 @@
 };
 
 static unsigned long ipr_offsets[] = {
-	0xFFFFFEE2	/* 0: IPRA */
-,	0xFFFFFEE4	/* 1: IPRB */
-,	0xA4000016	/* 2: IPRC */
-,	0xA4000018	/* 3: IPRD */
-,	0xA400001A	/* 4: IPRE */
-,	0xA4080000	/* 5: IPRF */
-,	0xA4080002	/* 6: IPRG */
-,	0xA4080004	/* 7: IPRH */
+	0xFFFFFEE2,	/* 0: IPRA */
+	0xFFFFFEE4,	/* 1: IPRB */
+	0xA4000016,	/* 2: IPRC */
+	0xA4000018,	/* 3: IPRD */
+	0xA400001A,	/* 4: IPRE */
+	0xA4080000,	/* 5: IPRF */
+	0xA4080002,	/* 6: IPRG */
+	0xA4080004,	/* 7: IPRH */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
 
-void __init init_IRQ_ipr()
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7705",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
index c7d7c35..d79ec0c 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
@@ -12,6 +12,26 @@
 #include <linux/serial.h>
 #include <asm/sci.h>
 
+static struct resource rtc_resources[] = {
+	[0] =	{
+		.start	= 0xfffffec0,
+		.end	= 0xfffffec0 + 0x1e,
+		.flags  = IORESOURCE_IO,
+	},
+	[1] =	{
+		.start  = 20,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] =	{
+		.start	= 21,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] =	{
+		.start	= 22,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xfffffe80,
@@ -41,8 +61,16 @@
 	},
 };
 
+static struct platform_device rtc_device = {
+	.name		= "sh-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtc_resources),
+	.resource	= rtc_resources,
+};
+
 static struct platform_device *sh7709_devices[] __initdata = {
 	&sci_device,
+	&rtc_device,
 };
 
 static int __init sh7709_devices_setup(void)
@@ -52,32 +80,66 @@
 }
 __initcall(sh7709_devices_setup);
 
-#define IPRx(A,N)	.addr=A, .shift=N
-#define IPRA(N)	IPRx(0xfffffee2UL,N)
-#define IPRB(N)	IPRx(0xfffffee4UL,N)
-#define IPRC(N)	IPRx(0xa4000016UL,N)
-#define IPRD(N)	IPRx(0xa4000018UL,N)
-#define IPRE(N)	IPRx(0xa400001aUL,N)
+static struct ipr_data ipr_irq_table[] = {
+	{ 16, 0, 12, 2 }, /* TMU TUNI0 */
+	{ 17, 0, 8,  4 }, /* TMU TUNI1 */
+	{ 18, 0, 4,  1 }, /* TMU TUNI1 */
+	{ 19, 0, 4,  1 }, /* TMU TUNI1 */
+	{ 20, 0, 0,  2 }, /* RTC CUI */
+	{ 21, 0, 0,  2 }, /* RTC CUI */
+	{ 22, 0, 0,  2 }, /* RTC CUI */
 
-static struct ipr_data sh7709_ipr_map[] = {
-	[16]		= { IPRA(12), 2 }, /* TMU TUNI0 */
-	[17]		= { IPRA(8),  4 }, /* TMU TUNI1 */
-	[18 ... 19]	= { IPRA(4),  1 }, /* TMU TUNI1 */
-	[20 ... 22]	= { IPRA(0),  2 }, /* RTC CUI */
-	[23 ... 26]	= { IPRB(4),  3 }, /* SCI */
-	[27]		= { IPRB(12), 2 }, /* WDT ITI */
-	[32]		= { IPRC(0),  1 }, /* IRQ 0 */
-	[33]		= { IPRC(4),  1 }, /* IRQ 1 */
-	[34]		= { IPRC(8),  1 }, /* IRQ 2 APM */
-	[35]		= { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */
-	[36]		= { IPRD(0),  1 }, /* IRQ 4 */
-	[37]		= { IPRD(4),  1 }, /* IRQ 5 */
-	[48 ... 51]	= { IPRE(12), 7 }, /* DMA */
-	[52 ... 55]	= { IPRE(8),  3 }, /* IRDA */
-	[56 ... 59]	= { IPRE(4),  3 }, /* SCIF */
+	{ 23, 1, 4,  3 }, /* SCI */
+	{ 24, 1, 4,  3 }, /* SCI */
+	{ 25, 1, 4,  3 }, /* SCI */
+	{ 26, 1, 4,  3 }, /* SCI */
+	{ 27, 1, 12, 3 }, /* WDT ITI */
+
+	{ 32, 2, 0,  1 }, /* IRQ 0 */
+	{ 33, 2, 4,  1 }, /* IRQ 1 */
+	{ 34, 2, 8,  1 }, /* IRQ 2 APM */
+	{ 35, 2, 12, 1 }, /* IRQ 3 TOUCHSCREEN */
+
+	{ 36, 3, 0,  1 }, /* IRQ 4 */
+	{ 37, 3, 4,  1 }, /* IRQ 5 */
+
+	{ 48, 4, 12, 7 }, /* DMA */
+	{ 49, 4, 12, 7 }, /* DMA */
+	{ 50, 4, 12, 7 }, /* DMA */
+	{ 51, 4, 12, 7 }, /* DMA */
+
+	{ 52, 4, 8,  3 }, /* IRDA */
+	{ 53, 4, 8,  3 }, /* IRDA */
+	{ 54, 4, 8,  3 }, /* IRDA */
+	{ 55, 4, 8,  3 }, /* IRDA */
+
+	{ 56, 4, 4,  3 }, /* SCIF */
+	{ 57, 4, 4,  3 }, /* SCIF */
+	{ 58, 4, 4,  3 }, /* SCIF */
+	{ 59, 4, 4,  3 }, /* SCIF */
 };
 
-void __init init_IRQ_ipr()
+static unsigned long ipr_offsets[] = {
+	0xfffffee2,	/* 0: IPRA */
+	0xfffffee4,	/* 1: IPRB */
+	0xa4000016,	/* 2: IPRC */
+	0xa4000018,	/* 3: IPRD */
+	0xa400001a,	/* 4: IPRE */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7709",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 51760a7..f40e6da 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -49,7 +49,7 @@
 }
 __initcall(sh7710_devices_setup);
 
-static struct ipr_data sh7710_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0,  8, 2 }, /* TMU1 TUNI */
@@ -78,26 +78,30 @@
 };
 
 static unsigned long ipr_offsets[] = {
-	0xA414FEE2	/* 0: IPRA */
-,	0xA414FEE4	/* 1: IPRB */
-,	0xA4140016	/* 2: IPRC */
-,	0xA4140018	/* 3: IPRD */
-,	0xA414001A	/* 4: IPRE */
-,	0xA4080000	/* 5: IPRF */
-,	0xA4080002	/* 6: IPRG */
-,	0xA4080004	/* 7: IPRH */
-,	0xA4080006	/* 8: IPRI */
+	0xA414FEE2,	/* 0: IPRA */
+	0xA414FEE4,	/* 1: IPRB */
+	0xA4140016,	/* 2: IPRC */
+	0xA4140018,	/* 3: IPRD */
+	0xA414001A,	/* 4: IPRE */
+	0xA4080000,	/* 5: IPRF */
+	0xA4080002,	/* 6: IPRG */
+	0xA4080004,	/* 7: IPRH */
+	0xA4080006,	/* 8: IPRI */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
 
-void __init init_IRQ_ipr()
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7710",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 8add10b..dadd6bf 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -10,7 +10,11 @@
 
 # CPU subtype setup
 obj-$(CONFIG_CPU_SUBTYPE_SH7750)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7750R)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7750S)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7091)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751R)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7760)	+= setup-sh7760.o
 obj-$(CONFIG_CPU_SUBTYPE_SH4_202)	+= setup-sh4-202.o
 
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index fab2eb0..66c3f75 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -141,6 +141,14 @@
 			current_cpu_data.flags |= CPU_HAS_LLSC;
 		}
 		break;
+	case 0x4000:	/* 1st cut */
+	case 0x4001:	/* 2nd cut */
+		current_cpu_data.type = CPU_SHX3;
+		current_cpu_data.icache.ways = 4;
+		current_cpu_data.dcache.ways = 4;
+		current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+					  CPU_HAS_LLSC;
+		break;
 	case 0x8000:
 		current_cpu_data.type = CPU_ST40RA;
 		current_cpu_data.flags |= CPU_HAS_FPU;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 03b14cf..da153bc 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -82,7 +82,7 @@
 }
 __initcall(sh7750_devices_setup);
 
-static struct ipr_data sh7750_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0, 12, 2 }, /* TMU1 TUNI */
@@ -106,8 +106,27 @@
 	{ 38, 2,  8, 7 }, /* DMAC DMAE */
 };
 
+static unsigned long ipr_offsets[] = {
+	0xffd00004UL,	/* 0: IPRA */
+	0xffd00008UL,	/* 1: IPRB */
+	0xffd0000cUL,	/* 2: IPRC */
+	0xffd00010UL,	/* 3: IPRD */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7750",
+	},
+};
+
 #ifdef CONFIG_CPU_SUBTYPE_SH7751
-static struct ipr_data sh7751_ipr_map[] = {
+static struct ipr_data ipr_irq_table_sh7751[] = {
 	{ 44, 2,  8, 7 }, /* DMAC DMTE4 */
 	{ 45, 2,  8, 7 }, /* DMAC DMTE5 */
 	{ 46, 2,  8, 7 }, /* DMAC DMTE6 */
@@ -118,21 +137,26 @@
 	/*{ 72, INTPRI00,  8, ? },*/ /* TMU3 TUNI */
 	/*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
 };
+
+static struct ipr_desc ipr_irq_desc_sh7751 = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table_sh7751,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table_sh7751),
+
+	.chip = {
+		.name	= "IPR-sh7751",
+	},
+};
 #endif
 
-static unsigned long ipr_offsets[] = {
-	0xffd00004UL,	/* 0: IPRA */
-	0xffd00008UL,	/* 1: IPRB */
-	0xffd0000cUL,	/* 2: IPRC */
-	0xffd00010UL,	/* 3: IPRD */
-};
-
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
+void __init init_IRQ_ipr(void)
 {
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
+	register_ipr_controller(&ipr_irq_desc);
+#ifdef CONFIG_CPU_SUBTYPE_SH7751
+	register_ipr_controller(&ipr_irq_desc_sh7751);
+#endif
 }
 
 #define INTC_ICR	0xffd00000UL
@@ -143,11 +167,3 @@
 {
 	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 }
-
-void __init init_IRQ_ipr()
-{
-	make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
-#ifdef CONFIG_CPU_SUBTYPE_SH7751
-	make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
-#endif
-}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index b7c7028..3df1697 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -96,7 +96,25 @@
 	{109,12,  0, 4,  0,  3},	/* CMTI */
 };
 
-static struct ipr_data sh7760_ipr_map[] = {
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xfe080000,
+	.msk_base	= 0xfe080040,
+	.mskclr_base	= 0xfe080060,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-sh7760",
+	},
+};
+
+void __init init_IRQ_intc2(void)
+{
+	register_intc2_controller(&intc2_irq_desc);
+}
+
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0,  8, 2 }, /* TMU1 TUNI */
@@ -133,20 +151,19 @@
 	0xffd00010UL,	/* 3: IPRD */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
 
-void __init init_IRQ_intc2(void)
-{
-	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
-}
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
 
-void __init  init_IRQ_ipr(void)
+	.chip = {
+		.name	= "IPR-sh7760",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index ab7422f..4006232 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_CPU_SUBTYPE_SH73180)	+= setup-sh73180.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7722)	+= setup-sh7722.o
+obj-$(CONFIG_CPU_SUBTYPE_SHX3)		+= setup-shx3.o
 
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SUBTYPE_SH73180)	:= clock-sh73180.o
@@ -17,5 +18,6 @@
 clock-$(CONFIG_CPU_SUBTYPE_SH7785)	:= clock-sh7785.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SHX3)	:= clock-shx3.o
 
 obj-y	+= $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
new file mode 100644
index 0000000..c630b29
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
@@ -0,0 +1,135 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-shx3.c
+ *
+ * SH-X3 support for the clock framework
+ *
+ *  Copyright (C) 2006-2007  Renesas Technology Corp.
+ *  Copyright (C) 2006-2007  Renesas Solutions Corp.
+ *  Copyright (C) 2006-2007  Paul Mundt
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 1, 2, 4 ,6 };
+static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
+static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
+static int cfc_divisors[] = { 1, 1, 4, 6 };
+
+#define IFC_POS		28
+#define IFC_MSK		0x0003
+#define BFC_MSK		0x000f
+#define PFC_MSK		0x000f
+#define CFC_MSK		0x0003
+#define BFC_POS		16
+#define PFC_POS		0
+#define CFC_POS		20
+
+static void master_clk_init(struct clk *clk)
+{
+	clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK];
+}
+
+static struct clk_ops shx3_master_clk_ops = {
+	.init		= master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
+	clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops shx3_module_clk_ops = {
+	.recalc		= module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
+	clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops shx3_bus_clk_ops = {
+	.recalc		= bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
+	clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops shx3_cpu_clk_ops = {
+	.recalc		= cpu_clk_recalc,
+};
+
+static struct clk_ops *shx3_clk_ops[] = {
+	&shx3_master_clk_ops,
+	&shx3_module_clk_ops,
+	&shx3_bus_clk_ops,
+	&shx3_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+	if (idx < ARRAY_SIZE(shx3_clk_ops))
+		*ops = shx3_clk_ops[idx];
+}
+
+static void shyway_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
+	clk->rate = clk->parent->rate / cfc_divisors[idx];
+}
+
+static struct clk_ops shx3_shyway_clk_ops = {
+	.recalc		= shyway_clk_recalc,
+};
+
+static struct clk shx3_shyway_clk = {
+	.name		= "shyway_clk",
+	.flags		= CLK_ALWAYS_ENABLED,
+	.ops		= &shx3_shyway_clk_ops,
+};
+
+/*
+ * Additional SHx3-specific on-chip clocks that aren't already part of the
+ * clock framework
+ */
+static struct clk *shx3_onchip_clocks[] = {
+	&shx3_shyway_clk,
+};
+
+static int __init shx3_clk_init(void)
+{
+	struct clk *clk = clk_get(NULL, "master_clk");
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
+		struct clk *clkp = shx3_onchip_clocks[i];
+
+		clkp->parent = clk;
+		clk_register(clkp);
+		clk_enable(clkp);
+	}
+
+	/*
+	 * Now that we have the rest of the clocks registered, we need to
+	 * force the parent clock to propagate so that these clocks will
+	 * automatically figure out their rate. We cheat by handing the
+	 * parent clock its current rate and forcing child propagation.
+	 */
+	clk_set_rate(clk, clk_get_rate(clk));
+
+	clk_put(clk);
+
+	return 0;
+}
+arch_initcall(shx3_clk_init);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 1143fbf..a3e159e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -1,7 +1,7 @@
 /*
  * SH7722 Setup
  *
- *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2006 - 2007  Paul Mundt
  *
  * 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
@@ -10,6 +10,8 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/serial.h>
+#include <linux/mm.h>
+#include <asm/mmzone.h>
 #include <asm/sci.h>
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -42,7 +44,7 @@
 }
 __initcall(sh7722_devices_setup);
 
-static struct ipr_data sh7722_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, prio */
 	{ 16, 0, 12, 2 }, /* TMU0 */
 	{ 17, 0,  8, 2 }, /* TMU1 */
@@ -67,14 +69,25 @@
 	0xa408002c, /* 11: IPRL */
 };
 
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7722",
+	},
+};
 
 void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
+}
+
+void __init plat_mem_setup(void)
+{
+	/* Register the URAM space as Node 1 */
+	setup_bootmem_node(1, 0x055f0000, 0x05610000);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 9aeaa2d..b57c760 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -102,7 +102,20 @@
 	{ 68, 0x14,  8, 0, 18, 2 },	/* PCIC4 */
 };
 
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xffd40000,
+	.msk_base	= 0xffd40038,
+	.mskclr_base	= 0xffd4003c,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-sh7780",
+	},
+};
+
 void __init init_IRQ_intc2(void)
 {
-	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+	register_intc2_controller(&intc2_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 07b0de8..ce10ec5 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -97,7 +97,21 @@
 	{ 60, 12, 16, 0, 7, 3 },	/* SCIF5 ERI, RXI, BRI, TXI */
 };
 
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xffd40000,
+	.msk_base	= 0xffd40038,
+	.mskclr_base	= 0xffd4003c,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-sh7785",
+	},
+};
+
 void __init init_IRQ_intc2(void)
 {
-	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+	register_intc2_controller(&intc2_irq_desc);
 }
+
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
new file mode 100644
index 0000000..70683ea
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -0,0 +1,85 @@
+/*
+ * SH-X3 Setup
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/io.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+	{
+		.mapbase	= 0xffc30000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 40, 41, 43, 42 },
+	}, {
+		.mapbase	= 0xffc40000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 44, 45, 47, 46 },
+	}, {
+		.mapbase	= 0xffc50000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 48, 49, 51, 50 },
+	}, {
+		.mapbase	= 0xffc60000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 52, 53, 55, 54 },
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct platform_device sci_device = {
+	.name		= "sh-sci",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= sci_platform_data,
+	},
+};
+
+static struct platform_device *shx3_devices[] __initdata = {
+	&sci_device,
+};
+
+static int __init shx3_devices_setup(void)
+{
+	return platform_add_devices(shx3_devices,
+				    ARRAY_SIZE(shx3_devices));
+}
+__initcall(shx3_devices_setup);
+
+static struct intc2_data intc2_irq_table[] = {
+	{ 16, 0, 0, 0, 1, 2 },		/* TMU0 */
+	{ 40, 4, 0, 0x20, 0, 3 },	/* SCIF0 ERI */
+	{ 41, 4, 0, 0x20, 1, 3 },	/* SCIF0 RXI */
+	{ 42, 4, 0, 0x20, 2, 3 },	/* SCIF0 BRI */
+	{ 43, 4, 0, 0x20, 3, 3 },	/* SCIF0 TXI */
+};
+
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xfe410000,
+	.msk_base	= 0xfe410820,
+	.mskclr_base	= 0xfe410850,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-SHX3",
+	},
+};
+
+void __init init_IRQ_intc2(void)
+{
+	register_intc2_controller(&intc2_irq_desc);
+}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 27b923c..2789779 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -158,15 +158,11 @@
 }
 
 #ifdef CONFIG_4KSTACKS
-/*
- * These should really be __section__(".bss.page_aligned") as well, but
- * gcc's 3.0 and earlier don't handle that correctly.
- */
 static char softirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__aligned__(THREAD_SIZE)));
+		__attribute__((__section__(".bss.page_aligned")));
 
 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__aligned__(THREAD_SIZE)));
+		__attribute__((__section__(".bss.page_aligned")));
 
 /*
  * allocate per-cpu stacks for hardirq and for softirq processing
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c
new file mode 100644
index 0000000..23c5948
--- /dev/null
+++ b/arch/sh/kernel/machvec.c
@@ -0,0 +1,130 @@
+/*
+ * arch/sh/kernel/machvec.c
+ *
+ * The SuperH machine vector setup handlers, yanked from setup.c
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *  Copyright (C) 2002 - 2007 Paul Mundt
+ *
+ * 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/init.h>
+#include <linux/string.h>
+#include <asm/machvec.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define MV_NAME_SIZE 32
+
+#define for_each_mv(mv) \
+	for ((mv) = (struct sh_machine_vector *)&__machvec_start; \
+	     (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \
+	     (mv)++)
+
+static struct sh_machine_vector * __init get_mv_byname(const char *name)
+{
+	struct sh_machine_vector *mv;
+
+	for_each_mv(mv)
+		if (strcasecmp(name, mv->mv_name) == 0)
+			return mv;
+
+	return NULL;
+}
+
+static unsigned int __initdata machvec_selected;
+
+static int __init early_parse_mv(char *from)
+{
+	char mv_name[MV_NAME_SIZE] = "";
+	char *mv_end;
+	char *mv_comma;
+	int mv_len;
+	struct sh_machine_vector *mvp;
+
+	mv_end = strchr(from, ' ');
+	if (mv_end == NULL)
+		mv_end = from + strlen(from);
+
+	mv_comma = strchr(from, ',');
+	mv_len = mv_end - from;
+	if (mv_len > (MV_NAME_SIZE-1))
+		mv_len = MV_NAME_SIZE-1;
+	memcpy(mv_name, from, mv_len);
+	mv_name[mv_len] = '\0';
+	from = mv_end;
+
+	machvec_selected = 1;
+
+	/* Boot with the generic vector */
+	if (strcmp(mv_name, "generic") == 0)
+		return 0;
+
+	mvp = get_mv_byname(mv_name);
+	if (unlikely(!mvp)) {
+		printk("Available vectors:\n\n\t'%s', ", sh_mv.mv_name);
+		for_each_mv(mvp)
+			printk("'%s', ", mvp->mv_name);
+		printk("\n\n");
+		panic("Failed to select machvec '%s' -- halting.\n",
+		      mv_name);
+	} else
+		sh_mv = *mvp;
+
+	return 0;
+}
+early_param("sh_mv", early_parse_mv);
+
+void __init sh_mv_setup(void)
+{
+	/*
+	 * Only overload the machvec if one hasn't been selected on
+	 * the command line with sh_mv=
+	 */
+	if (!machvec_selected) {
+		unsigned long machvec_size;
+
+		machvec_size = ((unsigned long)&__machvec_end -
+				(unsigned long)&__machvec_start);
+
+		/*
+		 * If the machvec hasn't been preselected, use the first
+		 * vector (usually the only one) from .machvec.init.
+		 */
+		if (machvec_size >= sizeof(struct sh_machine_vector))
+			sh_mv = *(struct sh_machine_vector *)&__machvec_start;
+	}
+
+	printk(KERN_NOTICE "Booting machvec: %s\n", get_system_type());
+
+	/*
+	 * Manually walk the vec, fill in anything that the board hasn't yet
+	 * by hand, wrapping to the generic implementation.
+	 */
+#define mv_set(elem) do { \
+	if (!sh_mv.mv_##elem) \
+		sh_mv.mv_##elem = generic_##elem; \
+} while (0)
+
+	mv_set(inb);	mv_set(inw);	mv_set(inl);
+	mv_set(outb);	mv_set(outw);	mv_set(outl);
+
+	mv_set(inb_p);	mv_set(inw_p);	mv_set(inl_p);
+	mv_set(outb_p);	mv_set(outw_p);	mv_set(outl_p);
+
+	mv_set(insb);	mv_set(insw);	mv_set(insl);
+	mv_set(outsb);	mv_set(outsw);	mv_set(outsl);
+
+	mv_set(readb);	mv_set(readw);	mv_set(readl);
+	mv_set(writeb);	mv_set(writew);	mv_set(writel);
+
+	mv_set(ioport_map);
+	mv_set(ioport_unmap);
+	mv_set(irq_demux);
+
+	if (!sh_mv.mv_nr_irqs)
+		sh_mv.mv_nr_irqs = NR_IRQS;
+}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index a11e2aa..6334a4c 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -17,6 +17,7 @@
 #include <linux/kexec.h>
 #include <linux/kdebug.h>
 #include <linux/tick.h>
+#include <linux/reboot.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
@@ -319,9 +320,7 @@
 	ctrl_outl(pc, UBC_BARA);
 
 #ifdef CONFIG_MMU
-	/* We don't have any ASID settings for the SH-2! */
-	if (current_cpu_data.type != CPU_SH7604)
-		ctrl_outb(asid, UBC_BASRA);
+	ctrl_outb(asid, UBC_BASRA);
 #endif
 
 	ctrl_outl(0, UBC_BAMRA);
@@ -405,8 +404,8 @@
 			unsigned long r6, unsigned long r7,
 			struct pt_regs __regs)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 #ifdef CONFIG_MMU
+	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
 #else
 	/* fork almost works, enough to trick you into looking elsewhere :-( */
@@ -449,23 +448,20 @@
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *ufilename, char **uargv,
-			  char **uenvp, unsigned long r7,
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
+			  char __user * __user *uenvp, unsigned long r7,
 			  struct pt_regs __regs)
 {
 	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	int error;
 	char *filename;
 
-	filename = getname((char __user *)ufilename);
+	filename = getname(ufilename);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
 
-	error = do_execve(filename,
-			  (char __user * __user *)uargv,
-			  (char __user * __user *)uenvp,
-			  regs);
+	error = do_execve(filename, uargv, uenvp, regs);
 	if (error == 0) {
 		task_lock(current);
 		current->ptrace &= ~PT_DTRACE;
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 3fb5fc0..891d1d4 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -91,17 +91,8 @@
 	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 *) data);
-		break;
-	}
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -128,17 +119,14 @@
 			tmp = !!tsk_used_math(child);
 		else
 			tmp = 0;
-		ret = put_user(tmp, (unsigned long *)data);
+		ret = put_user(tmp, (unsigned long __user *)data);
 		break;
 	}
 
 	/* when 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;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -196,7 +184,7 @@
 
 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
 		long pc;
-		struct pt_regs *dummy = NULL;
+		struct pt_regs *regs = NULL;
 
 		ret = -EIO;
 		if (!valid_signal(data))
@@ -207,7 +195,7 @@
 			child->ptrace |= PT_DTRACE;
 		}
 
-		pc = get_stack_long(child, (long)&dummy->pc);
+		pc = get_stack_long(child, (long)&regs->pc);
 
 		/* Next scheduling will set up UBC */
 		if (child->thread.ubc_pc == 0)
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index c277291..de8e6e2 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -23,6 +23,7 @@
 #include <linux/kexec.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/page.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
@@ -41,20 +42,19 @@
  * The bigger value means no problem.
  */
 struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
+
+/*
+ * The machine vector. First entry in .machvec.init, or clobbered by
+ * sh_mv= on the command line, prior to .machvec.init teardown.
+ */
+struct sh_machine_vector sh_mv = { .mv_name = "generic", };
+
 #ifdef CONFIG_VT
 struct screen_info screen_info;
 #endif
 
-#if defined(CONFIG_SH_UNKNOWN)
-struct sh_machine_vector sh_mv;
-#endif
-
 extern int root_mountflags;
 
-#define MV_NAME_SIZE 32
-
-static struct sh_machine_vector* __init get_mv_byname(const char* name);
-
 /*
  * This is set up by the setup-routine at boot-time
  */
@@ -80,131 +80,17 @@
 
 unsigned long memory_start, memory_end;
 
-static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
-				  struct sh_machine_vector** mvp,
-				  unsigned long *mv_io_base)
+static int __init early_parse_mem(char *p)
 {
-	char c = ' ', *to = command_line, *from = COMMAND_LINE;
-	int len = 0;
-
-	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	unsigned long size;
 
 	memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
-	memory_end = memory_start + __MEMORY_SIZE;
-
-	for (;;) {
-		/*
-		 * "mem=XXX[kKmM]" defines a size of memory.
-		 */
-		if (c == ' ' && !memcmp(from, "mem=", 4)) {
-			if (to != command_line)
-				to--;
-			{
-				unsigned long mem_size;
-
-				mem_size = memparse(from+4, &from);
-				memory_end = memory_start + mem_size;
-			}
-		}
-
-		if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
-			char* mv_end;
-			char* mv_comma;
-			int mv_len;
-			if (to != command_line)
-				to--;
-			from += 6;
-			mv_end = strchr(from, ' ');
-			if (mv_end == NULL)
-				mv_end = from + strlen(from);
-
-			mv_comma = strchr(from, ',');
-			if ((mv_comma != NULL) && (mv_comma < mv_end)) {
-				int ints[3];
-				get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
-				*mv_io_base = ints[1];
-				mv_len = mv_comma - from;
-			} else {
-				mv_len = mv_end - from;
-			}
-			if (mv_len > (MV_NAME_SIZE-1))
-				mv_len = MV_NAME_SIZE-1;
-			memcpy(mv_name, from, mv_len);
-			mv_name[mv_len] = '\0';
-			from = mv_end;
-
-			*mvp = get_mv_byname(mv_name);
-		}
-
-		c = *(from++);
-		if (!c)
-			break;
-		if (COMMAND_LINE_SIZE <= ++len)
-			break;
-		*(to++) = c;
-	}
-	*to = '\0';
-	*cmdline_p = command_line;
-}
-
-static int __init sh_mv_setup(char **cmdline_p)
-{
-#ifdef CONFIG_SH_UNKNOWN
-	extern struct sh_machine_vector mv_unknown;
-#endif
-	struct sh_machine_vector *mv = NULL;
-	char mv_name[MV_NAME_SIZE] = "";
-	unsigned long mv_io_base = 0;
-
-	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
-
-#ifdef CONFIG_SH_UNKNOWN
-	if (mv == NULL) {
-		mv = &mv_unknown;
-		if (*mv_name != '\0') {
-			printk("Warning: Unsupported machine %s, using unknown\n",
-			       mv_name);
-		}
-	}
-	sh_mv = *mv;
-#endif
-
-	/*
-	 * Manually walk the vec, fill in anything that the board hasn't yet
-	 * by hand, wrapping to the generic implementation.
-	 */
-#define mv_set(elem) do { \
-	if (!sh_mv.mv_##elem) \
-		sh_mv.mv_##elem = generic_##elem; \
-} while (0)
-
-	mv_set(inb);	mv_set(inw);	mv_set(inl);
-	mv_set(outb);	mv_set(outw);	mv_set(outl);
-
-	mv_set(inb_p);	mv_set(inw_p);	mv_set(inl_p);
-	mv_set(outb_p);	mv_set(outw_p);	mv_set(outl_p);
-
-	mv_set(insb);	mv_set(insw);	mv_set(insl);
-	mv_set(outsb);	mv_set(outsw);	mv_set(outsl);
-
-	mv_set(readb);	mv_set(readw);	mv_set(readl);
-	mv_set(writeb);	mv_set(writew);	mv_set(writel);
-
-	mv_set(ioport_map);
-	mv_set(ioport_unmap);
-	mv_set(irq_demux);
-
-#ifdef CONFIG_SH_UNKNOWN
-	__set_io_port_base(mv_io_base);
-#endif
-
-	if (!sh_mv.mv_nr_irqs)
-		sh_mv.mv_nr_irqs = NR_IRQS;
+	size = memparse(p, &p);
+	memory_end = memory_start + size;
 
 	return 0;
 }
+early_param("mem", early_parse_mem);
 
 /*
  * Register fully available low RAM pages with the bootmem allocator.
@@ -230,7 +116,7 @@
 	free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
 }
 
-void __init setup_bootmem_allocator(unsigned long start_pfn)
+void __init setup_bootmem_allocator(unsigned long free_pfn)
 {
 	unsigned long bootmap_size;
 
@@ -239,9 +125,10 @@
 	 * bootstrap step all allocations (until the page allocator
 	 * is intact) must be done via bootmem_alloc().
 	 */
-	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
+	bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
 					 min_low_pfn, max_low_pfn);
 
+	add_active_range(0, min_low_pfn, max_low_pfn);
 	register_bootmem_low_pages();
 
 	node_set_online(0);
@@ -254,7 +141,7 @@
 	 * an invalid RAM area.
 	 */
 	reserve_bootmem(__MEMORY_START+PAGE_SIZE,
-		(PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
+		(PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
 
 	/*
 	 * reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -262,6 +149,8 @@
 	 */
 	reserve_bootmem(__MEMORY_START, PAGE_SIZE);
 
+	sparse_memory_present_with_active_regions(0);
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
 	if (&__rd_start != &__rd_end) {
@@ -315,10 +204,6 @@
 {
 	enable_mmu();
 
-#ifdef CONFIG_CMDLINE_BOOL
-	strcpy(COMMAND_LINE, CONFIG_CMDLINE);
-#endif
-
 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
 
 #ifdef CONFIG_BLK_DEV_RAM
@@ -339,9 +224,22 @@
 	data_resource.start = virt_to_phys(_etext);
 	data_resource.end = virt_to_phys(_edata)-1;
 
+	memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
+	memory_end = memory_start + __MEMORY_SIZE;
+
+#ifdef CONFIG_CMDLINE_BOOL
+	strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line));
+#else
+	strlcpy(command_line, COMMAND_LINE, sizeof(command_line));
+#endif
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = command_line;
+
 	parse_early_param();
 
-	sh_mv_setup(cmdline_p);
+	sh_mv_setup();
 
 	/*
 	 * Find the highest page frame number we have available
@@ -355,8 +253,9 @@
 	min_low_pfn = __MEMORY_START >> PAGE_SHIFT;
 
 	nodes_clear(node_online_map);
+
+	/* Setup bootmem with available RAM */
 	setup_memory();
-	paging_init();
 	sparse_init();
 
 #ifdef CONFIG_DUMMY_CONSOLE
@@ -366,46 +265,13 @@
 	/* Perform the machine specific initialisation */
 	if (likely(sh_mv.mv_setup))
 		sh_mv.mv_setup(cmdline_p);
+
+	paging_init();
 }
 
-struct sh_machine_vector* __init get_mv_byname(const char* name)
-{
-	extern long __machvec_start, __machvec_end;
-	struct sh_machine_vector *all_vecs =
-		(struct sh_machine_vector *)&__machvec_start;
-
-	int i, n = ((unsigned long)&__machvec_end
-		    - (unsigned long)&__machvec_start)/
-		sizeof(struct sh_machine_vector);
-
-	for (i = 0; i < n; ++i) {
-		struct sh_machine_vector *mv = &all_vecs[i];
-		if (mv == NULL)
-			continue;
-		if (strcasecmp(name, get_system_type()) == 0) {
-			return mv;
-		}
-	}
-	return NULL;
-}
-
-static struct cpu cpu[NR_CPUS];
-
-static int __init topology_init(void)
-{
-	int cpu_id;
-
-	for_each_possible_cpu(cpu_id)
-		register_cpu(&cpu[cpu_id], cpu_id);
-
-	return 0;
-}
-
-subsys_initcall(topology_init);
-
 static const char *cpu_name[] = {
 	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
-	[CPU_SH7604]	= "SH7604",	[CPU_SH7300]	= "SH7300",
+	[CPU_SH7300]	= "SH7300",
 	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
 	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
 	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
@@ -419,7 +285,7 @@
 	[CPU_SH7770]	= "SH7770",	[CPU_SH7780]	= "SH7780",
 	[CPU_SH7781]	= "SH7781",	[CPU_SH7343]	= "SH7343",
 	[CPU_SH7785]	= "SH7785",	[CPU_SH7722]	= "SH7722",
-	[CPU_SH_NONE]	= "Unknown"
+	[CPU_SHX3]	= "SH-X3",	[CPU_SH_NONE]	= "Unknown"
 };
 
 const char *get_cpu_subtype(struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index c1cfcb9..c968dcf 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -78,6 +78,16 @@
 DECLARE_EXPORT(__movmem_i4_even);
 DECLARE_EXPORT(__movmem_i4_odd);
 DECLARE_EXPORT(__movmemSI12_i4);
+
+#if (__GNUC_MINOR__ == 2 || defined(__GNUC_STM_RELEASE__))
+/*
+ * GCC 4.2 emits these for division, as do GCC 4.1.x versions of the ST
+ * compiler which include backported patches.
+ */
+DECLARE_EXPORT(__sdivsi3_i4i);
+DECLARE_EXPORT(__udiv_qrnnd_16);
+DECLARE_EXPORT(__udivsi3_i4i);
+#endif
 #else /* GCC 3.x */
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index e323e29..706d81c 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -23,6 +23,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
+#include <linux/io.h>
 #include <asm/system.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -261,7 +262,7 @@
 		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs->regs[15]);
+	do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame);
 
 	return r0;
 
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index 7db1c2d..ff5656e 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -308,9 +308,9 @@
 	.long sys_utimes
  	.long sys_fadvise64_64_wrapper
 	.long sys_ni_syscall	/* Reserved for vserver */
-	.long sys_ni_syscall	/* Reserved for mbind */
-	.long sys_ni_syscall	/* 275 - get_mempolicy */
-	.long sys_ni_syscall	/* set_mempolicy */
+	.long sys_mbind
+	.long sys_get_mempolicy		/* 275 */
+	.long sys_set_mempolicy
 	.long sys_mq_open
 	.long sys_mq_unlink
 	.long sys_mq_timedsend
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 2d997e2..097ebd4 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -30,7 +30,7 @@
 
 static int tmu_timer_start(void)
 {
-	ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
+	ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR);
 	return 0;
 }
 
@@ -52,7 +52,7 @@
 
 static int tmu_timer_stop(void)
 {
-	ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
+	ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR);
 	return 0;
 }
 
@@ -174,7 +174,8 @@
 
 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7785)
+    !defined(CONFIG_CPU_SUBTYPE_SH7785) && \
+    !defined(CONFIG_CPU_SUBTYPE_SHX3)
 	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
 #endif
 
diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c
new file mode 100644
index 0000000..9b5844a
--- /dev/null
+++ b/arch/sh/kernel/topology.c
@@ -0,0 +1,49 @@
+/*
+ * arch/sh/kernel/topology.c
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * 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/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+	int i, ret;
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+	for_each_online_node(i)
+		register_one_node(i);
+#endif
+
+	for_each_present_cpu(i) {
+		ret = register_cpu(&per_cpu(cpu_devices, i), i);
+		if (unlikely(ret))
+			printk(KERN_WARNING "%s: register_cpu %d failed (%d)\n",
+			       __FUNCTION__, i, ret);
+	}
+
+#if defined(CONFIG_NUMA) && !defined(CONFIG_SMP)
+	/*
+	 * In the UP case, make sure the CPU association is still
+	 * registered under each node. Without this, sysfs fails
+	 * to make the connection between nodes other than node0
+	 * and cpu0.
+	 */
+	for_each_online_node(i)
+		if (i != numa_node_id())
+			register_cpu_under_node(raw_smp_processor_id(), i);
+#endif
+
+	return 0;
+}
+subsys_initcall(topology_init);
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 8f18930..502d43e 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -103,6 +103,7 @@
 			 (unsigned long)task_stack_page(current));
 
 	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (kexec_should_crash(current))
@@ -584,7 +585,7 @@
 		info.si_signo = SIGBUS;
 		info.si_errno = 0;
 		info.si_code = si_code;
-		info.si_addr = (void *) address;
+		info.si_addr = (void __user *)address;
 		force_sig_info(SIGBUS, &info, current);
 	} else {
 		if (regs->pc & 1)
@@ -617,7 +618,7 @@
  */
 int is_dsp_inst(struct pt_regs *regs)
 {
-	unsigned short inst;
+	unsigned short inst = 0;
 
 	/*
 	 * Safe guard if DSP mode is already enabled or we're lacking
@@ -645,7 +646,6 @@
 				unsigned long r6, unsigned long r7,
 				struct pt_regs __regs)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	siginfo_t info;
 
 	switch (r4) {
@@ -874,7 +874,7 @@
 void handle_BUG(struct pt_regs *regs)
 {
 	enum bug_trap_type tt;
-	tt = report_bug(regs->pc);
+	tt = report_bug(regs->pc, regs);
 	if (tt == BUG_TRAP_TYPE_WARN) {
 		regs->pc += 2;
 		return;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 4c5b57e..0696402 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -97,18 +97,20 @@
   __initramfs_end = .;
 #endif
 
+ . = ALIGN(4);
   __machvec_start = .;
-  .init.machvec : { *(.init.machvec) }
+  .machvec.init : { *(.machvec.init) }
   __machvec_end = .;
+
   . = ALIGN(PAGE_SIZE);
-  __init_end = .;
-
-  . = ALIGN(4);
-  __bss_start = .;		/* BSS */
-  .bss : { *(.bss) }
-
-  . = ALIGN(4);
-  _end = . ;
+  .bss : {
+	__init_end = .;
+	__bss_start = .;		/* BSS */
+  	*(.bss.page_aligned)
+  	*(.bss)
+	. = ALIGN(4);
+	_end = . ;
+  }
 
   /* When something in the kernel is NOT compiled as a module, the
    * module cleanup code and data are put into these segments.  Both
diff --git a/arch/sh/lib/div64-generic.c b/arch/sh/lib/div64-generic.c
index c02473a..4bef3b5 100644
--- a/arch/sh/lib/div64-generic.c
+++ b/arch/sh/lib/div64-generic.c
@@ -4,16 +4,15 @@
 
 #include <linux/types.h>
 
-extern u64 __xdiv64_32(u64 n, u32 d);
+extern uint64_t __xdiv64_32(u64 n, u32 d);
 
-u64 __div64_32(u64 *xp, u32 y)
+uint32_t __div64_32(u64 *xp, u32 y)
 {
-	u64 rem;
-	u64 q = __xdiv64_32(*xp, y);
+	uint32_t rem;
+	uint64_t q = __xdiv64_32(*xp, y);
 
 	rem = *xp - q * y;
 	*xp = q;
 
 	return rem;
 }
-
diff --git a/arch/sh/lib/div64.S b/arch/sh/lib/div64.S
index eefc275..5ee7334 100644
--- a/arch/sh/lib/div64.S
+++ b/arch/sh/lib/div64.S
@@ -1,12 +1,12 @@
 /*	
- * unsigned long long __xdiv64_32(unsigned long long n, unsigned long d); 
+ * unsigned long __xdiv64_32(unsigned long long n, unsigned long d); 
  */
 
 #include <linux/linkage.h>
 
 .text
 ENTRY(__xdiv64_32)
-#ifdef  __LITTLE_ENDIAN__
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
 	mov	r4, r0
 	mov	r5, r1
 #else
@@ -34,7 +34,7 @@
 	rotcl	r0
 	div1	r6, r1
 	.endr
-#ifdef  __LITTLE_ENDIAN__
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
 	mov	r2, r1
 	rts
 	 rotcl	r0
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index a38e1ee..ac2d7ab 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -507,6 +507,7 @@
 	unsigned short insn = *(unsigned short *)regs->pc;
 	unsigned short finsn;
 	unsigned long nextpc;
+	siginfo_t info;
 	int nib[4] = {
 		(insn >> 12) & 0xf,
 		(insn >> 8) & 0xf,
@@ -559,9 +560,11 @@
 				~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
 			set_tsk_thread_flag(tsk, TIF_USEDFPU);
 		} else {
-			tsk->thread.trap_no = 11;
-			tsk->thread.error_code = 0;
-			force_sig(SIGFPE, tsk);
+			info.si_signo = SIGFPE;
+			info.si_errno = 0;
+			info.si_code = FPE_FLTINV;
+			info.si_addr = (void __user *)regs->pc;
+			force_sig_info(SIGFPE, &info, tsk);
 		}
 
 		regs->pc = nextpc;
@@ -576,14 +579,17 @@
 			     struct pt_regs regs)
 {
 	struct task_struct *tsk = current;
+	siginfo_t info;
 
 	if (ieee_fpe_handler (&regs))
 		return;
 
 	regs.pc += 2;
-	tsk->thread.trap_no = 11;
-	tsk->thread.error_code = 0;
-	force_sig(SIGFPE, tsk);
+	info.si_signo = SIGFPE;
+	info.si_errno = 0;
+	info.si_code = FPE_FLTINV;
+	info.si_addr = (void __user *)regs.pc;
+	force_sig_info(SIGFPE, &info, tsk);
 }
 
 /**
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 253346d..28d79a4 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -1,5 +1,3 @@
-menu "Processor selection"
-
 #
 # Processor families
 #
@@ -38,27 +36,31 @@
 config CPU_SHX2
 	bool
 
+config CPU_SHX3
+	bool
+
+choice
+	prompt "Processor sub-type selection"
+
 #
 # Processor subtypes
 #
 
-comment "SH-2 Processor Support"
-
-config CPU_SUBTYPE_SH7604
-	bool "Support SH7604 processor"
-	select CPU_SH2
+# SH-2 Processor Support
 
 config CPU_SUBTYPE_SH7619
 	bool "Support SH7619 processor"
 	select CPU_SH2
+	select CPU_HAS_IPR_IRQ
 
-comment "SH-2A Processor Support"
+# SH-2A Processor Support
 
 config CPU_SUBTYPE_SH7206
 	bool "Support SH7206 processor"
 	select CPU_SH2A
+	select CPU_HAS_IPR_IRQ
 
-comment "SH-3 Processor Support"
+# SH-3 Processor Support
 
 config CPU_SUBTYPE_SH7300
 	bool "Support SH7300 processor"
@@ -113,7 +115,7 @@
 	help
 	  Select SH7712 if you have a SH3-DSP SH7712 CPU.
 
-comment "SH-4 Processor Support"
+# SH-4 Processor Support
 
 config CPU_SUBTYPE_SH7750
 	bool "Support SH7750 processor"
@@ -125,7 +127,7 @@
 config CPU_SUBTYPE_SH7091
 	bool "Support SH7091 processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7750
+	select CPU_HAS_IPR_IRQ
 	help
 	  Select SH7091 if you have an SH-4 based Sega device (such as
 	  the Dreamcast, Naomi, and Naomi 2).
@@ -133,13 +135,11 @@
 config CPU_SUBTYPE_SH7750R
 	bool "Support SH7750R processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7750
 	select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7750S
 	bool "Support SH7750S processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7750
 	select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7751
@@ -153,7 +153,6 @@
 config CPU_SUBTYPE_SH7751R
 	bool "Support SH7751R processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7751
 	select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7760
@@ -166,7 +165,7 @@
 	bool "Support SH4-202 processor"
 	select CPU_SH4
 
-comment "ST40 Processor Support"
+# ST40 Processor Support
 
 config CPU_SUBTYPE_ST40STB1
 	bool "Support ST40STB1/ST40RA processors"
@@ -181,7 +180,7 @@
 	help
 	  Select ST40GX1 if you have a ST40GX1 CPU.
 
-comment "SH-4A Processor Support"
+# SH-4A Processor Support
 
 config CPU_SUBTYPE_SH7770
 	bool "Support SH7770 processor"
@@ -198,7 +197,13 @@
 	select CPU_SHX2
 	select CPU_HAS_INTC2_IRQ
 
-comment "SH4AL-DSP Processor Support"
+config CPU_SUBTYPE_SHX3
+	bool "Support SH-X3 processor"
+	select CPU_SH4A
+	select CPU_SHX3
+	select CPU_HAS_INTC2_IRQ
+
+# SH4AL-DSP Processor Support
 
 config CPU_SUBTYPE_SH73180
 	bool "Support SH73180 processor"
@@ -213,8 +218,10 @@
 	select CPU_SH4AL_DSP
 	select CPU_SHX2
 	select CPU_HAS_IPR_IRQ
+	select ARCH_SPARSEMEM_ENABLE
+	select SYS_SUPPORTS_NUMA
 
-endmenu
+endchoice
 
 menu "Memory management options"
 
@@ -266,7 +273,7 @@
 
 config 32BIT
 	bool "Support 32-bit physical addressing through PMB"
-	depends on CPU_SH4A && MMU && (!X2TLB || BROKEN)
+	depends on MMU && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
 	default y
 	help
 	  If you say Y here, physical addressing will be extended to
@@ -295,6 +302,17 @@
 	  For systems with an MMU that can afford to give up a page,
 	  (the default value) say Y.
 
+config NUMA
+	bool "Non Uniform Memory Access (NUMA) Support"
+	depends on MMU && SYS_SUPPORTS_NUMA && EXPERIMENTAL
+	default n
+	help
+	  Some SH systems have many various memories scattered around
+	  the address space, each with varying latencies. This enables
+	  support for these blocks by binding them to nodes and allowing
+	  memory policies to be used for prioritizing and controlling
+	  allocation behaviour.
+
 config NODES_SHIFT
 	int
 	default "1"
@@ -302,14 +320,34 @@
 
 config ARCH_FLATMEM_ENABLE
 	def_bool y
+	depends on !NUMA
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	select SPARSEMEM_STATIC
+
+config ARCH_SPARSEMEM_DEFAULT
+	def_bool y
 
 config MAX_ACTIVE_REGIONS
 	int
+	default "2" if (CPU_SUBTYPE_SH7722 && SPARSEMEM)
 	default "1"
 
 config ARCH_POPULATES_NODE_MAP
 	def_bool y
 
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
+
+config ARCH_ENABLE_MEMORY_HOTPLUG
+	def_bool y
+	depends on SPARSEMEM
+
+config ARCH_MEMORY_PROBE
+	def_bool y
+	depends on MEMORY_HOTPLUG
+
 choice
 	prompt "Kernel page size"
 	default PAGE_SIZE_4KB
@@ -394,15 +432,4 @@
 
 	  If unsure, say N.
 
-config SH_OCRAM
-	bool "Operand Cache RAM (OCRAM) support"
-	help
-	  Selecting this option will automatically tear down the number of
-	  sets in the dcache by half, which in turn exposes a memory range.
-
-	  The addresses for the OC RAM base will vary according to the
-	  processor version. Consult vendor documentation for specifics.
-
-	  If unsure, say N.
-
 endmenu
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 3ffd7f6..d677d7f 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -8,9 +8,6 @@
 obj-$(CONFIG_CPU_SH3)	+= cache-sh3.o
 obj-$(CONFIG_CPU_SH4)	+= cache-sh4.o
 
-obj-$(CONFIG_DMA_PAGE_OPS)	+= pg-dma.o
-obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
-
 mmu-y			:= fault-nommu.o tlb-nommu.o pg-nommu.o
 mmu-$(CONFIG_MMU)	:= fault.o clear_page.o copy_page.o tlb-flush.o	\
 			   ioremap.o
@@ -27,5 +24,7 @@
 obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
 endif
 
+obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 obj-$(CONFIG_SH7705_CACHE_32KB)	+= cache-sh7705.o
 obj-$(CONFIG_32BIT)		+= pmb.o
+obj-$(CONFIG_NUMA)		+= numa.o
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index c878faa..0b3eaf6 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -32,7 +32,6 @@
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
-	unsigned long page;
 	int si_code;
 	siginfo_t info;
 
@@ -170,24 +169,38 @@
  * terminate things with extreme prejudice.
  *
  */
-	if (address < PAGE_SIZE)
-		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-	else
-		printk(KERN_ALERT "Unable to handle kernel paging request");
-	printk(" at virtual address %08lx\n", address);
-	printk(KERN_ALERT "pc = %08lx\n", regs->pc);
-	page = (unsigned long)get_TTB();
-	if (page) {
-		page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
-		printk(KERN_ALERT "*pde = %08lx\n", page);
-		if (page & _PAGE_PRESENT) {
-			page &= PAGE_MASK;
-			address &= 0x003ff000;
-			page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
-			printk(KERN_ALERT "*pte = %08lx\n", page);
+
+	bust_spinlocks(1);
+
+	if (oops_may_print()) {
+		__typeof__(pte_val(__pte(0))) page;
+
+		if (address < PAGE_SIZE)
+			printk(KERN_ALERT "Unable to handle kernel NULL "
+					  "pointer dereference");
+		else
+			printk(KERN_ALERT "Unable to handle kernel paging "
+					  "request");
+		printk(" at virtual address %08lx\n", address);
+		printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+		page = (unsigned long)get_TTB();
+		if (page) {
+			page = ((__typeof__(page) *) __va(page))[address >>
+								 PGDIR_SHIFT];
+			printk(KERN_ALERT "*pde = %08lx\n", page);
+			if (page & _PAGE_PRESENT) {
+				page &= PAGE_MASK;
+				address &= 0x003ff000;
+				page = ((__typeof__(page) *)
+						__va(page))[address >>
+							    PAGE_SHIFT];
+				printk(KERN_ALERT "*pte = %08lx\n", page);
+			}
 		}
 	}
+
 	die("Oops", regs, writeaccess);
+	bust_spinlocks(0);
 	do_exit(SIGKILL);
 
 /*
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index e0e644f..82b68c7 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -18,6 +18,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
+#include <asm/sections.h>
 #include <asm/cache.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -36,14 +37,11 @@
 	show_free_areas();
 
 	for_each_online_pgdat(pgdat) {
-		struct page *page, *end;
-		unsigned long flags;
+		unsigned long flags, i;
 
 		pgdat_resize_lock(pgdat, &flags);
-		page = pgdat->node_mem_map;
-		end = page + pgdat->node_spanned_pages;
-
-		do {
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page = pgdat_page_nr(pgdat, i);
 			total++;
 			if (PageReserved(page))
 				reserved++;
@@ -55,9 +53,7 @@
 				free++;
 			else
 				shared += page_count(page) - 1;
-			page++;
-		} while (page < end);
-
+		}
 		pgdat_resize_unlock(pgdat, &flags);
 	}
 
@@ -137,16 +133,12 @@
 }
 #endif	/* CONFIG_MMU */
 
-/* References to section boundaries */
-
-extern char _text, _etext, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
-
 /*
  * paging_init() sets up the page tables
  */
 void __init paging_init(void)
 {
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
 	int nid;
 
 	/* We don't need to map the kernel through the TLB, as
@@ -158,43 +150,39 @@
 	 * check for a null value. */
 	set_TTB(swapper_pg_dir);
 
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+
 	for_each_online_node(nid) {
 		pg_data_t *pgdat = NODE_DATA(nid);
-		unsigned long max_zone_pfns[MAX_NR_ZONES];
 		unsigned long low, start_pfn;
 
-		memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-
 		start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
 		low = pgdat->bdata->node_low_pfn;
 
-		max_zone_pfns[ZONE_NORMAL] = low;
-		add_active_range(nid, start_pfn, low);
+		if (max_zone_pfns[ZONE_NORMAL] < low)
+			max_zone_pfns[ZONE_NORMAL] = low;
 
 		printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
 		       nid, start_pfn, low);
-
-		free_area_init_nodes(max_zone_pfns);
-
-		printk("Node %u: mem_map starts at %p\n",
-		       pgdat->node_id, pgdat->node_mem_map);
 	}
+
+	free_area_init_nodes(max_zone_pfns);
 }
 
 static struct kcore_list kcore_mem, kcore_vmalloc;
 
 void __init mem_init(void)
 {
-	int codesize, reservedpages, datasize, initsize;
+	int codesize, datasize, initsize;
 	int nid;
 
-	reservedpages = 0;
+	num_physpages = 0;
+	high_memory = NULL;
 
 	for_each_online_node(nid) {
 		pg_data_t *pgdat = NODE_DATA(nid);
 		unsigned long node_pages = 0;
 		void *node_high_memory;
-		int i;
 
 		num_physpages += pgdat->node_present_pages;
 
@@ -203,13 +191,9 @@
 
 		totalram_pages += node_pages;
 
-		for (i = 0; i < node_pages; i++)
-			if (PageReserved(pgdat->node_mem_map + i))
-				reservedpages++;
-
-		node_high_memory = (void *)((pgdat->node_start_pfn +
-					     pgdat->node_spanned_pages) <<
-						PAGE_SHIFT);
+		node_high_memory = (void *)__va((pgdat->node_start_pfn +
+						 pgdat->node_spanned_pages) <<
+						 PAGE_SHIFT);
 		if (node_high_memory > high_memory)
 			high_memory = node_high_memory;
 	}
@@ -239,11 +223,10 @@
 		   VMALLOC_END - VMALLOC_START);
 
 	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
-	       "%dk reserved, %dk data, %dk init)\n",
+	       "%dk data, %dk init)\n",
 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
-		totalram_pages << (PAGE_SHIFT-10),
+		num_physpages << (PAGE_SHIFT-10),
 		codesize >> 10,
-		reservedpages << (PAGE_SHIFT-10),
 		datasize >> 10,
 		initsize >> 10);
 
@@ -264,7 +247,9 @@
 		free_page(addr);
 		totalram_pages++;
 	}
-	printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+	printk("Freeing unused kernel memory: %ldk freed\n",
+	       ((unsigned long)&__init_end -
+	        (unsigned long)&__init_begin) >> 10);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -277,6 +262,50 @@
 		free_page(p);
 		totalram_pages++;
 	}
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	printk("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+void online_page(struct page *page)
+{
+	ClearPageReserved(page);
+	init_page_count(page);
+	__free_page(page);
+	totalram_pages++;
+	num_physpages++;
+}
+
+int arch_add_memory(int nid, u64 start, u64 size)
+{
+	pg_data_t *pgdat;
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long nr_pages = size >> PAGE_SHIFT;
+	int ret;
+
+	pgdat = NODE_DATA(nid);
+
+	/* We only have ZONE_NORMAL, so this is easy.. */
+	ret = __add_pages(pgdat->node_zones + ZONE_NORMAL, start_pfn, nr_pages);
+	if (unlikely(ret))
+		printk("%s: Failed, __add_pages() == %d\n", __FUNCTION__, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(arch_add_memory);
+
+int remove_memory(u64 start, u64 size)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(remove_memory);
+
+#ifdef CONFIG_NUMA
+int memory_add_physaddr_to_nid(u64 addr)
+{
+	/* Node 0 for now.. */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
+#endif
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
new file mode 100644
index 0000000..8aff065
--- /dev/null
+++ b/arch/sh/mm/numa.c
@@ -0,0 +1,92 @@
+/*
+ * arch/sh/mm/numa.c - Multiple node support for SH machines
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * 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/module.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/numa.h>
+#include <linux/pfn.h>
+#include <asm/sections.h>
+
+static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL_GPL(node_data);
+
+/*
+ * On SH machines the conventional approach is to stash system RAM
+ * in node 0, and other memory blocks in to node 1 and up, ordered by
+ * latency. Each node's pgdat is node-local at the beginning of the node,
+ * immediately followed by the node mem map.
+ */
+void __init setup_memory(void)
+{
+	unsigned long free_pfn = PFN_UP(__pa(_end));
+
+	/*
+	 * Node 0 sets up its pgdat at the first available pfn,
+	 * and bumps it up before setting up the bootmem allocator.
+	 */
+	NODE_DATA(0) = pfn_to_kaddr(free_pfn);
+	memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
+	free_pfn += PFN_UP(sizeof(struct pglist_data));
+	NODE_DATA(0)->bdata = &plat_node_bdata[0];
+
+	/* Set up node 0 */
+	setup_bootmem_allocator(free_pfn);
+
+	/* Give the platforms a chance to hook up their nodes */
+	plat_mem_setup();
+}
+
+void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
+{
+	unsigned long bootmap_pages, bootmap_start, bootmap_size;
+	unsigned long start_pfn, free_pfn, end_pfn;
+
+	/* Don't allow bogus node assignment */
+	BUG_ON(nid > MAX_NUMNODES || nid == 0);
+
+	/*
+	 * The free pfn starts at the beginning of the range, and is
+	 * advanced as necessary for pgdat and node map allocations.
+	 */
+	free_pfn = start_pfn = start >> PAGE_SHIFT;
+	end_pfn = end >> PAGE_SHIFT;
+
+	add_active_range(nid, start_pfn, end_pfn);
+
+	/* Node-local pgdat */
+	NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
+	free_pfn += PFN_UP(sizeof(struct pglist_data));
+	memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+
+	NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+	NODE_DATA(nid)->node_start_pfn = start_pfn;
+	NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
+
+	/* Node-local bootmap */
+	bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+	bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
+	bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
+				    end_pfn);
+
+	free_bootmem_with_active_regions(nid, end_pfn);
+
+	/* Reserve the pgdat and bootmap space with the bootmem allocator */
+	reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
+			     sizeof(struct pglist_data));
+	reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
+			     bootmap_pages << PAGE_SHIFT);
+
+	/* It's up */
+	node_set_online(nid);
+
+	/* Kick sparsemem */
+	sparse_memory_present_with_active_regions(nid);
+}
diff --git a/arch/sh/mm/pg-dma.c b/arch/sh/mm/pg-dma.c
deleted file mode 100644
index bb23679..0000000
--- a/arch/sh/mm/pg-dma.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * arch/sh/mm/pg-dma.c
- *
- * Fast clear_page()/copy_page() implementation using the SH DMAC
- *
- * Copyright (C) 2003  Paul Mundt
- *
- * 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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/semaphore.h>
-#include <asm/mmu_context.h>
-#include <asm/addrspace.h>
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-
-/* Channel to use for page ops, must be dual-address mode capable. */
-static int dma_channel = CONFIG_DMA_PAGE_OPS_CHANNEL;
-
-static void copy_page_dma(void *to, void *from)
-{
-	/* 
-	 * This doesn't seem to get triggered until further along in the
-	 * boot process, at which point the DMAC is already initialized.
-	 * Fix this in the same fashion as clear_page_dma() in the event
-	 * that this crashes due to the DMAC not being initialized.
-	 */
-
-	flush_icache_range((unsigned long)from, PAGE_SIZE);
-	dma_write_page(dma_channel, (unsigned long)from, (unsigned long)to);
-	dma_wait_for_completion(dma_channel);
-}
-
-static void clear_page_dma(void *to)
-{
-	/*
-	 * We get invoked quite early on, if the DMAC hasn't been initialized
-	 * yet, fall back on the slow manual implementation.
-	 */
-	if (dma_info[dma_channel].chan != dma_channel) {
-		clear_page_slow(to);
-		return;
-	}
-
-	dma_write_page(dma_channel, (unsigned long)empty_zero_page,
-				    (unsigned long)to);
-
-	/*
-	 * FIXME: Something is a bit racy here, if we poll the counter right
-	 * away, we seem to lock. flushing the page from the dcache doesn't
-	 * seem to make a difference one way or the other, though either a full
-	 * icache or dcache flush does.
-	 *
-	 * The location of this is important as well, and must happen prior to
-	 * the completion loop but after the transfer was initiated.
-	 *
-	 * Oddly enough, this doesn't appear to be an issue for copy_page()..
-	 */
-	flush_icache_range((unsigned long)to, PAGE_SIZE);
-
-	dma_wait_for_completion(dma_channel);
-}
-
-static int __init pg_dma_init(void)
-{
-	int ret;
-	
-	ret = request_dma(dma_channel, "page ops");
-	if (ret != 0)
-		return ret;
-
-	copy_page = copy_page_dma;
-	clear_page = clear_page_dma;
-
-	return ret;
-}
-
-static void __exit pg_dma_exit(void)
-{
-	free_dma(dma_channel);
-}
-
-module_init(pg_dma_init);
-module_exit(pg_dma_exit);
-
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
-MODULE_DESCRIPTION("Optimized page copy/clear routines using a dual-address mode capable DMAC channel");
-MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/tools/Makefile b/arch/sh/tools/Makefile
index 3c370a1..567516b 100644
--- a/arch/sh/tools/Makefile
+++ b/arch/sh/tools/Makefile
@@ -12,4 +12,5 @@
 
 include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
 	@echo '  Generating $@'
+	$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
 	$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index fb40f18..4b5e930 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -18,7 +18,6 @@
 HP6XX			SH_HP6XX
 HD64461			HD64461
 HD64465			HD64465
-SATURN			SH_SATURN
 DREAMCAST		SH_DREAMCAST
 MPC1211			SH_MPC1211
 SNAPGEAR		SH_SECUREEDGE5410
@@ -34,3 +33,4 @@
 TITAN			SH_TITAN
 SHMIN			SH_SHMIN
 7710VOIPGW		SH_7710VOIPGW
+LBOXRE2			SH_LBOX_RE2
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 4e95e18..df06c64 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -129,17 +129,9 @@
 	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 *) data);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -166,10 +158,7 @@
 	/* when 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;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR:
diff --git a/arch/sh64/lib/c-checksum.c b/arch/sh64/lib/c-checksum.c
index 4b26763..bd55017 100644
--- a/arch/sh64/lib/c-checksum.c
+++ b/arch/sh64/lib/c-checksum.c
@@ -213,3 +213,4 @@
 
 	return (__wsum)result;
 }
+EXPORT_SYMBOL(csum_tcpudp_nofold);
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 8567cc9..73df711 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -217,6 +217,9 @@
 
 endif
 
+config NO_DMA
+	def_bool !PCI
+
 config SUN_OPENPROMFS
 	tristate "Openprom tree appears in /proc/openprom"
 	help
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
index dc9ffea..3bc3bff 100644
--- a/arch/sparc/kernel/traps.c
+++ b/arch/sparc/kernel/traps.c
@@ -101,6 +101,7 @@
 
 	printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
 	show_regs(regs);
+	add_taint(TAINT_DIE);
 
 	__SAVE; __SAVE; __SAVE; __SAVE;
 	__SAVE; __SAVE; __SAVE; __SAVE;
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index e5eaa80..ca26232 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -160,9 +160,6 @@
 static inline int srmmu_pte_present(pte_t pte)
 { return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE); }
 
-static inline int srmmu_pte_read(pte_t pte)
-{ return !(pte_val(pte) & SRMMU_NOREAD); }
-
 static inline void srmmu_pte_clear(pte_t *ptep)
 { srmmu_set_pte(ptep, __pte(0)); }
 
@@ -2181,7 +2178,6 @@
 
 	BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0);
-	BTFIXUPSET_CALL(pte_read, srmmu_pte_read, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(pmd_bad, srmmu_pmd_bad, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pmd_present, srmmu_pmd_present, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 436021c..bdd835f 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1748,11 +1748,6 @@
 }
 static void sun4c_pte_clear(pte_t *ptep)	{ *ptep = __pte(0); }
 
-static int sun4c_pte_read(pte_t pte)
-{
-	return (pte_val(pte) & _SUN4C_PAGE_READ);
-}
-
 static int sun4c_pmd_bad(pmd_t pmd)
 {
 	return (((pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE) ||
@@ -2212,7 +2207,6 @@
 
 	BTFIXUPSET_CALL(pte_present, sun4c_pte_present, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pte_clear, sun4c_pte_clear, BTFIXUPCALL_STG0O0);
-	BTFIXUPSET_CALL(pte_read, sun4c_pte_read, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(pmd_bad, sun4c_pmd_bad, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pmd_present, sun4c_pmd_present, BTFIXUPCALL_NORM);
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 6566d13..b84b6af 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -108,6 +108,15 @@
 
 source kernel/Kconfig.hz
 
+config HOTPLUG_CPU
+	bool "Support for hot-pluggable CPUs"
+	depends on SMP
+	select HOTPLUG
+	---help---
+	  Say Y here to experiment with turning CPUs off and on.  CPUs
+	  can be controlled through /sys/devices/system/cpu/cpu#.
+	  Say N if you want to disable CPU hotplug.
+
 source "init/Kconfig"
 
 config SYSVIPC_COMPAT
@@ -305,6 +314,12 @@
 	bool
 	default y
 
+config SUN_LDOMS
+	bool "Sun Logical Domains support"
+	help
+	  Say Y here is you want to support virtual devices via
+	  Logical Domains.
+
 config PCI
 	bool "PCI support"
 	select ARCH_SUPPORTS_MSI
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index f964bf2..b66876b 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -18,7 +18,7 @@
 obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o \
 			    pci_sun4v.o pci_sun4v_asm.o pci_fire.o
-obj-$(CONFIG_SMP)	 += smp.o trampoline.o
+obj-$(CONFIG_SMP)	 += smp.o trampoline.o hvtramp.o
 obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
 obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
 obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
@@ -26,6 +26,7 @@
 obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
 obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
 obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o
 obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o
 obj-y += $(obj-yy)
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
new file mode 100644
index 0000000..ba01533
--- /dev/null
+++ b/arch/sparc64/kernel/ds.c
@@ -0,0 +1,1168 @@
+/* ds.c: Domain Services driver for Logical Domains
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/cpu.h>
+
+#include <asm/ldc.h>
+#include <asm/vio.h>
+#include <asm/power.h>
+#include <asm/mdesc.h>
+#include <asm/head.h>
+#include <asm/irq.h>
+
+#define DRV_MODULE_NAME		"ds"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"Jul 11, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM domain services driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+struct ds_msg_tag {
+	__u32			type;
+#define DS_INIT_REQ		0x00
+#define DS_INIT_ACK		0x01
+#define DS_INIT_NACK		0x02
+#define DS_REG_REQ		0x03
+#define DS_REG_ACK		0x04
+#define DS_REG_NACK		0x05
+#define DS_UNREG_REQ		0x06
+#define DS_UNREG_ACK		0x07
+#define DS_UNREG_NACK		0x08
+#define DS_DATA			0x09
+#define DS_NACK			0x0a
+
+	__u32			len;
+};
+
+/* Result codes */
+#define DS_OK			0x00
+#define DS_REG_VER_NACK		0x01
+#define DS_REG_DUP		0x02
+#define DS_INV_HDL		0x03
+#define DS_TYPE_UNKNOWN		0x04
+
+struct ds_version {
+	__u16			major;
+	__u16			minor;
+};
+
+struct ds_ver_req {
+	struct ds_msg_tag	tag;
+	struct ds_version	ver;
+};
+
+struct ds_ver_ack {
+	struct ds_msg_tag	tag;
+	__u16			minor;
+};
+
+struct ds_ver_nack {
+	struct ds_msg_tag	tag;
+	__u16			major;
+};
+
+struct ds_reg_req {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u16			major;
+	__u16			minor;
+	char			svc_id[0];
+};
+
+struct ds_reg_ack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u16			minor;
+};
+
+struct ds_reg_nack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u16			major;
+};
+
+struct ds_unreg_req {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_unreg_ack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_unreg_nack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_data {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_data_nack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u64			result;
+};
+
+struct ds_cap_state {
+	__u64			handle;
+
+	void			(*data)(struct ldc_channel *lp,
+					struct ds_cap_state *cp,
+					void *buf, int len);
+
+	const char		*service_id;
+
+	u8			state;
+#define CAP_STATE_UNKNOWN	0x00
+#define CAP_STATE_REG_SENT	0x01
+#define CAP_STATE_REGISTERED	0x02
+};
+
+static void md_update_data(struct ldc_channel *lp, struct ds_cap_state *cp,
+			   void *buf, int len);
+static void domain_shutdown_data(struct ldc_channel *lp,
+				 struct ds_cap_state *cp,
+				 void *buf, int len);
+static void domain_panic_data(struct ldc_channel *lp,
+			      struct ds_cap_state *cp,
+			      void *buf, int len);
+#ifdef CONFIG_HOTPLUG_CPU
+static void dr_cpu_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len);
+#endif
+static void ds_pri_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len);
+static void ds_var_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len);
+
+struct ds_cap_state ds_states[] = {
+	{
+		.service_id	= "md-update",
+		.data		= md_update_data,
+	},
+	{
+		.service_id	= "domain-shutdown",
+		.data		= domain_shutdown_data,
+	},
+	{
+		.service_id	= "domain-panic",
+		.data		= domain_panic_data,
+	},
+#ifdef CONFIG_HOTPLUG_CPU
+	{
+		.service_id	= "dr-cpu",
+		.data		= dr_cpu_data,
+	},
+#endif
+	{
+		.service_id	= "pri",
+		.data		= ds_pri_data,
+	},
+	{
+		.service_id	= "var-config",
+		.data		= ds_var_data,
+	},
+	{
+		.service_id	= "var-config-backup",
+		.data		= ds_var_data,
+	},
+};
+
+static DEFINE_SPINLOCK(ds_lock);
+
+struct ds_info {
+	struct ldc_channel	*lp;
+	u8			hs_state;
+#define DS_HS_START		0x01
+#define DS_HS_DONE		0x02
+
+	void			*rcv_buf;
+	int			rcv_buf_len;
+};
+
+static struct ds_info *ds_info;
+
+static struct ds_cap_state *find_cap(u64 handle)
+{
+	unsigned int index = handle >> 32;
+
+	if (index >= ARRAY_SIZE(ds_states))
+		return NULL;
+	return &ds_states[index];
+}
+
+static struct ds_cap_state *find_cap_by_string(const char *name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
+		if (strcmp(ds_states[i].service_id, name))
+			continue;
+
+		return &ds_states[i];
+	}
+	return NULL;
+}
+
+static int __ds_send(struct ldc_channel *lp, void *data, int len)
+{
+	int err, limit = 1000;
+
+	err = -EINVAL;
+	while (limit-- > 0) {
+		err = ldc_write(lp, data, len);
+		if (!err || (err != -EAGAIN))
+			break;
+		udelay(1);
+	}
+
+	return err;
+}
+
+static int ds_send(struct ldc_channel *lp, void *data, int len)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&ds_lock, flags);
+	err = __ds_send(lp, data, len);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	return err;
+}
+
+struct ds_md_update_req {
+	__u64				req_num;
+};
+
+struct ds_md_update_res {
+	__u64				req_num;
+	__u32				result;
+};
+
+static void md_update_data(struct ldc_channel *lp,
+			   struct ds_cap_state *dp,
+			   void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_md_update_req *rp;
+	struct {
+		struct ds_data		data;
+		struct ds_md_update_res	res;
+	} pkt;
+
+	rp = (struct ds_md_update_req *) (dpkt + 1);
+
+	printk(KERN_INFO PFX "Machine description update.\n");
+
+	mdesc_update();
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+	pkt.data.handle = dp->handle;
+	pkt.res.req_num = rp->req_num;
+	pkt.res.result = DS_OK;
+
+	ds_send(lp, &pkt, sizeof(pkt));
+}
+
+struct ds_shutdown_req {
+	__u64				req_num;
+	__u32				ms_delay;
+};
+
+struct ds_shutdown_res {
+	__u64				req_num;
+	__u32				result;
+	char				reason[1];
+};
+
+static void domain_shutdown_data(struct ldc_channel *lp,
+				 struct ds_cap_state *dp,
+				 void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_shutdown_req *rp;
+	struct {
+		struct ds_data		data;
+		struct ds_shutdown_res	res;
+	} pkt;
+
+	rp = (struct ds_shutdown_req *) (dpkt + 1);
+
+	printk(KERN_ALERT PFX "Shutdown request from "
+	       "LDOM manager received.\n");
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+	pkt.data.handle = dp->handle;
+	pkt.res.req_num = rp->req_num;
+	pkt.res.result = DS_OK;
+	pkt.res.reason[0] = 0;
+
+	ds_send(lp, &pkt, sizeof(pkt));
+
+	wake_up_powerd();
+}
+
+struct ds_panic_req {
+	__u64				req_num;
+};
+
+struct ds_panic_res {
+	__u64				req_num;
+	__u32				result;
+	char				reason[1];
+};
+
+static void domain_panic_data(struct ldc_channel *lp,
+			      struct ds_cap_state *dp,
+			      void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_panic_req *rp;
+	struct {
+		struct ds_data		data;
+		struct ds_panic_res	res;
+	} pkt;
+
+	rp = (struct ds_panic_req *) (dpkt + 1);
+
+	printk(KERN_ALERT PFX "Panic request from "
+	       "LDOM manager received.\n");
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+	pkt.data.handle = dp->handle;
+	pkt.res.req_num = rp->req_num;
+	pkt.res.result = DS_OK;
+	pkt.res.reason[0] = 0;
+
+	ds_send(lp, &pkt, sizeof(pkt));
+
+	panic("PANIC requested by LDOM manager.");
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+struct dr_cpu_tag {
+	__u64				req_num;
+	__u32				type;
+#define DR_CPU_CONFIGURE		0x43
+#define DR_CPU_UNCONFIGURE		0x55
+#define DR_CPU_FORCE_UNCONFIGURE	0x46
+#define DR_CPU_STATUS			0x53
+
+/* Responses */
+#define DR_CPU_OK			0x6f
+#define DR_CPU_ERROR			0x65
+
+	__u32				num_records;
+};
+
+struct dr_cpu_resp_entry {
+	__u32				cpu;
+	__u32				result;
+#define DR_CPU_RES_OK			0x00
+#define DR_CPU_RES_FAILURE		0x01
+#define DR_CPU_RES_BLOCKED		0x02
+#define DR_CPU_RES_CPU_NOT_RESPONDING	0x03
+#define DR_CPU_RES_NOT_IN_MD		0x04
+
+	__u32				stat;
+#define DR_CPU_STAT_NOT_PRESENT		0x00
+#define DR_CPU_STAT_UNCONFIGURED	0x01
+#define DR_CPU_STAT_CONFIGURED		0x02
+
+	__u32				str_off;
+};
+
+static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data)
+{
+	struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
+	struct ds_info *dp = ds_info;
+	struct {
+		struct ds_data		data;
+		struct dr_cpu_tag	tag;
+	} pkt;
+	int msg_len;
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.handle = cp->handle;
+	pkt.tag.req_num = tag->req_num;
+	pkt.tag.type = DR_CPU_ERROR;
+	pkt.tag.num_records = 0;
+
+	msg_len = (sizeof(struct ds_data) +
+		   sizeof(struct dr_cpu_tag));
+
+	pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
+
+	__ds_send(dp->lp, &pkt, msg_len);
+}
+
+static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ds_lock, flags);
+	__dr_cpu_send_error(cp, data);
+	spin_unlock_irqrestore(&ds_lock, flags);
+}
+
+#define CPU_SENTINEL	0xffffffff
+
+static void purge_dups(u32 *list, u32 num_ents)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_ents; i++) {
+		u32 cpu = list[i];
+		unsigned int j;
+
+		if (cpu == CPU_SENTINEL)
+			continue;
+
+		for (j = i + 1; j < num_ents; j++) {
+			if (list[j] == cpu)
+				list[j] = CPU_SENTINEL;
+		}
+	}
+}
+
+static int dr_cpu_size_response(int ncpus)
+{
+	return (sizeof(struct ds_data) +
+		sizeof(struct dr_cpu_tag) +
+		(sizeof(struct dr_cpu_resp_entry) * ncpus));
+}
+
+static void dr_cpu_init_response(struct ds_data *resp, u64 req_num,
+				 u64 handle, int resp_len, int ncpus,
+				 cpumask_t *mask, u32 default_stat)
+{
+	struct dr_cpu_resp_entry *ent;
+	struct dr_cpu_tag *tag;
+	int i, cpu;
+
+	tag = (struct dr_cpu_tag *) (resp + 1);
+	ent = (struct dr_cpu_resp_entry *) (tag + 1);
+
+	resp->tag.type = DS_DATA;
+	resp->tag.len = resp_len - sizeof(struct ds_msg_tag);
+	resp->handle = handle;
+	tag->req_num = req_num;
+	tag->type = DR_CPU_OK;
+	tag->num_records = ncpus;
+
+	i = 0;
+	for_each_cpu_mask(cpu, *mask) {
+		ent[i].cpu = cpu;
+		ent[i].result = DR_CPU_RES_OK;
+		ent[i].stat = default_stat;
+		i++;
+	}
+	BUG_ON(i != ncpus);
+}
+
+static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus,
+			u32 res, u32 stat)
+{
+	struct dr_cpu_resp_entry *ent;
+	struct dr_cpu_tag *tag;
+	int i;
+
+	tag = (struct dr_cpu_tag *) (resp + 1);
+	ent = (struct dr_cpu_resp_entry *) (tag + 1);
+
+	for (i = 0; i < ncpus; i++) {
+		if (ent[i].cpu != cpu)
+			continue;
+		ent[i].result = res;
+		ent[i].stat = stat;
+		break;
+	}
+}
+
+static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num,
+			    cpumask_t *mask)
+{
+	struct ds_data *resp;
+	int resp_len, ncpus, cpu;
+	unsigned long flags;
+
+	ncpus = cpus_weight(*mask);
+	resp_len = dr_cpu_size_response(ncpus);
+	resp = kzalloc(resp_len, GFP_KERNEL);
+	if (!resp)
+		return -ENOMEM;
+
+	dr_cpu_init_response(resp, req_num, cp->handle,
+			     resp_len, ncpus, mask,
+			     DR_CPU_STAT_CONFIGURED);
+
+	mdesc_fill_in_cpu_data(*mask);
+
+	for_each_cpu_mask(cpu, *mask) {
+		int err;
+
+		printk(KERN_INFO PFX "Starting cpu %d...\n", cpu);
+		err = cpu_up(cpu);
+		if (err) {
+			__u32 res = DR_CPU_RES_FAILURE;
+			__u32 stat = DR_CPU_STAT_UNCONFIGURED;
+
+			if (!cpu_present(cpu)) {
+				/* CPU not present in MD */
+				res = DR_CPU_RES_NOT_IN_MD;
+				stat = DR_CPU_STAT_NOT_PRESENT;
+			} else if (err == -ENODEV) {
+				/* CPU did not call in successfully */
+				res = DR_CPU_RES_CPU_NOT_RESPONDING;
+			}
+
+			printk(KERN_INFO PFX "CPU startup failed err=%d\n",
+			       err);
+			dr_cpu_mark(resp, cpu, ncpus, res, stat);
+		}
+	}
+
+	spin_lock_irqsave(&ds_lock, flags);
+	__ds_send(ds_info->lp, resp, resp_len);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	kfree(resp);
+
+	/* Redistribute IRQs, taking into account the new cpus.  */
+	fixup_irqs();
+
+	return 0;
+}
+
+static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num,
+			      cpumask_t *mask)
+{
+	struct ds_data *resp;
+	int resp_len, ncpus, cpu;
+	unsigned long flags;
+
+	ncpus = cpus_weight(*mask);
+	resp_len = dr_cpu_size_response(ncpus);
+	resp = kzalloc(resp_len, GFP_KERNEL);
+	if (!resp)
+		return -ENOMEM;
+
+	dr_cpu_init_response(resp, req_num, cp->handle,
+			     resp_len, ncpus, mask,
+			     DR_CPU_STAT_UNCONFIGURED);
+
+	for_each_cpu_mask(cpu, *mask) {
+		int err;
+
+		printk(KERN_INFO PFX "CPU[%d]: Shutting down cpu %d...\n",
+		       smp_processor_id(), cpu);
+		err = cpu_down(cpu);
+		if (err)
+			dr_cpu_mark(resp, cpu, ncpus,
+				    DR_CPU_RES_FAILURE,
+				    DR_CPU_STAT_CONFIGURED);
+	}
+
+	spin_lock_irqsave(&ds_lock, flags);
+	__ds_send(ds_info->lp, resp, resp_len);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	kfree(resp);
+
+	return 0;
+}
+
+static void dr_cpu_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len)
+{
+	struct ds_data *data = buf;
+	struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
+	u32 *cpu_list = (u32 *) (tag + 1);
+	u64 req_num = tag->req_num;
+	cpumask_t mask;
+	unsigned int i;
+	int err;
+
+	switch (tag->type) {
+	case DR_CPU_CONFIGURE:
+	case DR_CPU_UNCONFIGURE:
+	case DR_CPU_FORCE_UNCONFIGURE:
+		break;
+
+	default:
+		dr_cpu_send_error(cp, data);
+		return;
+	}
+
+	purge_dups(cpu_list, tag->num_records);
+
+	cpus_clear(mask);
+	for (i = 0; i < tag->num_records; i++) {
+		if (cpu_list[i] == CPU_SENTINEL)
+			continue;
+
+		if (cpu_list[i] < NR_CPUS)
+			cpu_set(cpu_list[i], mask);
+	}
+
+	if (tag->type == DR_CPU_CONFIGURE)
+		err = dr_cpu_configure(cp, req_num, &mask);
+	else
+		err = dr_cpu_unconfigure(cp, req_num, &mask);
+
+	if (err)
+		dr_cpu_send_error(cp, data);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+struct ds_pri_msg {
+	__u64				req_num;
+	__u64				type;
+#define DS_PRI_REQUEST			0x00
+#define DS_PRI_DATA			0x01
+#define DS_PRI_UPDATE			0x02
+};
+
+static void ds_pri_data(struct ldc_channel *lp,
+			struct ds_cap_state *dp,
+			void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_pri_msg *rp;
+
+	rp = (struct ds_pri_msg *) (dpkt + 1);
+
+	printk(KERN_INFO PFX "PRI REQ [%lx:%lx], len=%d\n",
+	       rp->req_num, rp->type, len);
+}
+
+struct ds_var_hdr {
+	__u32				type;
+#define DS_VAR_SET_REQ			0x00
+#define DS_VAR_DELETE_REQ		0x01
+#define DS_VAR_SET_RESP			0x02
+#define DS_VAR_DELETE_RESP		0x03
+};
+
+struct ds_var_set_msg {
+	struct ds_var_hdr		hdr;
+	char				name_and_value[0];
+};
+
+struct ds_var_delete_msg {
+	struct ds_var_hdr		hdr;
+	char				name[0];
+};
+
+struct ds_var_resp {
+	struct ds_var_hdr		hdr;
+	__u32				result;
+#define DS_VAR_SUCCESS			0x00
+#define DS_VAR_NO_SPACE			0x01
+#define DS_VAR_INVALID_VAR		0x02
+#define DS_VAR_INVALID_VAL		0x03
+#define DS_VAR_NOT_PRESENT		0x04
+};
+
+static DEFINE_MUTEX(ds_var_mutex);
+static int ds_var_doorbell;
+static int ds_var_response;
+
+static void ds_var_data(struct ldc_channel *lp,
+			struct ds_cap_state *dp,
+			void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_var_resp *rp;
+
+	rp = (struct ds_var_resp *) (dpkt + 1);
+
+	if (rp->hdr.type != DS_VAR_SET_RESP &&
+	    rp->hdr.type != DS_VAR_DELETE_RESP)
+		return;
+
+	ds_var_response = rp->result;
+	wmb();
+	ds_var_doorbell = 1;
+}
+
+void ldom_set_var(const char *var, const char *value)
+{
+	struct ds_info *dp = ds_info;
+	struct ds_cap_state *cp;
+
+	cp = find_cap_by_string("var-config");
+	if (cp->state != CAP_STATE_REGISTERED)
+		cp = find_cap_by_string("var-config-backup");
+
+	if (cp->state == CAP_STATE_REGISTERED) {
+		union {
+			struct {
+				struct ds_data		data;
+				struct ds_var_set_msg	msg;
+			} header;
+			char			all[512];
+		} pkt;
+		unsigned long flags;
+		char  *base, *p;
+		int msg_len, loops;
+
+		memset(&pkt, 0, sizeof(pkt));
+		pkt.header.data.tag.type = DS_DATA;
+		pkt.header.data.handle = cp->handle;
+		pkt.header.msg.hdr.type = DS_VAR_SET_REQ;
+		base = p = &pkt.header.msg.name_and_value[0];
+		strcpy(p, var);
+		p += strlen(var) + 1;
+		strcpy(p, value);
+		p += strlen(value) + 1;
+
+		msg_len = (sizeof(struct ds_data) +
+			   sizeof(struct ds_var_set_msg) +
+			   (p - base));
+		msg_len = (msg_len + 3) & ~3;
+		pkt.header.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
+
+		mutex_lock(&ds_var_mutex);
+
+		spin_lock_irqsave(&ds_lock, flags);
+		ds_var_doorbell = 0;
+		ds_var_response = -1;
+
+		__ds_send(dp->lp, &pkt, msg_len);
+		spin_unlock_irqrestore(&ds_lock, flags);
+
+		loops = 1000;
+		while (ds_var_doorbell == 0) {
+			if (loops-- < 0)
+				break;
+			barrier();
+			udelay(100);
+		}
+
+		mutex_unlock(&ds_var_mutex);
+
+		if (ds_var_doorbell == 0 ||
+		    ds_var_response != DS_VAR_SUCCESS)
+			printk(KERN_ERR PFX "var-config [%s:%s] "
+			       "failed, response(%d).\n",
+			       var, value,
+			       ds_var_response);
+	} else {
+		printk(KERN_ERR PFX "var-config not registered so "
+		       "could not set (%s) variable to (%s).\n",
+		       var, value);
+	}
+}
+
+void ldom_reboot(const char *boot_command)
+{
+	/* Don't bother with any of this if the boot_command
+	 * is empty.
+	 */
+	if (boot_command && strlen(boot_command)) {
+		char full_boot_str[256];
+
+		strcpy(full_boot_str, "boot ");
+		strcpy(full_boot_str + strlen("boot "), boot_command);
+
+		ldom_set_var("reboot-command", full_boot_str);
+	}
+	sun4v_mach_sir();
+}
+
+void ldom_power_off(void)
+{
+	sun4v_mach_exit(0);
+}
+
+static void ds_conn_reset(struct ds_info *dp)
+{
+	printk(KERN_ERR PFX "ds_conn_reset() from %p\n",
+	       __builtin_return_address(0));
+}
+
+static int register_services(struct ds_info *dp)
+{
+	struct ldc_channel *lp = dp->lp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
+		struct {
+			struct ds_reg_req req;
+			u8 id_buf[256];
+		} pbuf;
+		struct ds_cap_state *cp = &ds_states[i];
+		int err, msg_len;
+		u64 new_count;
+
+		if (cp->state == CAP_STATE_REGISTERED)
+			continue;
+
+		new_count = sched_clock() & 0xffffffff;
+		cp->handle = ((u64) i << 32) | new_count;
+
+		msg_len = (sizeof(struct ds_reg_req) +
+			   strlen(cp->service_id));
+
+		memset(&pbuf, 0, sizeof(pbuf));
+		pbuf.req.tag.type = DS_REG_REQ;
+		pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
+		pbuf.req.handle = cp->handle;
+		pbuf.req.major = 1;
+		pbuf.req.minor = 0;
+		strcpy(pbuf.req.svc_id, cp->service_id);
+
+		err = __ds_send(lp, &pbuf, msg_len);
+		if (err > 0)
+			cp->state = CAP_STATE_REG_SENT;
+	}
+	return 0;
+}
+
+static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
+{
+
+	if (dp->hs_state == DS_HS_START) {
+		if (pkt->type != DS_INIT_ACK)
+			goto conn_reset;
+
+		dp->hs_state = DS_HS_DONE;
+
+		return register_services(dp);
+	}
+
+	if (dp->hs_state != DS_HS_DONE)
+		goto conn_reset;
+
+	if (pkt->type == DS_REG_ACK) {
+		struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
+		struct ds_cap_state *cp = find_cap(ap->handle);
+
+		if (!cp) {
+			printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n",
+			       ap->handle);
+			return 0;
+		}
+		printk(KERN_INFO PFX "Registered %s service.\n",
+		       cp->service_id);
+		cp->state = CAP_STATE_REGISTERED;
+	} else if (pkt->type == DS_REG_NACK) {
+		struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
+		struct ds_cap_state *cp = find_cap(np->handle);
+
+		if (!cp) {
+			printk(KERN_ERR PFX "REG NACK for "
+			       "unknown handle %lx\n",
+			       np->handle);
+			return 0;
+		}
+		printk(KERN_INFO PFX "Could not register %s service\n",
+		       cp->service_id);
+		cp->state = CAP_STATE_UNKNOWN;
+	}
+
+	return 0;
+
+conn_reset:
+	ds_conn_reset(dp);
+	return -ECONNRESET;
+}
+
+static void __send_ds_nack(struct ds_info *dp, u64 handle)
+{
+	struct ds_data_nack nack = {
+		.tag = {
+			.type = DS_NACK,
+			.len = (sizeof(struct ds_data_nack) -
+				sizeof(struct ds_msg_tag)),
+		},
+		.handle = handle,
+		.result = DS_INV_HDL,
+	};
+
+	__ds_send(dp->lp, &nack, sizeof(nack));
+}
+
+static LIST_HEAD(ds_work_list);
+static DECLARE_WAIT_QUEUE_HEAD(ds_wait);
+
+struct ds_queue_entry {
+	struct list_head		list;
+	int				req_len;
+	int				__pad;
+	u64				req[0];
+};
+
+static void process_ds_work(void)
+{
+	struct ds_queue_entry *qp, *tmp;
+	static struct ds_info *dp;
+	unsigned long flags;
+	LIST_HEAD(todo);
+
+	spin_lock_irqsave(&ds_lock, flags);
+	list_splice(&ds_work_list, &todo);
+	INIT_LIST_HEAD(&ds_work_list);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	dp = ds_info;
+
+	list_for_each_entry_safe(qp, tmp, &todo, list) {
+		struct ds_data *dpkt = (struct ds_data *) qp->req;
+		struct ds_cap_state *cp = find_cap(dpkt->handle);
+		int req_len = qp->req_len;
+
+		if (!cp) {
+			printk(KERN_ERR PFX "Data for unknown handle %lu\n",
+			       dpkt->handle);
+
+			spin_lock_irqsave(&ds_lock, flags);
+			__send_ds_nack(dp, dpkt->handle);
+			spin_unlock_irqrestore(&ds_lock, flags);
+		} else {
+			cp->data(dp->lp, cp, dpkt, req_len);
+		}
+
+		list_del(&qp->list);
+		kfree(qp);
+	}
+}
+
+static int ds_thread(void *__unused)
+{
+	DEFINE_WAIT(wait);
+
+	while (1) {
+		prepare_to_wait(&ds_wait, &wait, TASK_INTERRUPTIBLE);
+		if (list_empty(&ds_work_list))
+			schedule();
+		finish_wait(&ds_wait, &wait);
+
+		if (kthread_should_stop())
+			break;
+
+		process_ds_work();
+	}
+
+	return 0;
+}
+
+static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
+{
+	struct ds_data *dpkt = (struct ds_data *) pkt;
+	struct ds_queue_entry *qp;
+
+	qp = kmalloc(sizeof(struct ds_queue_entry) + len, GFP_ATOMIC);
+	if (!qp) {
+		__send_ds_nack(dp, dpkt->handle);
+	} else {
+		memcpy(&qp->req, pkt, len);
+		list_add_tail(&qp->list, &ds_work_list);
+		wake_up(&ds_wait);
+	}
+	return 0;
+}
+
+static void ds_up(struct ds_info *dp)
+{
+	struct ldc_channel *lp = dp->lp;
+	struct ds_ver_req req;
+	int err;
+
+	req.tag.type = DS_INIT_REQ;
+	req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
+	req.ver.major = 1;
+	req.ver.minor = 0;
+
+	err = __ds_send(lp, &req, sizeof(req));
+	if (err > 0)
+		dp->hs_state = DS_HS_START;
+}
+
+static void ds_event(void *arg, int event)
+{
+	struct ds_info *dp = arg;
+	struct ldc_channel *lp = dp->lp;
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&ds_lock, flags);
+
+	if (event == LDC_EVENT_UP) {
+		ds_up(dp);
+		spin_unlock_irqrestore(&ds_lock, flags);
+		return;
+	}
+
+	if (event != LDC_EVENT_DATA_READY) {
+		printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+		spin_unlock_irqrestore(&ds_lock, flags);
+		return;
+	}
+
+	err = 0;
+	while (1) {
+		struct ds_msg_tag *tag;
+
+		err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
+
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				ds_conn_reset(dp);
+			break;
+		}
+		if (err == 0)
+			break;
+
+		tag = dp->rcv_buf;
+		err = ldc_read(lp, tag + 1, tag->len);
+
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				ds_conn_reset(dp);
+			break;
+		}
+		if (err < tag->len)
+			break;
+
+		if (tag->type < DS_DATA)
+			err = ds_handshake(dp, dp->rcv_buf);
+		else
+			err = ds_data(dp, dp->rcv_buf,
+				      sizeof(*tag) + err);
+		if (err == -ECONNRESET)
+			break;
+	}
+
+	spin_unlock_irqrestore(&ds_lock, flags);
+}
+
+static int __devinit ds_probe(struct vio_dev *vdev,
+			      const struct vio_device_id *id)
+{
+	static int ds_version_printed;
+	struct ldc_channel_config ds_cfg = {
+		.event		= ds_event,
+		.mtu		= 4096,
+		.mode		= LDC_MODE_STREAM,
+	};
+	struct ldc_channel *lp;
+	struct ds_info *dp;
+	int err;
+
+	if (ds_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	dp = kzalloc(sizeof(*dp), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!dp)
+		goto out_err;
+
+	dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
+	if (!dp->rcv_buf)
+		goto out_free_dp;
+
+	dp->rcv_buf_len = 4096;
+
+	ds_cfg.tx_irq = vdev->tx_irq;
+	ds_cfg.rx_irq = vdev->rx_irq;
+
+	lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
+	if (IS_ERR(lp)) {
+		err = PTR_ERR(lp);
+		goto out_free_rcv_buf;
+	}
+	dp->lp = lp;
+
+	err = ldc_bind(lp, "DS");
+	if (err)
+		goto out_free_ldc;
+
+	ds_info = dp;
+
+	start_powerd();
+
+	return err;
+
+out_free_ldc:
+	ldc_free(dp->lp);
+
+out_free_rcv_buf:
+	kfree(dp->rcv_buf);
+
+out_free_dp:
+	kfree(dp);
+
+out_err:
+	return err;
+}
+
+static int ds_remove(struct vio_dev *vdev)
+{
+	return 0;
+}
+
+static struct vio_device_id ds_match[] = {
+	{
+		.type = "domain-services-port",
+	},
+	{},
+};
+
+static struct vio_driver ds_driver = {
+	.id_table	= ds_match,
+	.probe		= ds_probe,
+	.remove		= ds_remove,
+	.driver		= {
+		.name	= "ds",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init ds_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ds_states); i++)
+		ds_states[i].handle = ((u64)i << 32);
+
+	kthread_run(ds_thread, NULL, "kldomd");
+
+	return vio_register_driver(&ds_driver);
+}
+
+subsys_initcall(ds_init);
diff --git a/arch/sparc64/kernel/hvtramp.S b/arch/sparc64/kernel/hvtramp.S
new file mode 100644
index 0000000..76a090e
--- /dev/null
+++ b/arch/sparc64/kernel/hvtramp.S
@@ -0,0 +1,139 @@
+/* hvtramp.S: Hypervisor start-cpu trampoline code.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <asm/thread_info.h>
+#include <asm/hypervisor.h>
+#include <asm/scratchpad.h>
+#include <asm/spitfire.h>
+#include <asm/hvtramp.h>
+#include <asm/pstate.h>
+#include <asm/ptrace.h>
+#include <asm/asi.h>
+
+	.text
+	.align		8
+	.globl		hv_cpu_startup, hv_cpu_startup_end
+
+	/* This code executes directly out of the hypervisor
+	 * with physical addressing (va==pa).  %o0 contains
+	 * our client argument which for Linux points to
+	 * a descriptor data structure which defines the
+	 * MMU entries we need to load up.
+	 *
+	 * After we set things up we enable the MMU and call
+	 * into the kernel.
+	 *
+	 * First setup basic privileged cpu state.
+	 */
+hv_cpu_startup:
+	wrpr		%g0, 0, %gl
+	wrpr		%g0, 15, %pil
+	wrpr		%g0, 0, %canrestore
+	wrpr		%g0, 0, %otherwin
+	wrpr		%g0, 6, %cansave
+	wrpr		%g0, 6, %cleanwin
+	wrpr		%g0, 0, %cwp
+	wrpr		%g0, 0, %wstate
+	wrpr		%g0, 0, %tl
+
+	sethi		%hi(sparc64_ttable_tl0), %g1
+	wrpr		%g1, %tba
+
+	mov		%o0, %l0
+
+	lduw		[%l0 + HVTRAMP_DESCR_CPU], %g1
+	mov		SCRATCHPAD_CPUID, %g2
+	stxa		%g1, [%g2] ASI_SCRATCHPAD
+
+	ldx		[%l0 + HVTRAMP_DESCR_FAULT_INFO_VA], %g2
+	stxa		%g2, [%g0] ASI_SCRATCHPAD
+
+	mov		0, %l1
+	lduw		[%l0 + HVTRAMP_DESCR_NUM_MAPPINGS], %l2
+	add		%l0, HVTRAMP_DESCR_MAPS, %l3
+
+1:	ldx		[%l3 + HVTRAMP_MAPPING_VADDR], %o0
+	clr		%o1
+	ldx		[%l3 + HVTRAMP_MAPPING_TTE], %o2
+	mov		HV_MMU_IMMU | HV_MMU_DMMU, %o3
+	mov		HV_FAST_MMU_MAP_PERM_ADDR, %o5
+	ta		HV_FAST_TRAP
+
+	brnz,pn		%o0, 80f
+	 nop
+
+	add		%l1, 1, %l1
+	cmp		%l1, %l2
+	blt,a,pt	%xcc, 1b
+	 add		%l3, HVTRAMP_MAPPING_SIZE, %l3
+
+	ldx		[%l0 + HVTRAMP_DESCR_FAULT_INFO_PA], %o0
+	mov		HV_FAST_MMU_FAULT_AREA_CONF, %o5
+	ta		HV_FAST_TRAP
+
+	brnz,pn		%o0, 80f
+	 nop
+
+	wrpr		%g0, (PSTATE_PRIV | PSTATE_PEF), %pstate
+
+	ldx		[%l0 + HVTRAMP_DESCR_THREAD_REG], %l6
+
+	mov		1, %o0
+	set		1f, %o1
+	mov		HV_FAST_MMU_ENABLE, %o5
+	ta		HV_FAST_TRAP
+
+	ba,pt		%xcc, 80f
+	 nop
+
+1:
+	wr		%g0, 0, %fprs
+	wr		%g0, ASI_P, %asi
+
+	mov		PRIMARY_CONTEXT, %g7
+	stxa		%g0, [%g7] ASI_MMU
+	membar		#Sync
+
+	mov		SECONDARY_CONTEXT, %g7
+	stxa		%g0, [%g7] ASI_MMU
+	membar		#Sync
+
+	mov		%l6, %g6
+	ldx		[%g6 + TI_TASK], %g4
+
+	mov		1, %g5
+	sllx		%g5, THREAD_SHIFT, %g5
+	sub		%g5, (STACKFRAME_SZ + STACK_BIAS), %g5
+	add		%g6, %g5, %sp
+	mov		0, %fp
+
+	call		init_irqwork_curcpu
+	 nop
+	call		hard_smp_processor_id
+	 nop
+
+	mov		%o0, %o1
+	mov		0, %o0
+	mov		0, %o2
+	call		sun4v_init_mondo_queues
+	 mov		1, %o3
+
+	call		init_cur_cpu_trap
+	 mov		%g6, %o0
+
+	wrpr		%g0, (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE), %pstate
+
+	call		smp_callin
+	 nop
+	call		cpu_idle
+	 mov		0, %o0
+	call		cpu_panic
+	 nop
+
+80:	ba,pt		%xcc, 80b
+	 nop
+
+	.align		8
+hv_cpu_startup_end:
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 6b6165d3..8cb3358 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -293,6 +293,11 @@
 	}
 }
 
+static void sun4u_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+	sun4u_irq_enable(virt_irq);
+}
+
 static void sun4u_irq_disable(unsigned int virt_irq)
 {
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
@@ -309,6 +314,10 @@
 static void sun4u_irq_end(unsigned int virt_irq)
 {
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+	struct irq_desc *desc = irq_desc + virt_irq;
+
+	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		return;
 
 	if (likely(data))
 		upa_writeq(ICLR_IDLE, data->iclr);
@@ -340,6 +349,24 @@
 	}
 }
 
+static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		unsigned long cpuid;
+		int err;
+
+		cpuid = irq_choose_cpu(virt_irq);
+
+		err = sun4v_intr_settarget(ino, cpuid);
+		if (err != HV_EOK)
+			printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
+			       ino, cpuid, err);
+	}
+}
+
 static void sun4v_irq_disable(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -373,6 +400,10 @@
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
 	unsigned int ino = bucket - &ivector_table[0];
+	struct irq_desc *desc = irq_desc + virt_irq;
+
+	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		return;
 
 	if (likely(bucket)) {
 		int err;
@@ -418,6 +449,28 @@
 	}
 }
 
+static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		unsigned long cpuid, dev_handle, dev_ino;
+		int err;
+
+		cpuid = irq_choose_cpu(virt_irq);
+
+		dev_handle = ino & IMAP_IGN;
+		dev_ino = ino & IMAP_INO;
+
+		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
+		if (err != HV_EOK)
+			printk("sun4v_vintr_set_target(%lx,%lx,%lu): "
+			       "err(%d)\n",
+			       dev_handle, dev_ino, cpuid, err);
+	}
+}
+
 static void sun4v_virq_disable(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -443,6 +496,10 @@
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
 	unsigned int ino = bucket - &ivector_table[0];
+	struct irq_desc *desc = irq_desc + virt_irq;
+
+	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		return;
 
 	if (likely(bucket)) {
 		unsigned long dev_handle, dev_ino;
@@ -477,6 +534,7 @@
 	.enable		= sun4u_irq_enable,
 	.disable	= sun4u_irq_disable,
 	.end		= sun4u_irq_end,
+	.set_affinity	= sun4u_set_affinity,
 };
 
 static struct irq_chip sun4u_irq_ack = {
@@ -485,6 +543,7 @@
 	.disable	= sun4u_irq_disable,
 	.ack		= run_pre_handler,
 	.end		= sun4u_irq_end,
+	.set_affinity	= sun4u_set_affinity,
 };
 
 static struct irq_chip sun4v_irq = {
@@ -492,6 +551,7 @@
 	.enable		= sun4v_irq_enable,
 	.disable	= sun4v_irq_disable,
 	.end		= sun4v_irq_end,
+	.set_affinity	= sun4v_set_affinity,
 };
 
 static struct irq_chip sun4v_irq_ack = {
@@ -500,6 +560,7 @@
 	.disable	= sun4v_irq_disable,
 	.ack		= run_pre_handler,
 	.end		= sun4v_irq_end,
+	.set_affinity	= sun4v_set_affinity,
 };
 
 #ifdef CONFIG_PCI_MSI
@@ -511,6 +572,7 @@
 	.disable	= sun4v_msi_disable,
 	.ack		= run_pre_handler,
 	.end		= sun4v_irq_end,
+	.set_affinity	= sun4v_set_affinity,
 };
 #endif
 
@@ -519,6 +581,7 @@
 	.enable		= sun4v_virq_enable,
 	.disable	= sun4v_virq_disable,
 	.end		= sun4v_virq_end,
+	.set_affinity	= sun4v_virt_set_affinity,
 };
 
 static struct irq_chip sun4v_virq_ack = {
@@ -527,6 +590,7 @@
 	.disable	= sun4v_virq_disable,
 	.ack		= run_pre_handler,
 	.end		= sun4v_virq_end,
+	.set_affinity	= sun4v_virt_set_affinity,
 };
 
 void irq_install_pre_handler(int virt_irq,
@@ -739,6 +803,26 @@
 	set_irq_regs(old_regs);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+void fixup_irqs(void)
+{
+	unsigned int irq;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&irq_desc[irq].lock, flags);
+		if (irq_desc[irq].action &&
+		    !(irq_desc[irq].status & IRQ_PER_CPU)) {
+			if (irq_desc[irq].chip->set_affinity)
+				irq_desc[irq].chip->set_affinity(irq,
+					irq_desc[irq].affinity);
+		}
+		spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+	}
+}
+#endif
+
 struct sun5_timer {
 	u64	count0;
 	u64	limit0;
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c
new file mode 100644
index 0000000..85a2be0
--- /dev/null
+++ b/arch/sparc64/kernel/ldc.c
@@ -0,0 +1,2373 @@
+/* ldc.c: Logical Domain Channel link-layer protocol driver.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/iommu.h>
+#include <asm/page.h>
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+#define DRV_MODULE_NAME		"ldc"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"June 25, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+#define LDC_PACKET_SIZE		64
+
+/* Packet header layout for unreliable and reliable mode frames.
+ * When in RAW mode, packets are simply straight 64-byte payloads
+ * with no headers.
+ */
+struct ldc_packet {
+	u8			type;
+#define LDC_CTRL		0x01
+#define LDC_DATA		0x02
+#define LDC_ERR			0x10
+
+	u8			stype;
+#define LDC_INFO		0x01
+#define LDC_ACK			0x02
+#define LDC_NACK		0x04
+
+	u8			ctrl;
+#define LDC_VERS		0x01 /* Link Version		*/
+#define LDC_RTS			0x02 /* Request To Send		*/
+#define LDC_RTR			0x03 /* Ready To Receive	*/
+#define LDC_RDX			0x04 /* Ready for Data eXchange	*/
+#define LDC_CTRL_MSK		0x0f
+
+	u8			env;
+#define LDC_LEN			0x3f
+#define LDC_FRAG_MASK		0xc0
+#define LDC_START		0x40
+#define LDC_STOP		0x80
+
+	u32			seqid;
+
+	union {
+		u8		u_data[LDC_PACKET_SIZE - 8];
+		struct {
+			u32	pad;
+			u32	ackid;
+			u8	r_data[LDC_PACKET_SIZE - 8 - 8];
+		} r;
+	} u;
+};
+
+struct ldc_version {
+	u16 major;
+	u16 minor;
+};
+
+/* Ordered from largest major to lowest.  */
+static struct ldc_version ver_arr[] = {
+	{ .major = 1, .minor = 0 },
+};
+
+#define LDC_DEFAULT_MTU			(4 * LDC_PACKET_SIZE)
+#define LDC_DEFAULT_NUM_ENTRIES		(PAGE_SIZE / LDC_PACKET_SIZE)
+
+struct ldc_channel;
+
+struct ldc_mode_ops {
+	int (*write)(struct ldc_channel *, const void *, unsigned int);
+	int (*read)(struct ldc_channel *, void *, unsigned int);
+};
+
+static const struct ldc_mode_ops raw_ops;
+static const struct ldc_mode_ops nonraw_ops;
+static const struct ldc_mode_ops stream_ops;
+
+int ldom_domaining_enabled;
+
+struct ldc_iommu {
+	/* Protects arena alloc/free.  */
+	spinlock_t			lock;
+	struct iommu_arena		arena;
+	struct ldc_mtable_entry		*page_table;
+};
+
+struct ldc_channel {
+	/* Protects all operations that depend upon channel state.  */
+	spinlock_t			lock;
+
+	unsigned long			id;
+
+	u8				*mssbuf;
+	u32				mssbuf_len;
+	u32				mssbuf_off;
+
+	struct ldc_packet		*tx_base;
+	unsigned long			tx_head;
+	unsigned long			tx_tail;
+	unsigned long			tx_num_entries;
+	unsigned long			tx_ra;
+
+	unsigned long			tx_acked;
+
+	struct ldc_packet		*rx_base;
+	unsigned long			rx_head;
+	unsigned long			rx_tail;
+	unsigned long			rx_num_entries;
+	unsigned long			rx_ra;
+
+	u32				rcv_nxt;
+	u32				snd_nxt;
+
+	unsigned long			chan_state;
+
+	struct ldc_channel_config	cfg;
+	void				*event_arg;
+
+	const struct ldc_mode_ops	*mops;
+
+	struct ldc_iommu		iommu;
+
+	struct ldc_version		ver;
+
+	u8				hs_state;
+#define LDC_HS_CLOSED			0x00
+#define LDC_HS_OPEN			0x01
+#define LDC_HS_GOTVERS			0x02
+#define LDC_HS_SENTRTR			0x03
+#define LDC_HS_GOTRTR			0x04
+#define LDC_HS_COMPLETE			0x10
+
+	u8				flags;
+#define LDC_FLAG_ALLOCED_QUEUES		0x01
+#define LDC_FLAG_REGISTERED_QUEUES	0x02
+#define LDC_FLAG_REGISTERED_IRQS	0x04
+#define LDC_FLAG_RESET			0x10
+
+	u8				mss;
+	u8				state;
+
+#define LDC_IRQ_NAME_MAX		32
+	char				rx_irq_name[LDC_IRQ_NAME_MAX];
+	char				tx_irq_name[LDC_IRQ_NAME_MAX];
+
+	struct hlist_head		mh_list;
+
+	struct hlist_node		list;
+};
+
+#define ldcdbg(TYPE, f, a...) \
+do {	if (lp->cfg.debug & LDC_DEBUG_##TYPE) \
+		printk(KERN_INFO PFX "ID[%lu] " f, lp->id, ## a); \
+} while (0)
+
+static const char *state_to_str(u8 state)
+{
+	switch (state) {
+	case LDC_STATE_INVALID:
+		return "INVALID";
+	case LDC_STATE_INIT:
+		return "INIT";
+	case LDC_STATE_BOUND:
+		return "BOUND";
+	case LDC_STATE_READY:
+		return "READY";
+	case LDC_STATE_CONNECTED:
+		return "CONNECTED";
+	default:
+		return "<UNKNOWN>";
+	}
+}
+
+static void ldc_set_state(struct ldc_channel *lp, u8 state)
+{
+	ldcdbg(STATE, "STATE (%s) --> (%s)\n",
+	       state_to_str(lp->state),
+	       state_to_str(state));
+
+	lp->state = state;
+}
+
+static unsigned long __advance(unsigned long off, unsigned long num_entries)
+{
+	off += LDC_PACKET_SIZE;
+	if (off == (num_entries * LDC_PACKET_SIZE))
+		off = 0;
+
+	return off;
+}
+
+static unsigned long rx_advance(struct ldc_channel *lp, unsigned long off)
+{
+	return __advance(off, lp->rx_num_entries);
+}
+
+static unsigned long tx_advance(struct ldc_channel *lp, unsigned long off)
+{
+	return __advance(off, lp->tx_num_entries);
+}
+
+static struct ldc_packet *handshake_get_tx_packet(struct ldc_channel *lp,
+						  unsigned long *new_tail)
+{
+	struct ldc_packet *p;
+	unsigned long t;
+
+	t = tx_advance(lp, lp->tx_tail);
+	if (t == lp->tx_head)
+		return NULL;
+
+	*new_tail = t;
+
+	p = lp->tx_base;
+	return p + (lp->tx_tail / LDC_PACKET_SIZE);
+}
+
+/* When we are in reliable or stream mode, have to track the next packet
+ * we haven't gotten an ACK for in the TX queue using tx_acked.  We have
+ * to be careful not to stomp over the queue past that point.  During
+ * the handshake, we don't have TX data packets pending in the queue
+ * and that's why handshake_get_tx_packet() need not be mindful of
+ * lp->tx_acked.
+ */
+static unsigned long head_for_data(struct ldc_channel *lp)
+{
+	if (lp->cfg.mode == LDC_MODE_STREAM)
+		return lp->tx_acked;
+	return lp->tx_head;
+}
+
+static int tx_has_space_for(struct ldc_channel *lp, unsigned int size)
+{
+	unsigned long limit, tail, new_tail, diff;
+	unsigned int mss;
+
+	limit = head_for_data(lp);
+	tail = lp->tx_tail;
+	new_tail = tx_advance(lp, tail);
+	if (new_tail == limit)
+		return 0;
+
+	if (limit > new_tail)
+		diff = limit - new_tail;
+	else
+		diff = (limit +
+			((lp->tx_num_entries * LDC_PACKET_SIZE) - new_tail));
+	diff /= LDC_PACKET_SIZE;
+	mss = lp->mss;
+
+	if (diff * mss < size)
+		return 0;
+
+	return 1;
+}
+
+static struct ldc_packet *data_get_tx_packet(struct ldc_channel *lp,
+					     unsigned long *new_tail)
+{
+	struct ldc_packet *p;
+	unsigned long h, t;
+
+	h = head_for_data(lp);
+	t = tx_advance(lp, lp->tx_tail);
+	if (t == h)
+		return NULL;
+
+	*new_tail = t;
+
+	p = lp->tx_base;
+	return p + (lp->tx_tail / LDC_PACKET_SIZE);
+}
+
+static int set_tx_tail(struct ldc_channel *lp, unsigned long tail)
+{
+	unsigned long orig_tail = lp->tx_tail;
+	int limit = 1000;
+
+	lp->tx_tail = tail;
+	while (limit-- > 0) {
+		unsigned long err;
+
+		err = sun4v_ldc_tx_set_qtail(lp->id, tail);
+		if (!err)
+			return 0;
+
+		if (err != HV_EWOULDBLOCK) {
+			lp->tx_tail = orig_tail;
+			return -EINVAL;
+		}
+		udelay(1);
+	}
+
+	lp->tx_tail = orig_tail;
+	return -EBUSY;
+}
+
+/* This just updates the head value in the hypervisor using
+ * a polling loop with a timeout.  The caller takes care of
+ * upating software state representing the head change, if any.
+ */
+static int __set_rx_head(struct ldc_channel *lp, unsigned long head)
+{
+	int limit = 1000;
+
+	while (limit-- > 0) {
+		unsigned long err;
+
+		err = sun4v_ldc_rx_set_qhead(lp->id, head);
+		if (!err)
+			return 0;
+
+		if (err != HV_EWOULDBLOCK)
+			return -EINVAL;
+
+		udelay(1);
+	}
+
+	return -EBUSY;
+}
+
+static int send_tx_packet(struct ldc_channel *lp,
+			  struct ldc_packet *p,
+			  unsigned long new_tail)
+{
+	BUG_ON(p != (lp->tx_base + (lp->tx_tail / LDC_PACKET_SIZE)));
+
+	return set_tx_tail(lp, new_tail);
+}
+
+static struct ldc_packet *handshake_compose_ctrl(struct ldc_channel *lp,
+						 u8 stype, u8 ctrl,
+						 void *data, int dlen,
+						 unsigned long *new_tail)
+{
+	struct ldc_packet *p = handshake_get_tx_packet(lp, new_tail);
+
+	if (p) {
+		memset(p, 0, sizeof(*p));
+		p->type = LDC_CTRL;
+		p->stype = stype;
+		p->ctrl = ctrl;
+		if (data)
+			memcpy(p->u.u_data, data, dlen);
+	}
+	return p;
+}
+
+static int start_handshake(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	struct ldc_version *ver;
+	unsigned long new_tail;
+
+	ver = &ver_arr[0];
+
+	ldcdbg(HS, "SEND VER INFO maj[%u] min[%u]\n",
+	       ver->major, ver->minor);
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
+				   ver, sizeof(*ver), &new_tail);
+	if (p) {
+		int err = send_tx_packet(lp, p, new_tail);
+		if (!err)
+			lp->flags &= ~LDC_FLAG_RESET;
+		return err;
+	}
+	return -EBUSY;
+}
+
+static int send_version_nack(struct ldc_channel *lp,
+			     u16 major, u16 minor)
+{
+	struct ldc_packet *p;
+	struct ldc_version ver;
+	unsigned long new_tail;
+
+	ver.major = major;
+	ver.minor = minor;
+
+	p = handshake_compose_ctrl(lp, LDC_NACK, LDC_VERS,
+				   &ver, sizeof(ver), &new_tail);
+	if (p) {
+		ldcdbg(HS, "SEND VER NACK maj[%u] min[%u]\n",
+		       ver.major, ver.minor);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_version_ack(struct ldc_channel *lp,
+			    struct ldc_version *vp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_ACK, LDC_VERS,
+				   vp, sizeof(*vp), &new_tail);
+	if (p) {
+		ldcdbg(HS, "SEND VER ACK maj[%u] min[%u]\n",
+		       vp->major, vp->minor);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_rts(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RTS, NULL, 0,
+				   &new_tail);
+	if (p) {
+		p->env = lp->cfg.mode;
+		p->seqid = 0;
+		lp->rcv_nxt = 0;
+
+		ldcdbg(HS, "SEND RTS env[0x%x] seqid[0x%x]\n",
+		       p->env, p->seqid);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_rtr(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RTR, NULL, 0,
+				   &new_tail);
+	if (p) {
+		p->env = lp->cfg.mode;
+		p->seqid = 0;
+
+		ldcdbg(HS, "SEND RTR env[0x%x] seqid[0x%x]\n",
+		       p->env, p->seqid);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_rdx(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RDX, NULL, 0,
+				   &new_tail);
+	if (p) {
+		p->env = 0;
+		p->seqid = ++lp->snd_nxt;
+		p->u.r.ackid = lp->rcv_nxt;
+
+		ldcdbg(HS, "SEND RDX env[0x%x] seqid[0x%x] ackid[0x%x]\n",
+		       p->env, p->seqid, p->u.r.ackid);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_data_nack(struct ldc_channel *lp, struct ldc_packet *data_pkt)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+	int err;
+
+	p = data_get_tx_packet(lp, &new_tail);
+	if (!p)
+		return -EBUSY;
+	memset(p, 0, sizeof(*p));
+	p->type = data_pkt->type;
+	p->stype = LDC_NACK;
+	p->ctrl = data_pkt->ctrl & LDC_CTRL_MSK;
+	p->seqid = lp->snd_nxt + 1;
+	p->u.r.ackid = lp->rcv_nxt;
+
+	ldcdbg(HS, "SEND DATA NACK type[0x%x] ctl[0x%x] seq[0x%x] ack[0x%x]\n",
+	       p->type, p->ctrl, p->seqid, p->u.r.ackid);
+
+	err = send_tx_packet(lp, p, new_tail);
+	if (!err)
+		lp->snd_nxt++;
+
+	return err;
+}
+
+static int ldc_abort(struct ldc_channel *lp)
+{
+	unsigned long hv_err;
+
+	ldcdbg(STATE, "ABORT\n");
+
+	/* We report but do not act upon the hypervisor errors because
+	 * there really isn't much we can do if they fail at this point.
+	 */
+	hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_tx_qconf(%lx,%lx,%lx) failed, err=%lu\n",
+		       lp->id, lp->tx_ra, lp->tx_num_entries, hv_err);
+
+	hv_err = sun4v_ldc_tx_get_state(lp->id,
+					&lp->tx_head,
+					&lp->tx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_tx_get_state(%lx,...) failed, err=%lu\n",
+		       lp->id, hv_err);
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_rx_qconf(%lx,%lx,%lx) failed, err=%lu\n",
+		       lp->id, lp->rx_ra, lp->rx_num_entries, hv_err);
+
+	/* Refetch the RX queue state as well, because we could be invoked
+	 * here in the queue processing context.
+	 */
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_rx_get_state(%lx,...) failed, err=%lu\n",
+		       lp->id, hv_err);
+
+	return -ECONNRESET;
+}
+
+static struct ldc_version *find_by_major(u16 major)
+{
+	struct ldc_version *ret = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ver_arr); i++) {
+		struct ldc_version *v = &ver_arr[i];
+		if (v->major <= major) {
+			ret = v;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int process_ver_info(struct ldc_channel *lp, struct ldc_version *vp)
+{
+	struct ldc_version *vap;
+	int err;
+
+	ldcdbg(HS, "GOT VERSION INFO major[%x] minor[%x]\n",
+	       vp->major, vp->minor);
+
+	if (lp->hs_state == LDC_HS_GOTVERS) {
+		lp->hs_state = LDC_HS_OPEN;
+		memset(&lp->ver, 0, sizeof(lp->ver));
+	}
+
+	vap = find_by_major(vp->major);
+	if (!vap) {
+		err = send_version_nack(lp, 0, 0);
+	} else if (vap->major != vp->major) {
+		err = send_version_nack(lp, vap->major, vap->minor);
+	} else {
+		struct ldc_version ver = *vp;
+		if (ver.minor > vap->minor)
+			ver.minor = vap->minor;
+		err = send_version_ack(lp, &ver);
+		if (!err) {
+			lp->ver = ver;
+			lp->hs_state = LDC_HS_GOTVERS;
+		}
+	}
+	if (err)
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int process_ver_ack(struct ldc_channel *lp, struct ldc_version *vp)
+{
+	ldcdbg(HS, "GOT VERSION ACK major[%x] minor[%x]\n",
+	       vp->major, vp->minor);
+
+	if (lp->hs_state == LDC_HS_GOTVERS) {
+		if (lp->ver.major != vp->major ||
+		    lp->ver.minor != vp->minor)
+			return ldc_abort(lp);
+	} else {
+		lp->ver = *vp;
+		lp->hs_state = LDC_HS_GOTVERS;
+	}
+	if (send_rts(lp))
+		return ldc_abort(lp);
+	return 0;
+}
+
+static int process_ver_nack(struct ldc_channel *lp, struct ldc_version *vp)
+{
+	struct ldc_version *vap;
+
+	if ((vp->major == 0 && vp->minor == 0) ||
+	    !(vap = find_by_major(vp->major))) {
+		return ldc_abort(lp);
+	} else {
+		struct ldc_packet *p;
+		unsigned long new_tail;
+
+		p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
+					   vap, sizeof(*vap),
+					   &new_tail);
+		if (p)
+			return send_tx_packet(lp, p, new_tail);
+		else
+			return ldc_abort(lp);
+	}
+}
+
+static int process_version(struct ldc_channel *lp,
+			   struct ldc_packet *p)
+{
+	struct ldc_version *vp;
+
+	vp = (struct ldc_version *) p->u.u_data;
+
+	switch (p->stype) {
+	case LDC_INFO:
+		return process_ver_info(lp, vp);
+
+	case LDC_ACK:
+		return process_ver_ack(lp, vp);
+
+	case LDC_NACK:
+		return process_ver_nack(lp, vp);
+
+	default:
+		return ldc_abort(lp);
+	}
+}
+
+static int process_rts(struct ldc_channel *lp,
+		       struct ldc_packet *p)
+{
+	ldcdbg(HS, "GOT RTS stype[%x] seqid[%x] env[%x]\n",
+	       p->stype, p->seqid, p->env);
+
+	if (p->stype     != LDC_INFO	   ||
+	    lp->hs_state != LDC_HS_GOTVERS ||
+	    p->env       != lp->cfg.mode)
+		return ldc_abort(lp);
+
+	lp->snd_nxt = p->seqid;
+	lp->rcv_nxt = p->seqid;
+	lp->hs_state = LDC_HS_SENTRTR;
+	if (send_rtr(lp))
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int process_rtr(struct ldc_channel *lp,
+		       struct ldc_packet *p)
+{
+	ldcdbg(HS, "GOT RTR stype[%x] seqid[%x] env[%x]\n",
+	       p->stype, p->seqid, p->env);
+
+	if (p->stype     != LDC_INFO ||
+	    p->env       != lp->cfg.mode)
+		return ldc_abort(lp);
+
+	lp->snd_nxt = p->seqid;
+	lp->hs_state = LDC_HS_COMPLETE;
+	ldc_set_state(lp, LDC_STATE_CONNECTED);
+	send_rdx(lp);
+
+	return LDC_EVENT_UP;
+}
+
+static int rx_seq_ok(struct ldc_channel *lp, u32 seqid)
+{
+	return lp->rcv_nxt + 1 == seqid;
+}
+
+static int process_rdx(struct ldc_channel *lp,
+		       struct ldc_packet *p)
+{
+	ldcdbg(HS, "GOT RDX stype[%x] seqid[%x] env[%x] ackid[%x]\n",
+	       p->stype, p->seqid, p->env, p->u.r.ackid);
+
+	if (p->stype != LDC_INFO ||
+	    !(rx_seq_ok(lp, p->seqid)))
+		return ldc_abort(lp);
+
+	lp->rcv_nxt = p->seqid;
+
+	lp->hs_state = LDC_HS_COMPLETE;
+	ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+	return LDC_EVENT_UP;
+}
+
+static int process_control_frame(struct ldc_channel *lp,
+				 struct ldc_packet *p)
+{
+	switch (p->ctrl) {
+	case LDC_VERS:
+		return process_version(lp, p);
+
+	case LDC_RTS:
+		return process_rts(lp, p);
+
+	case LDC_RTR:
+		return process_rtr(lp, p);
+
+	case LDC_RDX:
+		return process_rdx(lp, p);
+
+	default:
+		return ldc_abort(lp);
+	}
+}
+
+static int process_error_frame(struct ldc_channel *lp,
+			       struct ldc_packet *p)
+{
+	return ldc_abort(lp);
+}
+
+static int process_data_ack(struct ldc_channel *lp,
+			    struct ldc_packet *ack)
+{
+	unsigned long head = lp->tx_acked;
+	u32 ackid = ack->u.r.ackid;
+
+	while (1) {
+		struct ldc_packet *p = lp->tx_base + (head / LDC_PACKET_SIZE);
+
+		head = tx_advance(lp, head);
+
+		if (p->seqid == ackid) {
+			lp->tx_acked = head;
+			return 0;
+		}
+		if (head == lp->tx_tail)
+			return ldc_abort(lp);
+	}
+
+	return 0;
+}
+
+static void send_events(struct ldc_channel *lp, unsigned int event_mask)
+{
+	if (event_mask & LDC_EVENT_RESET)
+		lp->cfg.event(lp->event_arg, LDC_EVENT_RESET);
+	if (event_mask & LDC_EVENT_UP)
+		lp->cfg.event(lp->event_arg, LDC_EVENT_UP);
+	if (event_mask & LDC_EVENT_DATA_READY)
+		lp->cfg.event(lp->event_arg, LDC_EVENT_DATA_READY);
+}
+
+static irqreturn_t ldc_rx(int irq, void *dev_id)
+{
+	struct ldc_channel *lp = dev_id;
+	unsigned long orig_state, hv_err, flags;
+	unsigned int event_mask;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	orig_state = lp->chan_state;
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+
+	ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
+	       orig_state, lp->chan_state, lp->rx_head, lp->rx_tail);
+
+	event_mask = 0;
+
+	if (lp->cfg.mode == LDC_MODE_RAW &&
+	    lp->chan_state == LDC_CHANNEL_UP) {
+		lp->hs_state = LDC_HS_COMPLETE;
+		ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+		event_mask |= LDC_EVENT_UP;
+
+		orig_state = lp->chan_state;
+	}
+
+	/* If we are in reset state, flush the RX queue and ignore
+	 * everything.
+	 */
+	if (lp->flags & LDC_FLAG_RESET) {
+		(void) __set_rx_head(lp, lp->rx_tail);
+		goto out;
+	}
+
+	/* Once we finish the handshake, we let the ldc_read()
+	 * paths do all of the control frame and state management.
+	 * Just trigger the callback.
+	 */
+	if (lp->hs_state == LDC_HS_COMPLETE) {
+handshake_complete:
+		if (lp->chan_state != orig_state) {
+			unsigned int event = LDC_EVENT_RESET;
+
+			if (lp->chan_state == LDC_CHANNEL_UP)
+				event = LDC_EVENT_UP;
+
+			event_mask |= event;
+		}
+		if (lp->rx_head != lp->rx_tail)
+			event_mask |= LDC_EVENT_DATA_READY;
+
+		goto out;
+	}
+
+	if (lp->chan_state != orig_state)
+		goto out;
+
+	while (lp->rx_head != lp->rx_tail) {
+		struct ldc_packet *p;
+		unsigned long new;
+		int err;
+
+		p = lp->rx_base + (lp->rx_head / LDC_PACKET_SIZE);
+
+		switch (p->type) {
+		case LDC_CTRL:
+			err = process_control_frame(lp, p);
+			if (err > 0)
+				event_mask |= err;
+			break;
+
+		case LDC_DATA:
+			event_mask |= LDC_EVENT_DATA_READY;
+			err = 0;
+			break;
+
+		case LDC_ERR:
+			err = process_error_frame(lp, p);
+			break;
+
+		default:
+			err = ldc_abort(lp);
+			break;
+		}
+
+		if (err < 0)
+			break;
+
+		new = lp->rx_head;
+		new += LDC_PACKET_SIZE;
+		if (new == (lp->rx_num_entries * LDC_PACKET_SIZE))
+			new = 0;
+		lp->rx_head = new;
+
+		err = __set_rx_head(lp, new);
+		if (err < 0) {
+			(void) ldc_abort(lp);
+			break;
+		}
+		if (lp->hs_state == LDC_HS_COMPLETE)
+			goto handshake_complete;
+	}
+
+out:
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	send_events(lp, event_mask);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ldc_tx(int irq, void *dev_id)
+{
+	struct ldc_channel *lp = dev_id;
+	unsigned long flags, hv_err, orig_state;
+	unsigned int event_mask = 0;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	orig_state = lp->chan_state;
+	hv_err = sun4v_ldc_tx_get_state(lp->id,
+					&lp->tx_head,
+					&lp->tx_tail,
+					&lp->chan_state);
+
+	ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
+	       orig_state, lp->chan_state, lp->tx_head, lp->tx_tail);
+
+	if (lp->cfg.mode == LDC_MODE_RAW &&
+	    lp->chan_state == LDC_CHANNEL_UP) {
+		lp->hs_state = LDC_HS_COMPLETE;
+		ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+		event_mask |= LDC_EVENT_UP;
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	send_events(lp, event_mask);
+
+	return IRQ_HANDLED;
+}
+
+/* XXX ldc_alloc() and ldc_free() needs to run under a mutex so
+ * XXX that addition and removal from the ldc_channel_list has
+ * XXX atomicity, otherwise the __ldc_channel_exists() check is
+ * XXX totally pointless as another thread can slip into ldc_alloc()
+ * XXX and add a channel with the same ID.  There also needs to be
+ * XXX a spinlock for ldc_channel_list.
+ */
+static HLIST_HEAD(ldc_channel_list);
+
+static int __ldc_channel_exists(unsigned long id)
+{
+	struct ldc_channel *lp;
+	struct hlist_node *n;
+
+	hlist_for_each_entry(lp, n, &ldc_channel_list, list) {
+		if (lp->id == id)
+			return 1;
+	}
+	return 0;
+}
+
+static int alloc_queue(const char *name, unsigned long num_entries,
+		       struct ldc_packet **base, unsigned long *ra)
+{
+	unsigned long size, order;
+	void *q;
+
+	size = num_entries * LDC_PACKET_SIZE;
+	order = get_order(size);
+
+	q = (void *) __get_free_pages(GFP_KERNEL, order);
+	if (!q) {
+		printk(KERN_ERR PFX "Alloc of %s queue failed with "
+		       "size=%lu order=%lu\n", name, size, order);
+		return -ENOMEM;
+	}
+
+	memset(q, 0, PAGE_SIZE << order);
+
+	*base = q;
+	*ra = __pa(q);
+
+	return 0;
+}
+
+static void free_queue(unsigned long num_entries, struct ldc_packet *q)
+{
+	unsigned long size, order;
+
+	if (!q)
+		return;
+
+	size = num_entries * LDC_PACKET_SIZE;
+	order = get_order(size);
+
+	free_pages((unsigned long)q, order);
+}
+
+/* XXX Make this configurable... XXX */
+#define LDC_IOTABLE_SIZE	(8 * 1024)
+
+static int ldc_iommu_init(struct ldc_channel *lp)
+{
+	unsigned long sz, num_tsb_entries, tsbsize, order;
+	struct ldc_iommu *iommu = &lp->iommu;
+	struct ldc_mtable_entry *table;
+	unsigned long hv_err;
+	int err;
+
+	num_tsb_entries = LDC_IOTABLE_SIZE;
+	tsbsize = num_tsb_entries * sizeof(struct ldc_mtable_entry);
+
+	spin_lock_init(&iommu->lock);
+
+	sz = num_tsb_entries / 8;
+	sz = (sz + 7UL) & ~7UL;
+	iommu->arena.map = kzalloc(sz, GFP_KERNEL);
+	if (!iommu->arena.map) {
+		printk(KERN_ERR PFX "Alloc of arena map failed, sz=%lu\n", sz);
+		return -ENOMEM;
+	}
+
+	iommu->arena.limit = num_tsb_entries;
+
+	order = get_order(tsbsize);
+
+	table = (struct ldc_mtable_entry *)
+		__get_free_pages(GFP_KERNEL, order);
+	err = -ENOMEM;
+	if (!table) {
+		printk(KERN_ERR PFX "Alloc of MTE table failed, "
+		       "size=%lu order=%lu\n", tsbsize, order);
+		goto out_free_map;
+	}
+
+	memset(table, 0, PAGE_SIZE << order);
+
+	iommu->page_table = table;
+
+	hv_err = sun4v_ldc_set_map_table(lp->id, __pa(table),
+					 num_tsb_entries);
+	err = -EINVAL;
+	if (hv_err)
+		goto out_free_table;
+
+	return 0;
+
+out_free_table:
+	free_pages((unsigned long) table, order);
+	iommu->page_table = NULL;
+
+out_free_map:
+	kfree(iommu->arena.map);
+	iommu->arena.map = NULL;
+
+	return err;
+}
+
+static void ldc_iommu_release(struct ldc_channel *lp)
+{
+	struct ldc_iommu *iommu = &lp->iommu;
+	unsigned long num_tsb_entries, tsbsize, order;
+
+	(void) sun4v_ldc_set_map_table(lp->id, 0, 0);
+
+	num_tsb_entries = iommu->arena.limit;
+	tsbsize = num_tsb_entries * sizeof(struct ldc_mtable_entry);
+	order = get_order(tsbsize);
+
+	free_pages((unsigned long) iommu->page_table, order);
+	iommu->page_table = NULL;
+
+	kfree(iommu->arena.map);
+	iommu->arena.map = NULL;
+}
+
+struct ldc_channel *ldc_alloc(unsigned long id,
+			      const struct ldc_channel_config *cfgp,
+			      void *event_arg)
+{
+	struct ldc_channel *lp;
+	const struct ldc_mode_ops *mops;
+	unsigned long dummy1, dummy2, hv_err;
+	u8 mss, *mssbuf;
+	int err;
+
+	err = -ENODEV;
+	if (!ldom_domaining_enabled)
+		goto out_err;
+
+	err = -EINVAL;
+	if (!cfgp)
+		goto out_err;
+
+	switch (cfgp->mode) {
+	case LDC_MODE_RAW:
+		mops = &raw_ops;
+		mss = LDC_PACKET_SIZE;
+		break;
+
+	case LDC_MODE_UNRELIABLE:
+		mops = &nonraw_ops;
+		mss = LDC_PACKET_SIZE - 8;
+		break;
+
+	case LDC_MODE_STREAM:
+		mops = &stream_ops;
+		mss = LDC_PACKET_SIZE - 8 - 8;
+		break;
+
+	default:
+		goto out_err;
+	}
+
+	if (!cfgp->event || !event_arg || !cfgp->rx_irq || !cfgp->tx_irq)
+		goto out_err;
+
+	hv_err = sun4v_ldc_tx_qinfo(id, &dummy1, &dummy2);
+	err = -ENODEV;
+	if (hv_err == HV_ECHANNEL)
+		goto out_err;
+
+	err = -EEXIST;
+	if (__ldc_channel_exists(id))
+		goto out_err;
+
+	mssbuf = NULL;
+
+	lp = kzalloc(sizeof(*lp), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!lp)
+		goto out_err;
+
+	spin_lock_init(&lp->lock);
+
+	lp->id = id;
+
+	err = ldc_iommu_init(lp);
+	if (err)
+		goto out_free_ldc;
+
+	lp->mops = mops;
+	lp->mss = mss;
+
+	lp->cfg = *cfgp;
+	if (!lp->cfg.mtu)
+		lp->cfg.mtu = LDC_DEFAULT_MTU;
+
+	if (lp->cfg.mode == LDC_MODE_STREAM) {
+		mssbuf = kzalloc(lp->cfg.mtu, GFP_KERNEL);
+		if (!mssbuf) {
+			err = -ENOMEM;
+			goto out_free_iommu;
+		}
+		lp->mssbuf = mssbuf;
+	}
+
+	lp->event_arg = event_arg;
+
+	/* XXX allow setting via ldc_channel_config to override defaults
+	 * XXX or use some formula based upon mtu
+	 */
+	lp->tx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
+	lp->rx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
+
+	err = alloc_queue("TX", lp->tx_num_entries,
+			  &lp->tx_base, &lp->tx_ra);
+	if (err)
+		goto out_free_mssbuf;
+
+	err = alloc_queue("RX", lp->rx_num_entries,
+			  &lp->rx_base, &lp->rx_ra);
+	if (err)
+		goto out_free_txq;
+
+	lp->flags |= LDC_FLAG_ALLOCED_QUEUES;
+
+	lp->hs_state = LDC_HS_CLOSED;
+	ldc_set_state(lp, LDC_STATE_INIT);
+
+	INIT_HLIST_NODE(&lp->list);
+	hlist_add_head(&lp->list, &ldc_channel_list);
+
+	INIT_HLIST_HEAD(&lp->mh_list);
+
+	return lp;
+
+out_free_txq:
+	free_queue(lp->tx_num_entries, lp->tx_base);
+
+out_free_mssbuf:
+	if (mssbuf)
+		kfree(mssbuf);
+
+out_free_iommu:
+	ldc_iommu_release(lp);
+
+out_free_ldc:
+	kfree(lp);
+
+out_err:
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(ldc_alloc);
+
+void ldc_free(struct ldc_channel *lp)
+{
+	if (lp->flags & LDC_FLAG_REGISTERED_IRQS) {
+		free_irq(lp->cfg.rx_irq, lp);
+		free_irq(lp->cfg.tx_irq, lp);
+	}
+
+	if (lp->flags & LDC_FLAG_REGISTERED_QUEUES) {
+		sun4v_ldc_tx_qconf(lp->id, 0, 0);
+		sun4v_ldc_rx_qconf(lp->id, 0, 0);
+		lp->flags &= ~LDC_FLAG_REGISTERED_QUEUES;
+	}
+	if (lp->flags & LDC_FLAG_ALLOCED_QUEUES) {
+		free_queue(lp->tx_num_entries, lp->tx_base);
+		free_queue(lp->rx_num_entries, lp->rx_base);
+		lp->flags &= ~LDC_FLAG_ALLOCED_QUEUES;
+	}
+
+	hlist_del(&lp->list);
+
+	if (lp->mssbuf)
+		kfree(lp->mssbuf);
+
+	ldc_iommu_release(lp);
+
+	kfree(lp);
+}
+EXPORT_SYMBOL(ldc_free);
+
+/* Bind the channel.  This registers the LDC queues with
+ * the hypervisor and puts the channel into a pseudo-listening
+ * state.  This does not initiate a handshake, ldc_connect() does
+ * that.
+ */
+int ldc_bind(struct ldc_channel *lp, const char *name)
+{
+	unsigned long hv_err, flags;
+	int err = -EINVAL;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (!name)
+		goto out_err;
+
+	if (lp->state != LDC_STATE_INIT)
+		goto out_err;
+
+	snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
+	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
+
+	err = request_irq(lp->cfg.rx_irq, ldc_rx,
+			  IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+			  lp->rx_irq_name, lp);
+	if (err)
+		goto out_err;
+
+	err = request_irq(lp->cfg.tx_irq, ldc_tx,
+			  IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+			  lp->tx_irq_name, lp);
+	if (err)
+		goto out_free_rx_irq;
+
+
+	lp->flags |= LDC_FLAG_REGISTERED_IRQS;
+
+	err = -ENODEV;
+	hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_free_tx_irq;
+
+	hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+	if (hv_err)
+		goto out_free_tx_irq;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_unmap_tx;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+	if (hv_err)
+		goto out_unmap_tx;
+
+	lp->flags |= LDC_FLAG_REGISTERED_QUEUES;
+
+	hv_err = sun4v_ldc_tx_get_state(lp->id,
+					&lp->tx_head,
+					&lp->tx_tail,
+					&lp->chan_state);
+	err = -EBUSY;
+	if (hv_err)
+		goto out_unmap_rx;
+
+	lp->tx_acked = lp->tx_head;
+
+	lp->hs_state = LDC_HS_OPEN;
+	ldc_set_state(lp, LDC_STATE_BOUND);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return 0;
+
+out_unmap_rx:
+	lp->flags &= ~LDC_FLAG_REGISTERED_QUEUES;
+	sun4v_ldc_rx_qconf(lp->id, 0, 0);
+
+out_unmap_tx:
+	sun4v_ldc_tx_qconf(lp->id, 0, 0);
+
+out_free_tx_irq:
+	lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
+	free_irq(lp->cfg.tx_irq, lp);
+
+out_free_rx_irq:
+	free_irq(lp->cfg.rx_irq, lp);
+
+out_err:
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_bind);
+
+int ldc_connect(struct ldc_channel *lp)
+{
+	unsigned long flags;
+	int err;
+
+	if (lp->cfg.mode == LDC_MODE_RAW)
+		return -EINVAL;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
+	    !(lp->flags & LDC_FLAG_REGISTERED_QUEUES) ||
+	    lp->hs_state != LDC_HS_OPEN)
+		err = -EINVAL;
+	else
+		err = start_handshake(lp);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_connect);
+
+int ldc_disconnect(struct ldc_channel *lp)
+{
+	unsigned long hv_err, flags;
+	int err;
+
+	if (lp->cfg.mode == LDC_MODE_RAW)
+		return -EINVAL;
+
+	if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
+	    !(lp->flags & LDC_FLAG_REGISTERED_QUEUES))
+		return -EINVAL;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	err = -ENODEV;
+	hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_err;
+
+	hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+	if (hv_err)
+		goto out_err;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_err;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+	if (hv_err)
+		goto out_err;
+
+	ldc_set_state(lp, LDC_STATE_BOUND);
+	lp->hs_state = LDC_HS_OPEN;
+	lp->flags |= LDC_FLAG_RESET;
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return 0;
+
+out_err:
+	sun4v_ldc_tx_qconf(lp->id, 0, 0);
+	sun4v_ldc_rx_qconf(lp->id, 0, 0);
+	free_irq(lp->cfg.tx_irq, lp);
+	free_irq(lp->cfg.rx_irq, lp);
+	lp->flags &= ~(LDC_FLAG_REGISTERED_IRQS |
+		       LDC_FLAG_REGISTERED_QUEUES);
+	ldc_set_state(lp, LDC_STATE_INIT);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_disconnect);
+
+int ldc_state(struct ldc_channel *lp)
+{
+	return lp->state;
+}
+EXPORT_SYMBOL(ldc_state);
+
+static int write_raw(struct ldc_channel *lp, const void *buf, unsigned int size)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+	int err;
+
+	if (size > LDC_PACKET_SIZE)
+		return -EMSGSIZE;
+
+	p = data_get_tx_packet(lp, &new_tail);
+	if (!p)
+		return -EAGAIN;
+
+	memcpy(p, buf, size);
+
+	err = send_tx_packet(lp, p, new_tail);
+	if (!err)
+		err = size;
+
+	return err;
+}
+
+static int read_raw(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	struct ldc_packet *p;
+	unsigned long hv_err, new;
+	int err;
+
+	if (size < LDC_PACKET_SIZE)
+		return -EINVAL;
+
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		return ldc_abort(lp);
+
+	if (lp->chan_state == LDC_CHANNEL_DOWN ||
+	    lp->chan_state == LDC_CHANNEL_RESETTING)
+		return -ECONNRESET;
+
+	if (lp->rx_head == lp->rx_tail)
+		return 0;
+
+	p = lp->rx_base + (lp->rx_head / LDC_PACKET_SIZE);
+	memcpy(buf, p, LDC_PACKET_SIZE);
+
+	new = rx_advance(lp, lp->rx_head);
+	lp->rx_head = new;
+
+	err = __set_rx_head(lp, new);
+	if (err < 0)
+		err = -ECONNRESET;
+	else
+		err = LDC_PACKET_SIZE;
+
+	return err;
+}
+
+static const struct ldc_mode_ops raw_ops = {
+	.write		=	write_raw,
+	.read		=	read_raw,
+};
+
+static int write_nonraw(struct ldc_channel *lp, const void *buf,
+			unsigned int size)
+{
+	unsigned long hv_err, tail;
+	unsigned int copied;
+	u32 seq;
+	int err;
+
+	hv_err = sun4v_ldc_tx_get_state(lp->id, &lp->tx_head, &lp->tx_tail,
+					&lp->chan_state);
+	if (unlikely(hv_err))
+		return -EBUSY;
+
+	if (unlikely(lp->chan_state != LDC_CHANNEL_UP))
+		return ldc_abort(lp);
+
+	if (!tx_has_space_for(lp, size))
+		return -EAGAIN;
+
+	seq = lp->snd_nxt;
+	copied = 0;
+	tail = lp->tx_tail;
+	while (copied < size) {
+		struct ldc_packet *p = lp->tx_base + (tail / LDC_PACKET_SIZE);
+		u8 *data = ((lp->cfg.mode == LDC_MODE_UNRELIABLE) ?
+			    p->u.u_data :
+			    p->u.r.r_data);
+		int data_len;
+
+		p->type = LDC_DATA;
+		p->stype = LDC_INFO;
+		p->ctrl = 0;
+
+		data_len = size - copied;
+		if (data_len > lp->mss)
+			data_len = lp->mss;
+
+		BUG_ON(data_len > LDC_LEN);
+
+		p->env = (data_len |
+			  (copied == 0 ? LDC_START : 0) |
+			  (data_len == size - copied ? LDC_STOP : 0));
+
+		p->seqid = ++seq;
+
+		ldcdbg(DATA, "SENT DATA [%02x:%02x:%02x:%02x:%08x]\n",
+		       p->type,
+		       p->stype,
+		       p->ctrl,
+		       p->env,
+		       p->seqid);
+
+		memcpy(data, buf, data_len);
+		buf += data_len;
+		copied += data_len;
+
+		tail = tx_advance(lp, tail);
+	}
+
+	err = set_tx_tail(lp, tail);
+	if (!err) {
+		lp->snd_nxt = seq;
+		err = size;
+	}
+
+	return err;
+}
+
+static int rx_bad_seq(struct ldc_channel *lp, struct ldc_packet *p,
+		      struct ldc_packet *first_frag)
+{
+	int err;
+
+	if (first_frag)
+		lp->rcv_nxt = first_frag->seqid - 1;
+
+	err = send_data_nack(lp, p);
+	if (err)
+		return err;
+
+	err = __set_rx_head(lp, lp->rx_tail);
+	if (err < 0)
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int data_ack_nack(struct ldc_channel *lp, struct ldc_packet *p)
+{
+	if (p->stype & LDC_ACK) {
+		int err = process_data_ack(lp, p);
+		if (err)
+			return err;
+	}
+	if (p->stype & LDC_NACK)
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int rx_data_wait(struct ldc_channel *lp, unsigned long cur_head)
+{
+	unsigned long dummy;
+	int limit = 1000;
+
+	ldcdbg(DATA, "DATA WAIT cur_head[%lx] rx_head[%lx] rx_tail[%lx]\n",
+	       cur_head, lp->rx_head, lp->rx_tail);
+	while (limit-- > 0) {
+		unsigned long hv_err;
+
+		hv_err = sun4v_ldc_rx_get_state(lp->id,
+						&dummy,
+						&lp->rx_tail,
+						&lp->chan_state);
+		if (hv_err)
+			return ldc_abort(lp);
+
+		if (lp->chan_state == LDC_CHANNEL_DOWN ||
+		    lp->chan_state == LDC_CHANNEL_RESETTING)
+			return -ECONNRESET;
+
+		if (cur_head != lp->rx_tail) {
+			ldcdbg(DATA, "DATA WAIT DONE "
+			       "head[%lx] tail[%lx] chan_state[%lx]\n",
+			       dummy, lp->rx_tail, lp->chan_state);
+			return 0;
+		}
+
+		udelay(1);
+	}
+	return -EAGAIN;
+}
+
+static int rx_set_head(struct ldc_channel *lp, unsigned long head)
+{
+	int err = __set_rx_head(lp, head);
+
+	if (err < 0)
+		return ldc_abort(lp);
+
+	lp->rx_head = head;
+	return 0;
+}
+
+static void send_data_ack(struct ldc_channel *lp)
+{
+	unsigned long new_tail;
+	struct ldc_packet *p;
+
+	p = data_get_tx_packet(lp, &new_tail);
+	if (likely(p)) {
+		int err;
+
+		memset(p, 0, sizeof(*p));
+		p->type = LDC_DATA;
+		p->stype = LDC_ACK;
+		p->ctrl = 0;
+		p->seqid = lp->snd_nxt + 1;
+		p->u.r.ackid = lp->rcv_nxt;
+
+		err = send_tx_packet(lp, p, new_tail);
+		if (!err)
+			lp->snd_nxt++;
+	}
+}
+
+static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	struct ldc_packet *first_frag;
+	unsigned long hv_err, new;
+	int err, copied;
+
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		return ldc_abort(lp);
+
+	if (lp->chan_state == LDC_CHANNEL_DOWN ||
+	    lp->chan_state == LDC_CHANNEL_RESETTING)
+		return -ECONNRESET;
+
+	if (lp->rx_head == lp->rx_tail)
+		return 0;
+
+	first_frag = NULL;
+	copied = err = 0;
+	new = lp->rx_head;
+	while (1) {
+		struct ldc_packet *p;
+		int pkt_len;
+
+		BUG_ON(new == lp->rx_tail);
+		p = lp->rx_base + (new / LDC_PACKET_SIZE);
+
+		ldcdbg(RX, "RX read pkt[%02x:%02x:%02x:%02x:%08x:%08x] "
+		       "rcv_nxt[%08x]\n",
+		       p->type,
+		       p->stype,
+		       p->ctrl,
+		       p->env,
+		       p->seqid,
+		       p->u.r.ackid,
+		       lp->rcv_nxt);
+
+		if (unlikely(!rx_seq_ok(lp, p->seqid))) {
+			err = rx_bad_seq(lp, p, first_frag);
+			copied = 0;
+			break;
+		}
+
+		if (p->type & LDC_CTRL) {
+			err = process_control_frame(lp, p);
+			if (err < 0)
+				break;
+			err = 0;
+		}
+
+		lp->rcv_nxt = p->seqid;
+
+		if (!(p->type & LDC_DATA)) {
+			new = rx_advance(lp, new);
+			goto no_data;
+		}
+		if (p->stype & (LDC_ACK | LDC_NACK)) {
+			err = data_ack_nack(lp, p);
+			if (err)
+				break;
+		}
+		if (!(p->stype & LDC_INFO)) {
+			new = rx_advance(lp, new);
+			err = rx_set_head(lp, new);
+			if (err)
+				break;
+			goto no_data;
+		}
+
+		pkt_len = p->env & LDC_LEN;
+
+		/* Every initial packet starts with the START bit set.
+		 *
+		 * Singleton packets will have both START+STOP set.
+		 *
+		 * Fragments will have START set in the first frame, STOP
+		 * set in the last frame, and neither bit set in middle
+		 * frames of the packet.
+		 *
+		 * Therefore if we are at the beginning of a packet and
+		 * we don't see START, or we are in the middle of a fragmented
+		 * packet and do see START, we are unsynchronized and should
+		 * flush the RX queue.
+		 */
+		if ((first_frag == NULL && !(p->env & LDC_START)) ||
+		    (first_frag != NULL &&  (p->env & LDC_START))) {
+			if (!first_frag)
+				new = rx_advance(lp, new);
+
+			err = rx_set_head(lp, new);
+			if (err)
+				break;
+
+			if (!first_frag)
+				goto no_data;
+		}
+		if (!first_frag)
+			first_frag = p;
+
+		if (pkt_len > size - copied) {
+			/* User didn't give us a big enough buffer,
+			 * what to do?  This is a pretty serious error.
+			 *
+			 * Since we haven't updated the RX ring head to
+			 * consume any of the packets, signal the error
+			 * to the user and just leave the RX ring alone.
+			 *
+			 * This seems the best behavior because this allows
+			 * a user of the LDC layer to start with a small
+			 * RX buffer for ldc_read() calls and use -EMSGSIZE
+			 * as a cue to enlarge it's read buffer.
+			 */
+			err = -EMSGSIZE;
+			break;
+		}
+
+		/* Ok, we are gonna eat this one.  */
+		new = rx_advance(lp, new);
+
+		memcpy(buf,
+		       (lp->cfg.mode == LDC_MODE_UNRELIABLE ?
+			p->u.u_data : p->u.r.r_data), pkt_len);
+		buf += pkt_len;
+		copied += pkt_len;
+
+		if (p->env & LDC_STOP)
+			break;
+
+no_data:
+		if (new == lp->rx_tail) {
+			err = rx_data_wait(lp, new);
+			if (err)
+				break;
+		}
+	}
+
+	if (!err)
+		err = rx_set_head(lp, new);
+
+	if (err && first_frag)
+		lp->rcv_nxt = first_frag->seqid - 1;
+
+	if (!err) {
+		err = copied;
+		if (err > 0 && lp->cfg.mode != LDC_MODE_UNRELIABLE)
+			send_data_ack(lp);
+	}
+
+	return err;
+}
+
+static const struct ldc_mode_ops nonraw_ops = {
+	.write		=	write_nonraw,
+	.read		=	read_nonraw,
+};
+
+static int write_stream(struct ldc_channel *lp, const void *buf,
+			unsigned int size)
+{
+	if (size > lp->cfg.mtu)
+		size = lp->cfg.mtu;
+	return write_nonraw(lp, buf, size);
+}
+
+static int read_stream(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	if (!lp->mssbuf_len) {
+		int err = read_nonraw(lp, lp->mssbuf, lp->cfg.mtu);
+		if (err < 0)
+			return err;
+
+		lp->mssbuf_len = err;
+		lp->mssbuf_off = 0;
+	}
+
+	if (size > lp->mssbuf_len)
+		size = lp->mssbuf_len;
+	memcpy(buf, lp->mssbuf + lp->mssbuf_off, size);
+
+	lp->mssbuf_off += size;
+	lp->mssbuf_len -= size;
+
+	return size;
+}
+
+static const struct ldc_mode_ops stream_ops = {
+	.write		=	write_stream,
+	.read		=	read_stream,
+};
+
+int ldc_write(struct ldc_channel *lp, const void *buf, unsigned int size)
+{
+	unsigned long flags;
+	int err;
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!size)
+		return 0;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (lp->hs_state != LDC_HS_COMPLETE)
+		err = -ENOTCONN;
+	else
+		err = lp->mops->write(lp, buf, size);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_write);
+
+int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	unsigned long flags;
+	int err;
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!size)
+		return 0;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (lp->hs_state != LDC_HS_COMPLETE)
+		err = -ENOTCONN;
+	else
+		err = lp->mops->read(lp, buf, size);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_read);
+
+static long arena_alloc(struct ldc_iommu *iommu, unsigned long npages)
+{
+	struct iommu_arena *arena = &iommu->arena;
+	unsigned long n, i, start, end, limit;
+	int pass;
+
+	limit = arena->limit;
+	start = arena->hint;
+	pass = 0;
+
+again:
+	n = find_next_zero_bit(arena->map, limit, start);
+	end = n + npages;
+	if (unlikely(end >= limit)) {
+		if (likely(pass < 1)) {
+			limit = start;
+			start = 0;
+			pass++;
+			goto again;
+		} else {
+			/* Scanned the whole thing, give up. */
+			return -1;
+		}
+	}
+
+	for (i = n; i < end; i++) {
+		if (test_bit(i, arena->map)) {
+			start = i + 1;
+			goto again;
+		}
+	}
+
+	for (i = n; i < end; i++)
+		__set_bit(i, arena->map);
+
+	arena->hint = end;
+
+	return n;
+}
+
+#define COOKIE_PGSZ_CODE	0xf000000000000000ULL
+#define COOKIE_PGSZ_CODE_SHIFT	60ULL
+
+static u64 pagesize_code(void)
+{
+	switch (PAGE_SIZE) {
+	default:
+	case (8ULL * 1024ULL):
+		return 0;
+	case (64ULL * 1024ULL):
+		return 1;
+	case (512ULL * 1024ULL):
+		return 2;
+	case (4ULL * 1024ULL * 1024ULL):
+		return 3;
+	case (32ULL * 1024ULL * 1024ULL):
+		return 4;
+	case (256ULL * 1024ULL * 1024ULL):
+		return 5;
+	}
+}
+
+static u64 make_cookie(u64 index, u64 pgsz_code, u64 page_offset)
+{
+	return ((pgsz_code << COOKIE_PGSZ_CODE_SHIFT) |
+		(index << PAGE_SHIFT) |
+		page_offset);
+}
+
+static u64 cookie_to_index(u64 cookie, unsigned long *shift)
+{
+	u64 szcode = cookie >> COOKIE_PGSZ_CODE_SHIFT;
+
+	cookie &= ~COOKIE_PGSZ_CODE;
+
+	*shift = szcode * 3;
+
+	return (cookie >> (13ULL + (szcode * 3ULL)));
+}
+
+static struct ldc_mtable_entry *alloc_npages(struct ldc_iommu *iommu,
+					     unsigned long npages)
+{
+	long entry;
+
+	entry = arena_alloc(iommu, npages);
+	if (unlikely(entry < 0))
+		return NULL;
+
+	return iommu->page_table + entry;
+}
+
+static u64 perm_to_mte(unsigned int map_perm)
+{
+	u64 mte_base;
+
+	mte_base = pagesize_code();
+
+	if (map_perm & LDC_MAP_SHADOW) {
+		if (map_perm & LDC_MAP_R)
+			mte_base |= LDC_MTE_COPY_R;
+		if (map_perm & LDC_MAP_W)
+			mte_base |= LDC_MTE_COPY_W;
+	}
+	if (map_perm & LDC_MAP_DIRECT) {
+		if (map_perm & LDC_MAP_R)
+			mte_base |= LDC_MTE_READ;
+		if (map_perm & LDC_MAP_W)
+			mte_base |= LDC_MTE_WRITE;
+		if (map_perm & LDC_MAP_X)
+			mte_base |= LDC_MTE_EXEC;
+	}
+	if (map_perm & LDC_MAP_IO) {
+		if (map_perm & LDC_MAP_R)
+			mte_base |= LDC_MTE_IOMMU_R;
+		if (map_perm & LDC_MAP_W)
+			mte_base |= LDC_MTE_IOMMU_W;
+	}
+
+	return mte_base;
+}
+
+static int pages_in_region(unsigned long base, long len)
+{
+	int count = 0;
+
+	do {
+		unsigned long new = (base + PAGE_SIZE) & PAGE_MASK;
+
+		len -= (new - base);
+		base = new;
+		count++;
+	} while (len > 0);
+
+	return count;
+}
+
+struct cookie_state {
+	struct ldc_mtable_entry		*page_table;
+	struct ldc_trans_cookie		*cookies;
+	u64				mte_base;
+	u64				prev_cookie;
+	u32				pte_idx;
+	u32				nc;
+};
+
+static void fill_cookies(struct cookie_state *sp, unsigned long pa,
+			 unsigned long off, unsigned long len)
+{
+	do {
+		unsigned long tlen, new = pa + PAGE_SIZE;
+		u64 this_cookie;
+
+		sp->page_table[sp->pte_idx].mte = sp->mte_base | pa;
+
+		tlen = PAGE_SIZE;
+		if (off)
+			tlen = PAGE_SIZE - off;
+		if (tlen > len)
+			tlen = len;
+
+		this_cookie = make_cookie(sp->pte_idx,
+					  pagesize_code(), off);
+
+		off = 0;
+
+		if (this_cookie == sp->prev_cookie) {
+			sp->cookies[sp->nc - 1].cookie_size += tlen;
+		} else {
+			sp->cookies[sp->nc].cookie_addr = this_cookie;
+			sp->cookies[sp->nc].cookie_size = tlen;
+			sp->nc++;
+		}
+		sp->prev_cookie = this_cookie + tlen;
+
+		sp->pte_idx++;
+
+		len -= tlen;
+		pa = new;
+	} while (len > 0);
+}
+
+static int sg_count_one(struct scatterlist *sg)
+{
+	unsigned long base = page_to_pfn(sg->page) << PAGE_SHIFT;
+	long len = sg->length;
+
+	if ((sg->offset | len) & (8UL - 1))
+		return -EFAULT;
+
+	return pages_in_region(base + sg->offset, len);
+}
+
+static int sg_count_pages(struct scatterlist *sg, int num_sg)
+{
+	int count;
+	int i;
+
+	count = 0;
+	for (i = 0; i < num_sg; i++) {
+		int err = sg_count_one(sg + i);
+		if (err < 0)
+			return err;
+		count += err;
+	}
+
+	return count;
+}
+
+int ldc_map_sg(struct ldc_channel *lp,
+	       struct scatterlist *sg, int num_sg,
+	       struct ldc_trans_cookie *cookies, int ncookies,
+	       unsigned int map_perm)
+{
+	unsigned long i, npages, flags;
+	struct ldc_mtable_entry *base;
+	struct cookie_state state;
+	struct ldc_iommu *iommu;
+	int err;
+
+	if (map_perm & ~LDC_MAP_ALL)
+		return -EINVAL;
+
+	err = sg_count_pages(sg, num_sg);
+	if (err < 0)
+		return err;
+
+	npages = err;
+	if (err > ncookies)
+		return -EMSGSIZE;
+
+	iommu = &lp->iommu;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	base = alloc_npages(iommu, npages);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	if (!base)
+		return -ENOMEM;
+
+	state.page_table = iommu->page_table;
+	state.cookies = cookies;
+	state.mte_base = perm_to_mte(map_perm);
+	state.prev_cookie = ~(u64)0;
+	state.pte_idx = (base - iommu->page_table);
+	state.nc = 0;
+
+	for (i = 0; i < num_sg; i++)
+		fill_cookies(&state, page_to_pfn(sg[i].page) << PAGE_SHIFT,
+			     sg[i].offset, sg[i].length);
+
+	return state.nc;
+}
+EXPORT_SYMBOL(ldc_map_sg);
+
+int ldc_map_single(struct ldc_channel *lp,
+		   void *buf, unsigned int len,
+		   struct ldc_trans_cookie *cookies, int ncookies,
+		   unsigned int map_perm)
+{
+	unsigned long npages, pa, flags;
+	struct ldc_mtable_entry *base;
+	struct cookie_state state;
+	struct ldc_iommu *iommu;
+
+	if ((map_perm & ~LDC_MAP_ALL) || (ncookies < 1))
+		return -EINVAL;
+
+	pa = __pa(buf);
+	if ((pa | len) & (8UL - 1))
+		return -EFAULT;
+
+	npages = pages_in_region(pa, len);
+
+	iommu = &lp->iommu;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	base = alloc_npages(iommu, npages);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	if (!base)
+		return -ENOMEM;
+
+	state.page_table = iommu->page_table;
+	state.cookies = cookies;
+	state.mte_base = perm_to_mte(map_perm);
+	state.prev_cookie = ~(u64)0;
+	state.pte_idx = (base - iommu->page_table);
+	state.nc = 0;
+	fill_cookies(&state, (pa & PAGE_MASK), (pa & ~PAGE_MASK), len);
+	BUG_ON(state.nc != 1);
+
+	return state.nc;
+}
+EXPORT_SYMBOL(ldc_map_single);
+
+static void free_npages(unsigned long id, struct ldc_iommu *iommu,
+			u64 cookie, u64 size)
+{
+	struct iommu_arena *arena = &iommu->arena;
+	unsigned long i, shift, index, npages;
+	struct ldc_mtable_entry *base;
+
+	npages = PAGE_ALIGN(((cookie & ~PAGE_MASK) + size)) >> PAGE_SHIFT;
+	index = cookie_to_index(cookie, &shift);
+	base = iommu->page_table + index;
+
+	BUG_ON(index > arena->limit ||
+	       (index + npages) > arena->limit);
+
+	for (i = 0; i < npages; i++) {
+		if (base->cookie)
+			sun4v_ldc_revoke(id, cookie + (i << shift),
+					 base->cookie);
+		base->mte = 0;
+		__clear_bit(index + i, arena->map);
+	}
+}
+
+void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+	       int ncookies)
+{
+	struct ldc_iommu *iommu = &lp->iommu;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	for (i = 0; i < ncookies; i++) {
+		u64 addr = cookies[i].cookie_addr;
+		u64 size = cookies[i].cookie_size;
+
+		free_npages(lp->id, iommu, addr, size);
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+EXPORT_SYMBOL(ldc_unmap);
+
+int ldc_copy(struct ldc_channel *lp, int copy_dir,
+	     void *buf, unsigned int len, unsigned long offset,
+	     struct ldc_trans_cookie *cookies, int ncookies)
+{
+	unsigned int orig_len;
+	unsigned long ra;
+	int i;
+
+	if (copy_dir != LDC_COPY_IN && copy_dir != LDC_COPY_OUT) {
+		printk(KERN_ERR PFX "ldc_copy: ID[%lu] Bad copy_dir[%d]\n",
+		       lp->id, copy_dir);
+		return -EINVAL;
+	}
+
+	ra = __pa(buf);
+	if ((ra | len | offset) & (8UL - 1)) {
+		printk(KERN_ERR PFX "ldc_copy: ID[%lu] Unaligned buffer "
+		       "ra[%lx] len[%x] offset[%lx]\n",
+		       lp->id, ra, len, offset);
+		return -EFAULT;
+	}
+
+	if (lp->hs_state != LDC_HS_COMPLETE ||
+	    (lp->flags & LDC_FLAG_RESET)) {
+		printk(KERN_ERR PFX "ldc_copy: ID[%lu] Link down hs_state[%x] "
+		       "flags[%x]\n", lp->id, lp->hs_state, lp->flags);
+		return -ECONNRESET;
+	}
+
+	orig_len = len;
+	for (i = 0; i < ncookies; i++) {
+		unsigned long cookie_raddr = cookies[i].cookie_addr;
+		unsigned long this_len = cookies[i].cookie_size;
+		unsigned long actual_len;
+
+		if (unlikely(offset)) {
+			unsigned long this_off = offset;
+
+			if (this_off > this_len)
+				this_off = this_len;
+
+			offset -= this_off;
+			this_len -= this_off;
+			if (!this_len)
+				continue;
+			cookie_raddr += this_off;
+		}
+
+		if (this_len > len)
+			this_len = len;
+
+		while (1) {
+			unsigned long hv_err;
+
+			hv_err = sun4v_ldc_copy(lp->id, copy_dir,
+						cookie_raddr, ra,
+						this_len, &actual_len);
+			if (unlikely(hv_err)) {
+				printk(KERN_ERR PFX "ldc_copy: ID[%lu] "
+				       "HV error %lu\n",
+				       lp->id, hv_err);
+				if (lp->hs_state != LDC_HS_COMPLETE ||
+				    (lp->flags & LDC_FLAG_RESET))
+					return -ECONNRESET;
+				else
+					return -EFAULT;
+			}
+
+			cookie_raddr += actual_len;
+			ra += actual_len;
+			len -= actual_len;
+			if (actual_len == this_len)
+				break;
+
+			this_len -= actual_len;
+		}
+
+		if (!len)
+			break;
+	}
+
+	/* It is caller policy what to do about short copies.
+	 * For example, a networking driver can declare the
+	 * packet a runt and drop it.
+	 */
+
+	return orig_len - len;
+}
+EXPORT_SYMBOL(ldc_copy);
+
+void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+			  struct ldc_trans_cookie *cookies, int *ncookies,
+			  unsigned int map_perm)
+{
+	void *buf;
+	int err;
+
+	if (len & (8UL - 1))
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	err = ldc_map_single(lp, buf, len, cookies, *ncookies, map_perm);
+	if (err < 0) {
+		kfree(buf);
+		return ERR_PTR(err);
+	}
+	*ncookies = err;
+
+	return buf;
+}
+EXPORT_SYMBOL(ldc_alloc_exp_dring);
+
+void ldc_free_exp_dring(struct ldc_channel *lp, void *buf, unsigned int len,
+			struct ldc_trans_cookie *cookies, int ncookies)
+{
+	ldc_unmap(lp, cookies, ncookies);
+	kfree(buf);
+}
+EXPORT_SYMBOL(ldc_free_exp_dring);
+
+static int __init ldc_init(void)
+{
+	unsigned long major, minor;
+	struct mdesc_handle *hp;
+	const u64 *v;
+	u64 mp;
+
+	hp = mdesc_grab();
+	if (!hp)
+		return -ENODEV;
+
+	mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
+	if (mp == MDESC_NODE_NULL)
+		return -ENODEV;
+
+	v = mdesc_get_property(hp, mp, "domaining-enabled", NULL);
+	if (!v)
+		return -ENODEV;
+
+	major = 1;
+	minor = 0;
+	if (sun4v_hvapi_register(HV_GRP_LDOM, major, &minor)) {
+		printk(KERN_INFO PFX "Could not register LDOM hvapi.\n");
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "%s", version);
+
+	if (!*v) {
+		printk(KERN_INFO PFX "Domaining disabled.\n");
+		return -ENODEV;
+	}
+	ldom_domaining_enabled = 1;
+
+	return 0;
+}
+
+core_initcall(ldc_init);
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index f0e16045..de5310f 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -6,6 +6,9 @@
 #include <linux/types.h>
 #include <linux/bootmem.h>
 #include <linux/log2.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
 
 #include <asm/hypervisor.h>
 #include <asm/mdesc.h>
@@ -29,7 +32,7 @@
 	u32	node_sz; /* node block size */
 	u32	name_sz; /* name block size */
 	u32	data_sz; /* data block size */
-};
+} __attribute__((aligned(16)));
 
 struct mdesc_elem {
 	u8	tag;
@@ -53,306 +56,396 @@
 	} d;
 };
 
-static struct mdesc_hdr *main_mdesc;
-static struct mdesc_node *allnodes;
+struct mdesc_mem_ops {
+	struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
+	void (*free)(struct mdesc_handle *handle);
+};
 
-static struct mdesc_node *allnodes_tail;
-static unsigned int unique_id;
+struct mdesc_handle {
+	struct list_head	list;
+	struct mdesc_mem_ops	*mops;
+	void			*self_base;
+	atomic_t		refcnt;
+	unsigned int		handle_size;
+	struct mdesc_hdr	mdesc;
+};
 
-static struct mdesc_node **mdesc_hash;
-static unsigned int mdesc_hash_size;
-
-static inline unsigned int node_hashfn(u64 node)
+static void mdesc_handle_init(struct mdesc_handle *hp,
+			      unsigned int handle_size,
+			      void *base)
 {
-	return ((unsigned int) (node ^ (node >> 8) ^ (node >> 16)))
-		& (mdesc_hash_size - 1);
+	BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
+
+	memset(hp, 0, handle_size);
+	INIT_LIST_HEAD(&hp->list);
+	hp->self_base = base;
+	atomic_set(&hp->refcnt, 1);
+	hp->handle_size = handle_size;
 }
 
-static inline void hash_node(struct mdesc_node *mp)
+static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size)
 {
-	struct mdesc_node **head = &mdesc_hash[node_hashfn(mp->node)];
+	struct mdesc_handle *hp;
+	unsigned int handle_size, alloc_size;
 
-	mp->hash_next = *head;
-	*head = mp;
+	handle_size = (sizeof(struct mdesc_handle) -
+		       sizeof(struct mdesc_hdr) +
+		       mdesc_size);
+	alloc_size = PAGE_ALIGN(handle_size);
 
-	if (allnodes_tail) {
-		allnodes_tail->allnodes_next = mp;
-		allnodes_tail = mp;
-	} else {
-		allnodes = allnodes_tail = mp;
+	hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
+	if (hp)
+		mdesc_handle_init(hp, handle_size, hp);
+
+	return hp;
+}
+
+static void mdesc_bootmem_free(struct mdesc_handle *hp)
+{
+	unsigned int alloc_size, handle_size = hp->handle_size;
+	unsigned long start, end;
+
+	BUG_ON(atomic_read(&hp->refcnt) != 0);
+	BUG_ON(!list_empty(&hp->list));
+
+	alloc_size = PAGE_ALIGN(handle_size);
+
+	start = (unsigned long) hp;
+	end = start + alloc_size;
+
+	while (start < end) {
+		struct page *p;
+
+		p = virt_to_page(start);
+		ClearPageReserved(p);
+		__free_page(p);
+		start += PAGE_SIZE;
 	}
 }
 
-static struct mdesc_node *find_node(u64 node)
+static struct mdesc_mem_ops bootmem_mdesc_memops = {
+	.alloc = mdesc_bootmem_alloc,
+	.free  = mdesc_bootmem_free,
+};
+
+static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
 {
-	struct mdesc_node *mp = mdesc_hash[node_hashfn(node)];
+	unsigned int handle_size;
+	void *base;
 
-	while (mp) {
-		if (mp->node == node)
-			return mp;
+	handle_size = (sizeof(struct mdesc_handle) -
+		       sizeof(struct mdesc_hdr) +
+		       mdesc_size);
 
-		mp = mp->hash_next;
+	base = kmalloc(handle_size + 15, GFP_KERNEL);
+	if (base) {
+		struct mdesc_handle *hp;
+		unsigned long addr;
+
+		addr = (unsigned long)base;
+		addr = (addr + 15UL) & ~15UL;
+		hp = (struct mdesc_handle *) addr;
+
+		mdesc_handle_init(hp, handle_size, base);
+		return hp;
 	}
+
 	return NULL;
 }
 
-struct property *md_find_property(const struct mdesc_node *mp,
-				  const char *name,
-				  int *lenp)
+static void mdesc_kfree(struct mdesc_handle *hp)
 {
-	struct property *pp;
+	BUG_ON(atomic_read(&hp->refcnt) != 0);
+	BUG_ON(!list_empty(&hp->list));
 
-	for (pp = mp->properties; pp != 0; pp = pp->next) {
-		if (strcasecmp(pp->name, name) == 0) {
-			if (lenp)
-				*lenp = pp->length;
-			break;
-		}
+	kfree(hp->self_base);
+}
+
+static struct mdesc_mem_ops kmalloc_mdesc_memops = {
+	.alloc = mdesc_kmalloc,
+	.free  = mdesc_kfree,
+};
+
+static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
+					struct mdesc_mem_ops *mops)
+{
+	struct mdesc_handle *hp = mops->alloc(mdesc_size);
+
+	if (hp)
+		hp->mops = mops;
+
+	return hp;
+}
+
+static void mdesc_free(struct mdesc_handle *hp)
+{
+	hp->mops->free(hp);
+}
+
+static struct mdesc_handle *cur_mdesc;
+static LIST_HEAD(mdesc_zombie_list);
+static DEFINE_SPINLOCK(mdesc_lock);
+
+struct mdesc_handle *mdesc_grab(void)
+{
+	struct mdesc_handle *hp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdesc_lock, flags);
+	hp = cur_mdesc;
+	if (hp)
+		atomic_inc(&hp->refcnt);
+	spin_unlock_irqrestore(&mdesc_lock, flags);
+
+	return hp;
+}
+EXPORT_SYMBOL(mdesc_grab);
+
+void mdesc_release(struct mdesc_handle *hp)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdesc_lock, flags);
+	if (atomic_dec_and_test(&hp->refcnt)) {
+		list_del_init(&hp->list);
+		hp->mops->free(hp);
 	}
-	return pp;
+	spin_unlock_irqrestore(&mdesc_lock, flags);
 }
-EXPORT_SYMBOL(md_find_property);
+EXPORT_SYMBOL(mdesc_release);
 
-/*
- * Find a property with a given name for a given node
- * and return the value.
- */
-const void *md_get_property(const struct mdesc_node *mp, const char *name,
-			    int *lenp)
+void mdesc_update(void)
 {
-	struct property *pp = md_find_property(mp, name, lenp);
-	return pp ? pp->value : NULL;
-}
-EXPORT_SYMBOL(md_get_property);
+	unsigned long len, real_len, status;
+	struct mdesc_handle *hp, *orig_hp;
+	unsigned long flags;
 
-struct mdesc_node *md_find_node_by_name(struct mdesc_node *from,
-					const char *name)
-{
-	struct mdesc_node *mp;
+	(void) sun4v_mach_desc(0UL, 0UL, &len);
 
-	mp = from ? from->allnodes_next : allnodes;
-	for (; mp != NULL; mp = mp->allnodes_next) {
-		if (strcmp(mp->name, name) == 0)
-			break;
-	}
-	return mp;
-}
-EXPORT_SYMBOL(md_find_node_by_name);
-
-static unsigned int mdesc_early_allocated;
-
-static void * __init mdesc_early_alloc(unsigned long size)
-{
-	void *ret;
-
-	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
-	if (ret == NULL) {
-		prom_printf("MDESC: alloc of %lu bytes failed.\n", size);
-		prom_halt();
+	hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
+	if (!hp) {
+		printk(KERN_ERR "MD: mdesc alloc fails\n");
+		return;
 	}
 
-	memset(ret, 0, size);
-
-	mdesc_early_allocated += size;
-
-	return ret;
-}
-
-static unsigned int __init count_arcs(struct mdesc_elem *ep)
-{
-	unsigned int ret = 0;
-
-	ep++;
-	while (ep->tag != MD_NODE_END) {
-		if (ep->tag == MD_PROP_ARC)
-			ret++;
-		ep++;
+	status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
+	if (status != HV_EOK || real_len > len) {
+		printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
+		       status);
+		atomic_dec(&hp->refcnt);
+		mdesc_free(hp);
+		return;
 	}
-	return ret;
+
+	spin_lock_irqsave(&mdesc_lock, flags);
+	orig_hp = cur_mdesc;
+	cur_mdesc = hp;
+
+	if (atomic_dec_and_test(&orig_hp->refcnt))
+		mdesc_free(orig_hp);
+	else
+		list_add(&orig_hp->list, &mdesc_zombie_list);
+	spin_unlock_irqrestore(&mdesc_lock, flags);
 }
 
-static void __init mdesc_node_alloc(u64 node, struct mdesc_elem *ep, const char *names)
-{
-	unsigned int num_arcs = count_arcs(ep);
-	struct mdesc_node *mp;
-
-	mp = mdesc_early_alloc(sizeof(*mp) +
-			       (num_arcs * sizeof(struct mdesc_arc)));
-	mp->name = names + ep->name_offset;
-	mp->node = node;
-	mp->unique_id = unique_id++;
-	mp->num_arcs = num_arcs;
-
-	hash_node(mp);
-}
-
-static inline struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
+static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
 {
 	return (struct mdesc_elem *) (mdesc + 1);
 }
 
-static inline void *name_block(struct mdesc_hdr *mdesc)
+static void *name_block(struct mdesc_hdr *mdesc)
 {
 	return ((void *) node_block(mdesc)) + mdesc->node_sz;
 }
 
-static inline void *data_block(struct mdesc_hdr *mdesc)
+static void *data_block(struct mdesc_hdr *mdesc)
 {
 	return ((void *) name_block(mdesc)) + mdesc->name_sz;
 }
 
-/* In order to avoid recursion (the graph can be very deep) we use a
- * two pass algorithm.  First we allocate all the nodes and hash them.
- * Then we iterate over each node, filling in the arcs and properties.
- */
-static void __init build_all_nodes(struct mdesc_hdr *mdesc)
+u64 mdesc_node_by_name(struct mdesc_handle *hp,
+		       u64 from_node, const char *name)
 {
-	struct mdesc_elem *start, *ep;
-	struct mdesc_node *mp;
-	const char *names;
-	void *data;
-	u64 last_node;
+	struct mdesc_elem *ep = node_block(&hp->mdesc);
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
+	u64 ret;
 
-	start = ep = node_block(mdesc);
-	last_node = mdesc->node_sz / 16;
+	if (from_node == MDESC_NODE_NULL) {
+		ret = from_node = 0;
+	} else if (from_node >= last_node) {
+		return MDESC_NODE_NULL;
+	} else {
+		ret = ep[from_node].d.val;
+	}
 
-	names = name_block(mdesc);
+	while (ret < last_node) {
+		if (ep[ret].tag != MD_NODE)
+			return MDESC_NODE_NULL;
+		if (!strcmp(names + ep[ret].name_offset, name))
+			break;
+		ret = ep[ret].d.val;
+	}
+	if (ret >= last_node)
+		ret = MDESC_NODE_NULL;
+	return ret;
+}
+EXPORT_SYMBOL(mdesc_node_by_name);
 
-	while (1) {
-		u64 node = ep - start;
+const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
+			       const char *name, int *lenp)
+{
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
+	void *data = data_block(&hp->mdesc);
+	struct mdesc_elem *ep;
 
-		if (ep->tag == MD_LIST_END)
+	if (node == MDESC_NODE_NULL || node >= last_node)
+		return NULL;
+
+	ep = node_block(&hp->mdesc) + node;
+	ep++;
+	for (; ep->tag != MD_NODE_END; ep++) {
+		void *val = NULL;
+		int len = 0;
+
+		switch (ep->tag) {
+		case MD_PROP_VAL:
+			val = &ep->d.val;
+			len = 8;
 			break;
 
-		if (ep->tag != MD_NODE) {
-			prom_printf("MDESC: Inconsistent element list.\n");
-			prom_halt();
-		}
+		case MD_PROP_STR:
+		case MD_PROP_DATA:
+			val = data + ep->d.data.data_offset;
+			len = ep->d.data.data_len;
+			break;
 
-		mdesc_node_alloc(node, ep, names);
-
-		if (ep->d.val >= last_node) {
-			printk("MDESC: Warning, early break out of node scan.\n");
-			printk("MDESC: Next node [%lu] last_node [%lu].\n",
-			       node, last_node);
+		default:
 			break;
 		}
+		if (!val)
+			continue;
 
-		ep = start + ep->d.val;
-	}
-
-	data = data_block(mdesc);
-	for (mp = allnodes; mp; mp = mp->allnodes_next) {
-		struct mdesc_elem *ep = start + mp->node;
-		struct property **link = &mp->properties;
-		unsigned int this_arc = 0;
-
-		ep++;
-		while (ep->tag != MD_NODE_END) {
-			switch (ep->tag) {
-			case MD_PROP_ARC: {
-				struct mdesc_node *target;
-
-				if (this_arc >= mp->num_arcs) {
-					prom_printf("MDESC: ARC overrun [%u:%u]\n",
-						    this_arc, mp->num_arcs);
-					prom_halt();
-				}
-				target = find_node(ep->d.val);
-				if (!target) {
-					printk("MDESC: Warning, arc points to "
-					       "missing node, ignoring.\n");
-					break;
-				}
-				mp->arcs[this_arc].name =
-					(names + ep->name_offset);
-				mp->arcs[this_arc].arc = target;
-				this_arc++;
-				break;
-			}
-
-			case MD_PROP_VAL:
-			case MD_PROP_STR:
-			case MD_PROP_DATA: {
-				struct property *p = mdesc_early_alloc(sizeof(*p));
-
-				p->unique_id = unique_id++;
-				p->name = (char *) names + ep->name_offset;
-				if (ep->tag == MD_PROP_VAL) {
-					p->value = &ep->d.val;
-					p->length = 8;
-				} else {
-					p->value = data + ep->d.data.data_offset;
-					p->length = ep->d.data.data_len;
-				}
-				*link = p;
-				link = &p->next;
-				break;
-			}
-
-			case MD_NOOP:
-				break;
-
-			default:
-				printk("MDESC: Warning, ignoring unknown tag type %02x\n",
-				       ep->tag);
-			}
-			ep++;
+		if (!strcmp(names + ep->name_offset, name)) {
+			if (lenp)
+				*lenp = len;
+			return val;
 		}
 	}
-}
 
-static unsigned int __init count_nodes(struct mdesc_hdr *mdesc)
+	return NULL;
+}
+EXPORT_SYMBOL(mdesc_get_property);
+
+u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
 {
-	struct mdesc_elem *ep = node_block(mdesc);
-	struct mdesc_elem *end;
-	unsigned int cnt = 0;
+	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
 
-	end = ((void *)ep) + mdesc->node_sz;
-	while (ep < end) {
-		if (ep->tag == MD_NODE)
-			cnt++;
-		ep++;
+	if (from == MDESC_NODE_NULL || from >= last_node)
+		return MDESC_NODE_NULL;
+
+	ep = base + from;
+
+	ep++;
+	for (; ep->tag != MD_NODE_END; ep++) {
+		if (ep->tag != MD_PROP_ARC)
+			continue;
+
+		if (strcmp(names + ep->name_offset, arc_type))
+			continue;
+
+		return ep - base;
 	}
-	return cnt;
+
+	return MDESC_NODE_NULL;
 }
+EXPORT_SYMBOL(mdesc_next_arc);
+
+u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
+{
+	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+
+	ep = base + arc;
+
+	return ep->d.val;
+}
+EXPORT_SYMBOL(mdesc_arc_target);
+
+const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
+{
+	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
+
+	if (node == MDESC_NODE_NULL || node >= last_node)
+		return NULL;
+
+	ep = base + node;
+	if (ep->tag != MD_NODE)
+		return NULL;
+
+	return names + ep->name_offset;
+}
+EXPORT_SYMBOL(mdesc_node_name);
 
 static void __init report_platform_properties(void)
 {
-	struct mdesc_node *pn = md_find_node_by_name(NULL, "platform");
+	struct mdesc_handle *hp = mdesc_grab();
+	u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
 	const char *s;
 	const u64 *v;
 
-	if (!pn) {
+	if (pn == MDESC_NODE_NULL) {
 		prom_printf("No platform node in machine-description.\n");
 		prom_halt();
 	}
 
-	s = md_get_property(pn, "banner-name", NULL);
+	s = mdesc_get_property(hp, pn, "banner-name", NULL);
 	printk("PLATFORM: banner-name [%s]\n", s);
-	s = md_get_property(pn, "name", NULL);
+	s = mdesc_get_property(hp, pn, "name", NULL);
 	printk("PLATFORM: name [%s]\n", s);
 
-	v = md_get_property(pn, "hostid", NULL);
+	v = mdesc_get_property(hp, pn, "hostid", NULL);
 	if (v)
 		printk("PLATFORM: hostid [%08lx]\n", *v);
-	v = md_get_property(pn, "serial#", NULL);
+	v = mdesc_get_property(hp, pn, "serial#", NULL);
 	if (v)
 		printk("PLATFORM: serial# [%08lx]\n", *v);
-	v = md_get_property(pn, "stick-frequency", NULL);
+	v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
 	printk("PLATFORM: stick-frequency [%08lx]\n", *v);
-	v = md_get_property(pn, "mac-address", NULL);
+	v = mdesc_get_property(hp, pn, "mac-address", NULL);
 	if (v)
 		printk("PLATFORM: mac-address [%lx]\n", *v);
-	v = md_get_property(pn, "watchdog-resolution", NULL);
+	v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
 	if (v)
 		printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
-	v = md_get_property(pn, "watchdog-max-timeout", NULL);
+	v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
 	if (v)
 		printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
-	v = md_get_property(pn, "max-cpus", NULL);
+	v = mdesc_get_property(hp, pn, "max-cpus", NULL);
 	if (v)
 		printk("PLATFORM: max-cpus [%lu]\n", *v);
+
+#ifdef CONFIG_SMP
+	{
+		int max_cpu, i;
+
+		if (v) {
+			max_cpu = *v;
+			if (max_cpu > NR_CPUS)
+				max_cpu = NR_CPUS;
+		} else {
+			max_cpu = NR_CPUS;
+		}
+		for (i = 0; i < max_cpu; i++)
+			cpu_set(i, cpu_possible_map);
+	}
+#endif
+
+	mdesc_release(hp);
 }
 
 static int inline find_in_proplist(const char *list, const char *match, int len)
@@ -369,15 +462,17 @@
 	return 0;
 }
 
-static void __init fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_node *mp)
+static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
+					struct mdesc_handle *hp,
+					u64 mp)
 {
-	const u64 *level = md_get_property(mp, "level", NULL);
-	const u64 *size = md_get_property(mp, "size", NULL);
-	const u64 *line_size = md_get_property(mp, "line-size", NULL);
+	const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
+	const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
+	const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
 	const char *type;
 	int type_len;
 
-	type = md_get_property(mp, "type", &type_len);
+	type = mdesc_get_property(hp, mp, "type", &type_len);
 
 	switch (*level) {
 	case 1:
@@ -400,48 +495,45 @@
 	}
 
 	if (*level == 1) {
-		unsigned int i;
+		u64 a;
 
-		for (i = 0; i < mp->num_arcs; i++) {
-			struct mdesc_node *t = mp->arcs[i].arc;
+		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+			u64 target = mdesc_arc_target(hp, a);
+			const char *name = mdesc_node_name(hp, target);
 
-			if (strcmp(mp->arcs[i].name, "fwd"))
-				continue;
-
-			if (!strcmp(t->name, "cache"))
-				fill_in_one_cache(c, t);
+			if (!strcmp(name, "cache"))
+				fill_in_one_cache(c, hp, target);
 		}
 	}
 }
 
-static void __init mark_core_ids(struct mdesc_node *mp, int core_id)
+static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
+				    int core_id)
 {
-	unsigned int i;
+	u64 a;
 
-	for (i = 0; i < mp->num_arcs; i++) {
-		struct mdesc_node *t = mp->arcs[i].arc;
+	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
+		u64 t = mdesc_arc_target(hp, a);
+		const char *name;
 		const u64 *id;
 
-		if (strcmp(mp->arcs[i].name, "back"))
-			continue;
-
-		if (!strcmp(t->name, "cpu")) {
-			id = md_get_property(t, "id", NULL);
+		name = mdesc_node_name(hp, t);
+		if (!strcmp(name, "cpu")) {
+			id = mdesc_get_property(hp, t, "id", NULL);
 			if (*id < NR_CPUS)
 				cpu_data(*id).core_id = core_id;
 		} else {
-			unsigned int j;
+			u64 j;
 
-			for (j = 0; j < t->num_arcs; j++) {
-				struct mdesc_node *n = t->arcs[j].arc;
+			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
+				u64 n = mdesc_arc_target(hp, j);
+				const char *n_name;
 
-				if (strcmp(t->arcs[j].name, "back"))
+				n_name = mdesc_node_name(hp, n);
+				if (strcmp(n_name, "cpu"))
 					continue;
 
-				if (strcmp(n->name, "cpu"))
-					continue;
-
-				id = md_get_property(n, "id", NULL);
+				id = mdesc_get_property(hp, n, "id", NULL);
 				if (*id < NR_CPUS)
 					cpu_data(*id).core_id = core_id;
 			}
@@ -449,78 +541,81 @@
 	}
 }
 
-static void __init set_core_ids(void)
+static void __devinit set_core_ids(struct mdesc_handle *hp)
 {
-	struct mdesc_node *mp;
 	int idx;
+	u64 mp;
 
 	idx = 1;
-	md_for_each_node_by_name(mp, "cache") {
-		const u64 *level = md_get_property(mp, "level", NULL);
+	mdesc_for_each_node_by_name(hp, mp, "cache") {
+		const u64 *level;
 		const char *type;
 		int len;
 
+		level = mdesc_get_property(hp, mp, "level", NULL);
 		if (*level != 1)
 			continue;
 
-		type = md_get_property(mp, "type", &len);
+		type = mdesc_get_property(hp, mp, "type", &len);
 		if (!find_in_proplist(type, "instn", len))
 			continue;
 
-		mark_core_ids(mp, idx);
+		mark_core_ids(hp, mp, idx);
 
 		idx++;
 	}
 }
 
-static void __init mark_proc_ids(struct mdesc_node *mp, int proc_id)
+static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
+				    int proc_id)
 {
-	int i;
+	u64 a;
 
-	for (i = 0; i < mp->num_arcs; i++) {
-		struct mdesc_node *t = mp->arcs[i].arc;
+	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
+		u64 t = mdesc_arc_target(hp, a);
+		const char *name;
 		const u64 *id;
 
-		if (strcmp(mp->arcs[i].name, "back"))
+		name = mdesc_node_name(hp, t);
+		if (strcmp(name, "cpu"))
 			continue;
 
-		if (strcmp(t->name, "cpu"))
-			continue;
-
-		id = md_get_property(t, "id", NULL);
+		id = mdesc_get_property(hp, t, "id", NULL);
 		if (*id < NR_CPUS)
 			cpu_data(*id).proc_id = proc_id;
 	}
 }
 
-static void __init __set_proc_ids(const char *exec_unit_name)
+static void __devinit __set_proc_ids(struct mdesc_handle *hp,
+				     const char *exec_unit_name)
 {
-	struct mdesc_node *mp;
 	int idx;
+	u64 mp;
 
 	idx = 0;
-	md_for_each_node_by_name(mp, exec_unit_name) {
+	mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
 		const char *type;
 		int len;
 
-		type = md_get_property(mp, "type", &len);
+		type = mdesc_get_property(hp, mp, "type", &len);
 		if (!find_in_proplist(type, "int", len) &&
 		    !find_in_proplist(type, "integer", len))
 			continue;
 
-		mark_proc_ids(mp, idx);
+		mark_proc_ids(hp, mp, idx);
 
 		idx++;
 	}
 }
 
-static void __init set_proc_ids(void)
+static void __devinit set_proc_ids(struct mdesc_handle *hp)
 {
-	__set_proc_ids("exec_unit");
-	__set_proc_ids("exec-unit");
+	__set_proc_ids(hp, "exec_unit");
+	__set_proc_ids(hp, "exec-unit");
 }
 
-static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def)
+static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
+					 unsigned char def)
 {
 	u64 val;
 
@@ -538,35 +633,37 @@
 	*mask = ((1U << def) * 64U) - 1U;
 }
 
-static void __init get_mondo_data(struct mdesc_node *mp, struct trap_per_cpu *tb)
+static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
+				     struct trap_per_cpu *tb)
 {
 	const u64 *val;
 
-	val = md_get_property(mp, "q-cpu-mondo-#bits", NULL);
+	val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
 	get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
 
-	val = md_get_property(mp, "q-dev-mondo-#bits", NULL);
+	val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
 	get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
 
-	val = md_get_property(mp, "q-resumable-#bits", NULL);
+	val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
 	get_one_mondo_bits(val, &tb->resum_qmask, 6);
 
-	val = md_get_property(mp, "q-nonresumable-#bits", NULL);
+	val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
 	get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
 }
 
-static void __init mdesc_fill_in_cpu_data(void)
+void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
 {
-	struct mdesc_node *mp;
+	struct mdesc_handle *hp = mdesc_grab();
+	u64 mp;
 
 	ncpus_probed = 0;
-	md_for_each_node_by_name(mp, "cpu") {
-		const u64 *id = md_get_property(mp, "id", NULL);
-		const u64 *cfreq = md_get_property(mp, "clock-frequency", NULL);
+	mdesc_for_each_node_by_name(hp, mp, "cpu") {
+		const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
+		const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
 		struct trap_per_cpu *tb;
 		cpuinfo_sparc *c;
-		unsigned int i;
 		int cpuid;
+		u64 a;
 
 		ncpus_probed++;
 
@@ -575,6 +672,8 @@
 #ifdef CONFIG_SMP
 		if (cpuid >= NR_CPUS)
 			continue;
+		if (!cpu_isset(cpuid, mask))
+			continue;
 #else
 		/* On uniprocessor we only want the values for the
 		 * real physical cpu the kernel booted onto, however
@@ -589,35 +688,30 @@
 		c->clock_tick = *cfreq;
 
 		tb = &trap_block[cpuid];
-		get_mondo_data(mp, tb);
+		get_mondo_data(hp, mp, tb);
 
-		for (i = 0; i < mp->num_arcs; i++) {
-			struct mdesc_node *t = mp->arcs[i].arc;
-			unsigned int j;
+		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+			u64 j, t = mdesc_arc_target(hp, a);
+			const char *t_name;
 
-			if (strcmp(mp->arcs[i].name, "fwd"))
-				continue;
-
-			if (!strcmp(t->name, "cache")) {
-				fill_in_one_cache(c, t);
+			t_name = mdesc_node_name(hp, t);
+			if (!strcmp(t_name, "cache")) {
+				fill_in_one_cache(c, hp, t);
 				continue;
 			}
 
-			for (j = 0; j < t->num_arcs; j++) {
-				struct mdesc_node *n;
+			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
+				u64 n = mdesc_arc_target(hp, j);
+				const char *n_name;
 
-				n = t->arcs[j].arc;
-				if (strcmp(t->arcs[j].name, "fwd"))
-					continue;
-
-				if (!strcmp(n->name, "cache"))
-					fill_in_one_cache(c, n);
+				n_name = mdesc_node_name(hp, n);
+				if (!strcmp(n_name, "cache"))
+					fill_in_one_cache(c, hp, n);
 			}
 		}
 
 #ifdef CONFIG_SMP
 		cpu_set(cpuid, cpu_present_map);
-		cpu_set(cpuid, phys_cpu_present_map);
 #endif
 
 		c->core_id = 0;
@@ -628,45 +722,43 @@
 	sparc64_multi_core = 1;
 #endif
 
-	set_core_ids();
-	set_proc_ids();
+	set_core_ids(hp);
+	set_proc_ids(hp);
 
 	smp_fill_in_sib_core_maps();
+
+	mdesc_release(hp);
 }
 
 void __init sun4v_mdesc_init(void)
 {
+	struct mdesc_handle *hp;
 	unsigned long len, real_len, status;
+	cpumask_t mask;
 
 	(void) sun4v_mach_desc(0UL, 0UL, &len);
 
 	printk("MDESC: Size is %lu bytes.\n", len);
 
-	main_mdesc = mdesc_early_alloc(len);
+	hp = mdesc_alloc(len, &bootmem_mdesc_memops);
+	if (hp == NULL) {
+		prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
+		prom_halt();
+	}
 
-	status = sun4v_mach_desc(__pa(main_mdesc), len, &real_len);
+	status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
 	if (status != HV_EOK || real_len > len) {
 		prom_printf("sun4v_mach_desc fails, err(%lu), "
 			    "len(%lu), real_len(%lu)\n",
 			    status, len, real_len);
+		mdesc_free(hp);
 		prom_halt();
 	}
 
-	len = count_nodes(main_mdesc);
-	printk("MDESC: %lu nodes.\n", len);
-
-	len = roundup_pow_of_two(len);
-
-	mdesc_hash = mdesc_early_alloc(len * sizeof(struct mdesc_node *));
-	mdesc_hash_size = len;
-
-	printk("MDESC: Hash size %lu entries.\n", len);
-
-	build_all_nodes(main_mdesc);
-
-	printk("MDESC: Built graph with %u bytes of memory.\n",
-	       mdesc_early_allocated);
+	cur_mdesc = hp;
 
 	report_platform_properties();
-	mdesc_fill_in_cpu_data();
+
+	cpus_setall(mask);
+	mdesc_fill_in_cpu_data(mask);
 }
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 5d6adea..8dd4294 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -1,7 +1,6 @@
-/* $Id: power.c,v 1.10 2001/12/11 01:57:16 davem Exp $
- * power.c: Power management driver.
+/* power.c: Power management driver.
  *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/kernel.h>
@@ -19,6 +18,7 @@
 #include <asm/prom.h>
 #include <asm/of_device.h>
 #include <asm/io.h>
+#include <asm/power.h>
 #include <asm/sstate.h>
 
 #include <linux/unistd.h>
@@ -29,24 +29,26 @@
  */
 int scons_pwroff = 1; 
 
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
 static void __iomem *power_reg;
 
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
 static int button_pressed;
 
-static irqreturn_t power_handler(int irq, void *dev_id)
+void wake_up_powerd(void)
 {
 	if (button_pressed == 0) {
 		button_pressed = 1;
 		wake_up(&powerd_wait);
 	}
+}
+
+static irqreturn_t power_handler(int irq, void *dev_id)
+{
+	wake_up_powerd();
 
 	/* FIXME: Check registers for status... */
 	return IRQ_HANDLED;
 }
-#endif /* CONFIG_PCI */
 
 extern void machine_halt(void);
 extern void machine_alt_power_off(void);
@@ -56,19 +58,18 @@
 {
 	sstate_poweroff();
 	if (!serial_console || scons_pwroff) {
-#ifdef CONFIG_PCI
 		if (power_reg) {
 			/* Both register bits seem to have the
 			 * same effect, so until I figure out
 			 * what the difference is...
 			 */
 			writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg);
-		} else
-#endif /* CONFIG_PCI */
+		} else {
 			if (poweroff_method != NULL) {
 				poweroff_method();
 				/* not reached */
 			}
+		}
 	}
 	machine_halt();
 }
@@ -76,7 +77,6 @@
 void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL(pm_power_off);
 
-#ifdef CONFIG_PCI
 static int powerd(void *__unused)
 {
 	static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
@@ -86,7 +86,7 @@
 	daemonize("powerd");
 
 	add_wait_queue(&powerd_wait, &wait);
-again:
+
 	for (;;) {
 		set_task_state(current, TASK_INTERRUPTIBLE);
 		if (button_pressed)
@@ -100,16 +100,28 @@
 	/* Ok, down we go... */
 	button_pressed = 0;
 	if (kernel_execve("/sbin/shutdown", argv, envp) < 0) {
-		printk("powerd: shutdown execution failed\n");
-		add_wait_queue(&powerd_wait, &wait);
-		goto again;
+		printk(KERN_ERR "powerd: shutdown execution failed\n");
+		machine_power_off();
 	}
 	return 0;
 }
 
+int start_powerd(void)
+{
+	int err;
+
+	err = kernel_thread(powerd, NULL, CLONE_FS);
+	if (err < 0)
+		printk(KERN_ERR "power: Failed to start power daemon.\n");
+	else
+		printk(KERN_INFO "power: powerd running.\n");
+
+	return err;
+}
+
 static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
 {
-	if (irq == PCI_IRQ_NONE)
+	if (irq == 0xffffffff)
 		return 0;
 	if (!of_find_property(dp, "button", NULL))
 		return 0;
@@ -130,17 +142,14 @@
 	poweroff_method = machine_halt;  /* able to use the standard halt */
 
 	if (has_button_interrupt(irq, op->node)) {
-		if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
-			printk("Failed to start power daemon.\n");
+		if (start_powerd() < 0)
 			return 0;
-		}
-		printk("powerd running.\n");
 
 		if (request_irq(irq,
 				power_handler, 0, "power", NULL) < 0)
-			printk("power: Error, cannot register IRQ handler.\n");
+			printk(KERN_ERR "power: Cannot setup IRQ handler.\n");
 	} else {
-		printk("not using powerd.\n");
+		printk(KERN_INFO "power: Not using powerd.\n");
 	}
 
 	return 0;
@@ -164,4 +173,3 @@
 	of_register_driver(&power_driver, &of_bus_type);
 	return;
 }
-#endif /* CONFIG_PCI */
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index f5f97e2..9355750 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -29,6 +29,7 @@
 #include <linux/compat.h>
 #include <linux/tick.h>
 #include <linux/init.h>
+#include <linux/cpu.h>
 
 #include <asm/oplib.h>
 #include <asm/uaccess.h>
@@ -49,7 +50,7 @@
 
 /* #define VERBOSE_SHOWREGS */
 
-static void sparc64_yield(void)
+static void sparc64_yield(int cpu)
 {
 	if (tlb_type != hypervisor)
 		return;
@@ -57,7 +58,7 @@
 	clear_thread_flag(TIF_POLLING_NRFLAG);
 	smp_mb__after_clear_bit();
 
-	while (!need_resched()) {
+	while (!need_resched() && !cpu_is_offline(cpu)) {
 		unsigned long pstate;
 
 		/* Disable interrupts. */
@@ -68,7 +69,7 @@
 			: "=&r" (pstate)
 			: "i" (PSTATE_IE));
 
-		if (!need_resched())
+		if (!need_resched() && !cpu_is_offline(cpu))
 			sun4v_cpu_yield();
 
 		/* Re-enable interrupts. */
@@ -86,15 +87,25 @@
 /* The idle loop on sparc64. */
 void cpu_idle(void)
 {
+	int cpu = smp_processor_id();
+
 	set_thread_flag(TIF_POLLING_NRFLAG);
 
 	while(1) {
 		tick_nohz_stop_sched_tick();
-		while (!need_resched())
-			sparc64_yield();
+
+		while (!need_resched() && !cpu_is_offline(cpu))
+			sparc64_yield(cpu);
+
 		tick_nohz_restart_sched_tick();
 
 		preempt_enable_no_resched();
+
+#ifdef CONFIG_HOTPLUG_CPU
+		if (cpu_is_offline(cpu))
+			cpu_play_dead();
+#endif
+
 		schedule();
 		preempt_disable();
 	}
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 61036b3..5d22030 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -1808,7 +1808,7 @@
 
 #ifdef CONFIG_SMP
 		cpu_set(cpuid, cpu_present_map);
-		cpu_set(cpuid, phys_cpu_present_map);
+		cpu_set(cpuid, cpu_possible_map);
 #endif
 	}
 
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 7490cc6..aafde3d 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -442,7 +442,6 @@
 		   "D$ parity tl1\t: %u\n"
 		   "I$ parity tl1\t: %u\n"
 #ifndef CONFIG_SMP
-		   "Cpu0Bogo\t: %lu.%02lu\n"
 		   "Cpu0ClkTck\t: %016lx\n"
 #endif
 		   ,
@@ -457,9 +456,7 @@
 		   dcache_parity_tl1_occurred,
 		   icache_parity_tl1_occurred
 #ifndef CONFIG_SMP
-		   , cpu_data(0).udelay_val/(500000/HZ),
-		   (cpu_data(0).udelay_val/(5000/HZ)) % 100,
-		   cpu_data(0).clock_tick
+		   , cpu_data(0).clock_tick
 #endif
 		);
 #ifdef CONFIG_SMP
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 40e40f9..b448d33 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1,6 +1,6 @@
 /* smp.c: Sparc64 SMP support.
  *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/module.h>
@@ -28,6 +28,8 @@
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 #include <asm/cpudata.h>
+#include <asm/hvtramp.h>
+#include <asm/io.h>
 
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
@@ -41,22 +43,26 @@
 #include <asm/sections.h>
 #include <asm/prom.h>
 #include <asm/mdesc.h>
+#include <asm/ldc.h>
+#include <asm/hypervisor.h>
 
 extern void calibrate_delay(void);
 
 int sparc64_multi_core __read_mostly;
 
-/* Please don't make this stuff initdata!!!  --DaveM */
-unsigned char boot_cpu_id;
-
+cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
 cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
-cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly =
 	{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
 cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
 	{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+
+EXPORT_SYMBOL(cpu_possible_map);
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_sibling_map);
+EXPORT_SYMBOL(cpu_core_map);
+
 static cpumask_t smp_commenced_mask;
-static cpumask_t cpu_callout_map;
 
 void smp_info(struct seq_file *m)
 {
@@ -73,18 +79,17 @@
 	
 	for_each_online_cpu(i)
 		seq_printf(m,
-			   "Cpu%dBogo\t: %lu.%02lu\n"
 			   "Cpu%dClkTck\t: %016lx\n",
-			   i, cpu_data(i).udelay_val / (500000/HZ),
-			   (cpu_data(i).udelay_val / (5000/HZ)) % 100,
 			   i, cpu_data(i).clock_tick);
 }
 
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
+
 extern void setup_sparc64_timer(void);
 
 static volatile unsigned long callin_flag = 0;
 
-void __init smp_callin(void)
+void __devinit smp_callin(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -102,8 +107,6 @@
 
 	local_irq_enable();
 
-	calibrate_delay();
-	cpu_data(cpuid).udelay_val = loops_per_jiffy;
 	callin_flag = 1;
 	__asm__ __volatile__("membar #Sync\n\t"
 			     "flush  %%g6" : : : "memory");
@@ -120,7 +123,9 @@
 	while (!cpu_isset(cpuid, smp_commenced_mask))
 		rmb();
 
+	spin_lock(&call_lock);
 	cpu_set(cpuid, cpu_online_map);
+	spin_unlock(&call_lock);
 
 	/* idle thread is expected to have preempt disabled */
 	preempt_disable();
@@ -268,6 +273,67 @@
 	spin_unlock_irqrestore(&itc_sync_lock, flags);
 }
 
+#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
+/* XXX Put this in some common place. XXX */
+static unsigned long kimage_addr_to_ra(void *p)
+{
+	unsigned long val = (unsigned long) p;
+
+	return kern_base + (val - KERNBASE);
+}
+
+static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
+{
+	extern unsigned long sparc64_ttable_tl0;
+	extern unsigned long kern_locked_tte_data;
+	extern int bigkernel;
+	struct hvtramp_descr *hdesc;
+	unsigned long trampoline_ra;
+	struct trap_per_cpu *tb;
+	u64 tte_vaddr, tte_data;
+	unsigned long hv_err;
+
+	hdesc = kzalloc(sizeof(*hdesc), GFP_KERNEL);
+	if (!hdesc) {
+		printk(KERN_ERR "ldom_startcpu_cpuid: Cannot allocate "
+		       "hvtramp_descr.\n");
+		return;
+	}
+
+	hdesc->cpu = cpu;
+	hdesc->num_mappings = (bigkernel ? 2 : 1);
+
+	tb = &trap_block[cpu];
+	tb->hdesc = hdesc;
+
+	hdesc->fault_info_va = (unsigned long) &tb->fault_info;
+	hdesc->fault_info_pa = kimage_addr_to_ra(&tb->fault_info);
+
+	hdesc->thread_reg = thread_reg;
+
+	tte_vaddr = (unsigned long) KERNBASE;
+	tte_data = kern_locked_tte_data;
+
+	hdesc->maps[0].vaddr = tte_vaddr;
+	hdesc->maps[0].tte   = tte_data;
+	if (bigkernel) {
+		tte_vaddr += 0x400000;
+		tte_data  += 0x400000;
+		hdesc->maps[1].vaddr = tte_vaddr;
+		hdesc->maps[1].tte   = tte_data;
+	}
+
+	trampoline_ra = kimage_addr_to_ra(hv_cpu_startup);
+
+	hv_err = sun4v_cpu_start(cpu, trampoline_ra,
+				 kimage_addr_to_ra(&sparc64_ttable_tl0),
+				 __pa(hdesc));
+	if (hv_err)
+		printk(KERN_ERR "ldom_startcpu_cpuid: sun4v_cpu_start() "
+		       "gives error %lu\n", hv_err);
+}
+#endif
+
 extern void sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int load);
 
 extern unsigned long sparc64_cpu_startup;
@@ -280,6 +346,7 @@
 
 static int __devinit smp_boot_one_cpu(unsigned int cpu)
 {
+	struct trap_per_cpu *tb = &trap_block[cpu];
 	unsigned long entry =
 		(unsigned long)(&sparc64_cpu_startup);
 	unsigned long cookie =
@@ -290,20 +357,25 @@
 	p = fork_idle(cpu);
 	callin_flag = 0;
 	cpu_new_thread = task_thread_info(p);
-	cpu_set(cpu, cpu_callout_map);
 
 	if (tlb_type == hypervisor) {
 		/* Alloc the mondo queues, cpu will load them.  */
 		sun4v_init_mondo_queues(0, cpu, 1, 0);
 
-		prom_startcpu_cpuid(cpu, entry, cookie);
+#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
+		if (ldom_domaining_enabled)
+			ldom_startcpu_cpuid(cpu,
+					    (unsigned long) cpu_new_thread);
+		else
+#endif
+			prom_startcpu_cpuid(cpu, entry, cookie);
 	} else {
 		struct device_node *dp = of_find_node_by_cpuid(cpu);
 
 		prom_startcpu(dp->node, entry, cookie);
 	}
 
-	for (timeout = 0; timeout < 5000000; timeout++) {
+	for (timeout = 0; timeout < 50000; timeout++) {
 		if (callin_flag)
 			break;
 		udelay(100);
@@ -313,11 +385,15 @@
 		ret = 0;
 	} else {
 		printk("Processor %d is stuck.\n", cpu);
-		cpu_clear(cpu, cpu_callout_map);
 		ret = -ENODEV;
 	}
 	cpu_new_thread = NULL;
 
+	if (tb->hdesc) {
+		kfree(tb->hdesc);
+		tb->hdesc = NULL;
+	}
+
 	return ret;
 }
 
@@ -720,7 +796,6 @@
 	int wait;
 };
 
-static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
 static struct call_data_struct *call_data;
 
 extern unsigned long xcall_call_function;
@@ -1152,34 +1227,14 @@
 	preempt_enable();
 }
 
-void __init smp_tick_init(void)
-{
-	boot_cpu_id = hard_smp_processor_id();
-}
-
 /* /proc/profile writes can call this, don't __init it please. */
 int setup_profiling_timer(unsigned int multiplier)
 {
 	return -EINVAL;
 }
 
-/* Constrain the number of cpus to max_cpus.  */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	if (num_possible_cpus() > max_cpus) {
-		for_each_possible_cpu(i) {
-			if (i != boot_cpu_id) {
-				cpu_clear(i, phys_cpu_present_map);
-				cpu_clear(i, cpu_present_map);
-				if (num_possible_cpus() <= max_cpus)
-					break;
-			}
-		}
-	}
-
-	cpu_data(boot_cpu_id).udelay_val = loops_per_jiffy;
 }
 
 void __devinit smp_prepare_boot_cpu(void)
@@ -1190,30 +1245,32 @@
 {
 	unsigned int i;
 
-	for_each_possible_cpu(i) {
+	for_each_present_cpu(i) {
 		unsigned int j;
 
+		cpus_clear(cpu_core_map[i]);
 		if (cpu_data(i).core_id == 0) {
 			cpu_set(i, cpu_core_map[i]);
 			continue;
 		}
 
-		for_each_possible_cpu(j) {
+		for_each_present_cpu(j) {
 			if (cpu_data(i).core_id ==
 			    cpu_data(j).core_id)
 				cpu_set(j, cpu_core_map[i]);
 		}
 	}
 
-	for_each_possible_cpu(i) {
+	for_each_present_cpu(i) {
 		unsigned int j;
 
+		cpus_clear(cpu_sibling_map[i]);
 		if (cpu_data(i).proc_id == -1) {
 			cpu_set(i, cpu_sibling_map[i]);
 			continue;
 		}
 
-		for_each_possible_cpu(j) {
+		for_each_present_cpu(j) {
 			if (cpu_data(i).proc_id ==
 			    cpu_data(j).proc_id)
 				cpu_set(j, cpu_sibling_map[i]);
@@ -1242,18 +1299,112 @@
 	return ret;
 }
 
-void __init smp_cpus_done(unsigned int max_cpus)
+#ifdef CONFIG_HOTPLUG_CPU
+void cpu_play_dead(void)
 {
-	unsigned long bogosum = 0;
+	int cpu = smp_processor_id();
+	unsigned long pstate;
+
+	idle_task_exit();
+
+	if (tlb_type == hypervisor) {
+		struct trap_per_cpu *tb = &trap_block[cpu];
+
+		sun4v_cpu_qconf(HV_CPU_QUEUE_CPU_MONDO,
+				tb->cpu_mondo_pa, 0);
+		sun4v_cpu_qconf(HV_CPU_QUEUE_DEVICE_MONDO,
+				tb->dev_mondo_pa, 0);
+		sun4v_cpu_qconf(HV_CPU_QUEUE_RES_ERROR,
+				tb->resum_mondo_pa, 0);
+		sun4v_cpu_qconf(HV_CPU_QUEUE_NONRES_ERROR,
+				tb->nonresum_mondo_pa, 0);
+	}
+
+	cpu_clear(cpu, smp_commenced_mask);
+	membar_safe("#Sync");
+
+	local_irq_disable();
+
+	__asm__ __volatile__(
+		"rdpr	%%pstate, %0\n\t"
+		"wrpr	%0, %1, %%pstate"
+		: "=r" (pstate)
+		: "i" (PSTATE_IE));
+
+	while (1)
+		barrier();
+}
+
+int __cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+	cpuinfo_sparc *c;
 	int i;
 
-	for_each_online_cpu(i)
-		bogosum += cpu_data(i).udelay_val;
-	printk("Total of %ld processors activated "
-	       "(%lu.%02lu BogoMIPS).\n",
-	       (long) num_online_cpus(),
-	       bogosum/(500000/HZ),
-	       (bogosum/(5000/HZ))%100);
+	for_each_cpu_mask(i, cpu_core_map[cpu])
+		cpu_clear(cpu, cpu_core_map[i]);
+	cpus_clear(cpu_core_map[cpu]);
+
+	for_each_cpu_mask(i, cpu_sibling_map[cpu])
+		cpu_clear(cpu, cpu_sibling_map[i]);
+	cpus_clear(cpu_sibling_map[cpu]);
+
+	c = &cpu_data(cpu);
+
+	c->core_id = 0;
+	c->proc_id = -1;
+
+	spin_lock(&call_lock);
+	cpu_clear(cpu, cpu_online_map);
+	spin_unlock(&call_lock);
+
+	smp_wmb();
+
+	/* Make sure no interrupts point to this cpu.  */
+	fixup_irqs();
+
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+
+	return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	int i;
+
+	for (i = 0; i < 100; i++) {
+		smp_rmb();
+		if (!cpu_isset(cpu, smp_commenced_mask))
+			break;
+		msleep(100);
+	}
+	if (cpu_isset(cpu, smp_commenced_mask)) {
+		printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+	} else {
+#if defined(CONFIG_SUN_LDOMS)
+		unsigned long hv_err;
+		int limit = 100;
+
+		do {
+			hv_err = sun4v_cpu_stop(cpu);
+			if (hv_err == HV_EOK) {
+				cpu_clear(cpu, cpu_present_map);
+				break;
+			}
+		} while (--limit > 0);
+		if (limit <= 0) {
+			printk(KERN_ERR "sun4v_cpu_stop() fails err=%lu\n",
+			       hv_err);
+		}
+#endif
+	}
+}
+#endif
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
 }
 
 void smp_send_reschedule(int cpu)
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 6fa7616..719d676 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,7 +1,6 @@
-/* $Id: sparc64_ksyms.c,v 1.121 2002/02/09 19:49:31 davem Exp $
- * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
+/* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
  * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
  */
@@ -28,7 +27,6 @@
 #include <net/compat.h>
 
 #include <asm/oplib.h>
-#include <asm/delay.h>
 #include <asm/system.h>
 #include <asm/auxio.h>
 #include <asm/pgtable.h>
@@ -124,10 +122,6 @@
 EXPORT_SYMBOL(__write_unlock);
 EXPORT_SYMBOL(__write_trylock);
 
-/* CPU online map and active count.  */
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(phys_cpu_present_map);
-
 EXPORT_SYMBOL(smp_call_function);
 #endif /* CONFIG_SMP */
 
@@ -330,12 +324,6 @@
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(strncmp);
 
-/* Delay routines. */
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__delay);
-
 void VISenter(void);
 /* RAID code needs this */
 EXPORT_SYMBOL(VISenter);
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
index cdb1477..52816c7 100644
--- a/arch/sparc64/kernel/sysfs.c
+++ b/arch/sparc64/kernel/sysfs.c
@@ -193,7 +193,6 @@
 }
 
 SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick);
-SHOW_CPUDATA_ULONG_NAME(udelay_val, udelay_val);
 SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size);
 SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size);
 SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size);
@@ -203,7 +202,6 @@
 
 static struct sysdev_attribute cpu_core_attrs[] = {
 	_SYSDEV_ATTR(clock_tick,          0444, show_clock_tick, NULL),
-	_SYSDEV_ATTR(udelay_val,          0444, show_udelay_val, NULL),
 	_SYSDEV_ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
 	_SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
 	_SYSDEV_ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index a31a043..62e316a 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -849,9 +849,6 @@
 {
 	struct device_node *dp;
 	unsigned long clock;
-#ifdef CONFIG_SMP
-	extern void smp_tick_init(void);
-#endif
 
 	dp = of_find_node_by_path("/");
 	if (tlb_type == spitfire) {
@@ -874,10 +871,6 @@
 		clock = of_getintprop_default(dp, "stick-frequency", 0);
 	}
 
-#ifdef CONFIG_SMP
-	smp_tick_init();
-#endif
-
 	return clock;
 }
 
@@ -1038,10 +1031,31 @@
 	sparc64_clockevent.mult = mult;
 }
 
+static unsigned long tb_ticks_per_usec __read_mostly;
+
+void __delay(unsigned long loops)
+{
+	unsigned long bclock, now;
+
+	bclock = tick_ops->get_tick();
+	do {
+		now = tick_ops->get_tick();
+	} while ((now-bclock) < loops);
+}
+EXPORT_SYMBOL(__delay);
+
+void udelay(unsigned long usecs)
+{
+	__delay(tb_ticks_per_usec * usecs);
+}
+EXPORT_SYMBOL(udelay);
+
 void __init time_init(void)
 {
 	unsigned long clock = sparc64_init_timers();
 
+	tb_ticks_per_usec = clock / USEC_PER_SEC;
+
 	timer_ticks_per_nsec_quotient =
 		clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT);
 
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 00a9e32..6ef2d29 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -2225,6 +2225,7 @@
 	notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
 	__asm__ __volatile__("flushw");
 	__show_regs(regs);
+	add_taint(TAINT_DIE);
 	if (regs->tstate & TSTATE_PRIV) {
 		struct reg_window *rw = (struct reg_window *)
 			(regs->u_regs[UREG_FP] + STACK_BIAS);
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
new file mode 100644
index 0000000..49569b4
--- /dev/null
+++ b/arch/sparc64/kernel/vio.c
@@ -0,0 +1,395 @@
+/* vio.c: Virtual I/O channel devices probing infrastructure.
+ *
+ *    Copyright (c) 2003-2005 IBM Corp.
+ *     Dave Engebretsen engebret@us.ibm.com
+ *     Santiago Leon santil@us.ibm.com
+ *     Hollis Blanchard <hollisb@us.ibm.com>
+ *     Stephen Rothwell
+ *
+ * Adapted to sparc64 by David S. Miller davem@davemloft.net
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+
+#include <asm/mdesc.h>
+#include <asm/vio.h>
+
+static inline int find_in_proplist(const char *list, const char *match,
+				   int len)
+{
+	while (len > 0) {
+		int l;
+
+		if (!strcmp(list, match))
+			return 1;
+		l = strlen(list) + 1;
+		list += l;
+		len -= l;
+	}
+	return 0;
+}
+
+static const struct vio_device_id *vio_match_device(
+	const struct vio_device_id *matches,
+	const struct vio_dev *dev)
+{
+	const char *type, *compat;
+	int len;
+
+	type = dev->type;
+	compat = dev->compat;
+	len = dev->compat_len;
+
+	while (matches->type[0] || matches->compat[0]) {
+		int match = 1;
+		if (matches->type[0])
+			match &= !strcmp(matches->type, type);
+
+		if (matches->compat[0]) {
+			match &= len &&
+				find_in_proplist(compat, matches->compat, len);
+		}
+		if (match)
+			return matches;
+		matches++;
+	}
+	return NULL;
+}
+
+static int vio_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct vio_driver *vio_drv = to_vio_driver(drv);
+	const struct vio_device_id *matches = vio_drv->id_table;
+
+	if (!matches)
+		return 0;
+
+	return vio_match_device(matches, vio_dev) != NULL;
+}
+
+static int vio_device_probe(struct device *dev)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	struct vio_driver *drv = to_vio_driver(dev->driver);
+	const struct vio_device_id *id;
+	int error = -ENODEV;
+
+	if (drv->probe) {
+		id = vio_match_device(drv->id_table, vdev);
+		if (id)
+			error = drv->probe(vdev, id);
+	}
+
+	return error;
+}
+
+static int vio_device_remove(struct device *dev)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	struct vio_driver *drv = to_vio_driver(dev->driver);
+
+	if (drv->remove)
+		return drv->remove(vdev);
+
+	return 1;
+}
+
+static ssize_t devspec_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	const char *str = "none";
+
+	if (!strcmp(vdev->type, "network"))
+		str = "vnet";
+	else if (!strcmp(vdev->type, "block"))
+		str = "vdisk";
+
+	return sprintf(buf, "%s\n", str);
+}
+
+static ssize_t type_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	return sprintf(buf, "%s\n", vdev->type);
+}
+
+static struct device_attribute vio_dev_attrs[] = {
+	__ATTR_RO(devspec),
+	__ATTR_RO(type),
+	__ATTR_NULL
+};
+
+static struct bus_type vio_bus_type = {
+	.name		= "vio",
+	.dev_attrs	= vio_dev_attrs,
+	.match		= vio_bus_match,
+	.probe		= vio_device_probe,
+	.remove		= vio_device_remove,
+};
+
+int vio_register_driver(struct vio_driver *viodrv)
+{
+	viodrv->driver.bus = &vio_bus_type;
+
+	return driver_register(&viodrv->driver);
+}
+EXPORT_SYMBOL(vio_register_driver);
+
+void vio_unregister_driver(struct vio_driver *viodrv)
+{
+	driver_unregister(&viodrv->driver);
+}
+EXPORT_SYMBOL(vio_unregister_driver);
+
+static void __devinit vio_dev_release(struct device *dev)
+{
+	kfree(to_vio_dev(dev));
+}
+
+static ssize_t
+show_pciobppath_attr(struct device *dev, struct device_attribute *attr,
+		     char *buf)
+{
+	struct vio_dev *vdev;
+	struct device_node *dp;
+
+	vdev = to_vio_dev(dev);
+	dp = vdev->dp;
+
+	return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name);
+}
+
+static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH,
+		   show_pciobppath_attr, NULL);
+
+struct device_node *cdev_node;
+
+static struct vio_dev *root_vdev;
+static u64 cdev_cfg_handle;
+
+static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
+				  struct vio_dev *vdev)
+{
+	u64 a;
+
+	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+		const u64 *chan_id;
+		const u64 *irq;
+		u64 target;
+
+		target = mdesc_arc_target(hp, a);
+
+		irq = mdesc_get_property(hp, target, "tx-ino", NULL);
+		if (irq)
+			vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
+
+		irq = mdesc_get_property(hp, target, "rx-ino", NULL);
+		if (irq)
+			vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
+
+		chan_id = mdesc_get_property(hp, target, "id", NULL);
+		if (chan_id)
+			vdev->channel_id = *chan_id;
+	}
+}
+
+static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
+				      struct device *parent)
+{
+	const char *type, *compat;
+	struct device_node *dp;
+	struct vio_dev *vdev;
+	int err, tlen, clen;
+
+	type = mdesc_get_property(hp, mp, "device-type", &tlen);
+	if (!type) {
+		type = mdesc_get_property(hp, mp, "name", &tlen);
+		if (!type) {
+			type = mdesc_node_name(hp, mp);
+			tlen = strlen(type) + 1;
+		}
+	}
+	if (tlen > VIO_MAX_TYPE_LEN) {
+		printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
+		       type);
+		return NULL;
+	}
+
+	compat = mdesc_get_property(hp, mp, "device-type", &clen);
+	if (!compat) {
+		clen = 0;
+	} else if (clen > VIO_MAX_COMPAT_LEN) {
+		printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
+		       clen, type);
+		return NULL;
+	}
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev) {
+		printk(KERN_ERR "VIO: Could not allocate vio_dev\n");
+		return NULL;
+	}
+
+	vdev->mp = mp;
+	memcpy(vdev->type, type, tlen);
+	if (compat)
+		memcpy(vdev->compat, compat, clen);
+	else
+		memset(vdev->compat, 0, sizeof(vdev->compat));
+	vdev->compat_len = clen;
+
+	vdev->channel_id = ~0UL;
+	vdev->tx_irq = ~0;
+	vdev->rx_irq = ~0;
+
+	vio_fill_channel_info(hp, mp, vdev);
+
+	snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp);
+	vdev->dev.parent = parent;
+	vdev->dev.bus = &vio_bus_type;
+	vdev->dev.release = vio_dev_release;
+
+	if (parent == NULL) {
+		dp = cdev_node;
+	} else if (to_vio_dev(parent) == root_vdev) {
+		dp = of_get_next_child(cdev_node, NULL);
+		while (dp) {
+			if (!strcmp(dp->type, type))
+				break;
+
+			dp = of_get_next_child(cdev_node, dp);
+		}
+	} else {
+		dp = to_vio_dev(parent)->dp;
+	}
+	vdev->dp = dp;
+
+	err = device_register(&vdev->dev);
+	if (err) {
+		printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
+		       vdev->dev.bus_id, err);
+		kfree(vdev);
+		return NULL;
+	}
+	if (vdev->dp)
+		err = sysfs_create_file(&vdev->dev.kobj,
+					&dev_attr_obppath.attr);
+
+	return vdev;
+}
+
+static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent)
+{
+	u64 a;
+
+	mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) {
+		struct vio_dev *vdev;
+		u64 target;
+
+		target = mdesc_arc_target(hp, a);
+		vdev = vio_create_one(hp, target, &parent->dev);
+		if (vdev)
+			walk_tree(hp, target, vdev);
+	}
+}
+
+static void create_devices(struct mdesc_handle *hp, u64 root)
+{
+	u64 mp;
+
+	root_vdev = vio_create_one(hp, root, NULL);
+	if (!root_vdev) {
+		printk(KERN_ERR "VIO: Coult not create root device.\n");
+		return;
+	}
+
+	walk_tree(hp, root, root_vdev);
+
+	/* Domain services is odd as it doesn't sit underneath the
+	 * channel-devices node, so we plug it in manually.
+	 */
+	mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services");
+	if (mp != MDESC_NODE_NULL) {
+		struct vio_dev *parent = vio_create_one(hp, mp,
+							&root_vdev->dev);
+
+		if (parent)
+			walk_tree(hp, mp, parent);
+	}
+}
+
+const char *channel_devices_node = "channel-devices";
+const char *channel_devices_compat = "SUNW,sun4v-channel-devices";
+const char *cfg_handle_prop = "cfg-handle";
+
+static int __init vio_init(void)
+{
+	struct mdesc_handle *hp;
+	const char *compat;
+	const u64 *cfg_handle;
+	int err, len;
+	u64 root;
+
+	err = bus_register(&vio_bus_type);
+	if (err) {
+		printk(KERN_ERR "VIO: Could not register bus type err=%d\n",
+		       err);
+		return err;
+	}
+
+	hp = mdesc_grab();
+	if (!hp)
+		return 0;
+
+	root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node);
+	if (root == MDESC_NODE_NULL) {
+		printk(KERN_INFO "VIO: No channel-devices MDESC node.\n");
+		mdesc_release(hp);
+		return 0;
+	}
+
+	cdev_node = of_find_node_by_name(NULL, "channel-devices");
+	err = -ENODEV;
+	if (!cdev_node) {
+		printk(KERN_INFO "VIO: No channel-devices OBP node.\n");
+		goto out_release;
+	}
+
+	compat = mdesc_get_property(hp, root, "compatible", &len);
+	if (!compat) {
+		printk(KERN_ERR "VIO: Channel devices lacks compatible "
+		       "property\n");
+		goto out_release;
+	}
+	if (!find_in_proplist(compat, channel_devices_compat, len)) {
+		printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
+		       "compat entry.\n", channel_devices_compat);
+		goto out_release;
+	}
+
+	cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL);
+	if (!cfg_handle) {
+		printk(KERN_ERR "VIO: Channel devices lacks %s property\n",
+		       cfg_handle_prop);
+		goto out_release;
+	}
+
+	cdev_cfg_handle = *cfg_handle;
+
+	create_devices(hp, root);
+
+	mdesc_release(hp);
+
+	return 0;
+
+out_release:
+	mdesc_release(hp);
+	return err;
+}
+
+postcore_initcall(vio_init);
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c
new file mode 100644
index 0000000..15613ad
--- /dev/null
+++ b/arch/sparc64/kernel/viohs.c
@@ -0,0 +1,792 @@
+/* viohs.c: LDOM Virtual I/O handshake helper layer.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/ldc.h>
+#include <asm/vio.h>
+
+int vio_ldc_send(struct vio_driver_state *vio, void *data, int len)
+{
+	int err, limit = 1000;
+
+	err = -EINVAL;
+	while (limit-- > 0) {
+		err = ldc_write(vio->lp, data, len);
+		if (!err || (err != -EAGAIN))
+			break;
+		udelay(1);
+	}
+
+	return err;
+}
+EXPORT_SYMBOL(vio_ldc_send);
+
+static int send_ctrl(struct vio_driver_state *vio,
+		     struct vio_msg_tag *tag, int len)
+{
+	tag->sid = vio_send_sid(vio);
+	return vio_ldc_send(vio, tag, len);
+}
+
+static void init_tag(struct vio_msg_tag *tag, u8 type, u8 stype, u16 stype_env)
+{
+	tag->type = type;
+	tag->stype = stype;
+	tag->stype_env = stype_env;
+}
+
+static int send_version(struct vio_driver_state *vio, u16 major, u16 minor)
+{
+	struct vio_ver_info pkt;
+
+	vio->_local_sid = (u32) sched_clock();
+
+	memset(&pkt, 0, sizeof(pkt));
+	init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_VER_INFO);
+	pkt.major = major;
+	pkt.minor = minor;
+	pkt.dev_class = vio->dev_class;
+
+	viodbg(HS, "SEND VERSION INFO maj[%u] min[%u] devclass[%u]\n",
+	       major, minor, vio->dev_class);
+
+	return send_ctrl(vio, &pkt.tag, sizeof(pkt));
+}
+
+static int start_handshake(struct vio_driver_state *vio)
+{
+	int err;
+
+	viodbg(HS, "START HANDSHAKE\n");
+
+	vio->hs_state = VIO_HS_INVALID;
+
+	err = send_version(vio,
+			   vio->ver_table[0].major,
+			   vio->ver_table[0].minor);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+void vio_link_state_change(struct vio_driver_state *vio, int event)
+{
+	if (event == LDC_EVENT_UP) {
+		vio->hs_state = VIO_HS_INVALID;
+
+		switch (vio->dev_class) {
+		case VDEV_NETWORK:
+		case VDEV_NETWORK_SWITCH:
+			vio->dr_state = (VIO_DR_STATE_TXREQ |
+					 VIO_DR_STATE_RXREQ);
+			break;
+
+		case VDEV_DISK:
+			vio->dr_state = VIO_DR_STATE_TXREQ;
+			break;
+		case VDEV_DISK_SERVER:
+			vio->dr_state = VIO_DR_STATE_RXREQ;
+			break;
+		}
+		start_handshake(vio);
+	}
+}
+EXPORT_SYMBOL(vio_link_state_change);
+
+static int handshake_failure(struct vio_driver_state *vio)
+{
+	struct vio_dring_state *dr;
+
+	/* XXX Put policy here...  Perhaps start a timer to fire
+	 * XXX in 100 ms, which will bring the link up and retry
+	 * XXX the handshake.
+	 */
+
+	viodbg(HS, "HANDSHAKE FAILURE\n");
+
+	vio->dr_state &= ~(VIO_DR_STATE_TXREG |
+			   VIO_DR_STATE_RXREG);
+
+	dr = &vio->drings[VIO_DRIVER_RX_RING];
+	memset(dr, 0, sizeof(*dr));
+
+	kfree(vio->desc_buf);
+	vio->desc_buf = NULL;
+	vio->desc_buf_len = 0;
+
+	vio->hs_state = VIO_HS_INVALID;
+
+	return -ECONNRESET;
+}
+
+static int process_unknown(struct vio_driver_state *vio, void *arg)
+{
+	struct vio_msg_tag *pkt = arg;
+
+	viodbg(HS, "UNKNOWN CONTROL [%02x:%02x:%04x:%08x]\n",
+	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+
+	printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n",
+	       vio->vdev->channel_id);
+
+	ldc_disconnect(vio->lp);
+
+	return -ECONNRESET;
+}
+
+static int send_dreg(struct vio_driver_state *vio)
+{
+	struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_TX_RING];
+	union {
+		struct vio_dring_register pkt;
+		char all[sizeof(struct vio_dring_register) +
+			 (sizeof(struct ldc_trans_cookie) *
+			  dr->ncookies)];
+	} u;
+	int i;
+
+	memset(&u, 0, sizeof(u));
+	init_tag(&u.pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_DRING_REG);
+	u.pkt.dring_ident = 0;
+	u.pkt.num_descr = dr->num_entries;
+	u.pkt.descr_size = dr->entry_size;
+	u.pkt.options = VIO_TX_DRING;
+	u.pkt.num_cookies = dr->ncookies;
+
+	viodbg(HS, "SEND DRING_REG INFO ndesc[%u] dsz[%u] opt[0x%x] "
+	       "ncookies[%u]\n",
+	       u.pkt.num_descr, u.pkt.descr_size, u.pkt.options,
+	       u.pkt.num_cookies);
+
+	for (i = 0; i < dr->ncookies; i++) {
+		u.pkt.cookies[i] = dr->cookies[i];
+
+		viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
+		       i,
+		       (unsigned long long) u.pkt.cookies[i].cookie_addr,
+		       (unsigned long long) u.pkt.cookies[i].cookie_size);
+	}
+
+	return send_ctrl(vio, &u.pkt.tag, sizeof(u));
+}
+
+static int send_rdx(struct vio_driver_state *vio)
+{
+	struct vio_rdx pkt;
+
+	memset(&pkt, 0, sizeof(pkt));
+
+	init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_RDX);
+
+	viodbg(HS, "SEND RDX INFO\n");
+
+	return send_ctrl(vio, &pkt.tag, sizeof(pkt));
+}
+
+static int send_attr(struct vio_driver_state *vio)
+{
+	return vio->ops->send_attr(vio);
+}
+
+static struct vio_version *find_by_major(struct vio_driver_state *vio,
+					 u16 major)
+{
+	struct vio_version *ret = NULL;
+	int i;
+
+	for (i = 0; i < vio->ver_table_entries; i++) {
+		struct vio_version *v = &vio->ver_table[i];
+		if (v->major <= major) {
+			ret = v;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int process_ver_info(struct vio_driver_state *vio,
+			    struct vio_ver_info *pkt)
+{
+	struct vio_version *vap;
+	int err;
+
+	viodbg(HS, "GOT VERSION INFO maj[%u] min[%u] devclass[%u]\n",
+	       pkt->major, pkt->minor, pkt->dev_class);
+
+	if (vio->hs_state != VIO_HS_INVALID) {
+		/* XXX Perhaps invoke start_handshake? XXX */
+		memset(&vio->ver, 0, sizeof(vio->ver));
+		vio->hs_state = VIO_HS_INVALID;
+	}
+
+	vap = find_by_major(vio, pkt->major);
+
+	vio->_peer_sid = pkt->tag.sid;
+
+	if (!vap) {
+		pkt->tag.stype = VIO_SUBTYPE_NACK;
+		pkt->major = 0;
+		pkt->minor = 0;
+		viodbg(HS, "SEND VERSION NACK maj[0] min[0]\n");
+		err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+	} else if (vap->major != pkt->major) {
+		pkt->tag.stype = VIO_SUBTYPE_NACK;
+		pkt->major = vap->major;
+		pkt->minor = vap->minor;
+		viodbg(HS, "SEND VERSION NACK maj[%u] min[%u]\n",
+		       pkt->major, pkt->minor);
+		err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+	} else {
+		struct vio_version ver = {
+			.major = pkt->major,
+			.minor = pkt->minor,
+		};
+		if (ver.minor > vap->minor)
+			ver.minor = vap->minor;
+		pkt->minor = ver.minor;
+		pkt->tag.stype = VIO_SUBTYPE_ACK;
+		viodbg(HS, "SEND VERSION ACK maj[%u] min[%u]\n",
+		       pkt->major, pkt->minor);
+		err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+		if (err > 0) {
+			vio->ver = ver;
+			vio->hs_state = VIO_HS_GOTVERS;
+		}
+	}
+	if (err < 0)
+		return handshake_failure(vio);
+
+	return 0;
+}
+
+static int process_ver_ack(struct vio_driver_state *vio,
+			   struct vio_ver_info *pkt)
+{
+	viodbg(HS, "GOT VERSION ACK maj[%u] min[%u] devclass[%u]\n",
+	       pkt->major, pkt->minor, pkt->dev_class);
+
+	if (vio->hs_state & VIO_HS_GOTVERS) {
+		if (vio->ver.major != pkt->major ||
+		    vio->ver.minor != pkt->minor) {
+			pkt->tag.stype = VIO_SUBTYPE_NACK;
+			(void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+			return handshake_failure(vio);
+		}
+	} else {
+		vio->ver.major = pkt->major;
+		vio->ver.minor = pkt->minor;
+		vio->hs_state = VIO_HS_GOTVERS;
+	}
+
+	switch (vio->dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_DISK:
+		if (send_attr(vio) < 0)
+			return handshake_failure(vio);
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int process_ver_nack(struct vio_driver_state *vio,
+			    struct vio_ver_info *pkt)
+{
+	struct vio_version *nver;
+
+	viodbg(HS, "GOT VERSION NACK maj[%u] min[%u] devclass[%u]\n",
+	       pkt->major, pkt->minor, pkt->dev_class);
+
+	if ((pkt->major == 0 && pkt->minor == 0) ||
+	    !(nver = find_by_major(vio, pkt->major)))
+		return handshake_failure(vio);
+
+	if (send_version(vio, nver->major, nver->minor) < 0)
+		return handshake_failure(vio);
+
+	return 0;
+}
+
+static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt)
+{
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return process_ver_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return process_ver_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return process_ver_nack(vio, pkt);
+
+	default:
+		return handshake_failure(vio);
+	};
+}
+
+static int process_attr(struct vio_driver_state *vio, void *pkt)
+{
+	int err;
+
+	if (!(vio->hs_state & VIO_HS_GOTVERS))
+		return handshake_failure(vio);
+
+	err = vio->ops->handle_attr(vio, pkt);
+	if (err < 0) {
+		return handshake_failure(vio);
+	} else {
+		vio->hs_state |= VIO_HS_GOT_ATTR;
+
+		if ((vio->dr_state & VIO_DR_STATE_TXREQ) &&
+		    !(vio->hs_state & VIO_HS_SENT_DREG)) {
+			if (send_dreg(vio) < 0)
+				return handshake_failure(vio);
+
+			vio->hs_state |= VIO_HS_SENT_DREG;
+		}
+	}
+	return 0;
+}
+
+static int all_drings_registered(struct vio_driver_state *vio)
+{
+	int need_rx, need_tx;
+
+	need_rx = (vio->dr_state & VIO_DR_STATE_RXREQ);
+	need_tx = (vio->dr_state & VIO_DR_STATE_TXREQ);
+
+	if (need_rx &&
+	    !(vio->dr_state & VIO_DR_STATE_RXREG))
+		return 0;
+
+	if (need_tx &&
+	    !(vio->dr_state & VIO_DR_STATE_TXREG))
+		return 0;
+
+	return 1;
+}
+
+static int process_dreg_info(struct vio_driver_state *vio,
+			     struct vio_dring_register *pkt)
+{
+	struct vio_dring_state *dr;
+	int i, len;
+
+	viodbg(HS, "GOT DRING_REG INFO ident[%llx] "
+	       "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+	       (unsigned long long) pkt->dring_ident,
+	       pkt->num_descr, pkt->descr_size, pkt->options,
+	       pkt->num_cookies);
+
+	if (!(vio->dr_state & VIO_DR_STATE_RXREQ))
+		goto send_nack;
+
+	if (vio->dr_state & VIO_DR_STATE_RXREG)
+		goto send_nack;
+
+	vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
+	if (!vio->desc_buf)
+		goto send_nack;
+
+	vio->desc_buf_len = pkt->descr_size;
+
+	dr = &vio->drings[VIO_DRIVER_RX_RING];
+
+	dr->num_entries = pkt->num_descr;
+	dr->entry_size = pkt->descr_size;
+	dr->ncookies = pkt->num_cookies;
+	for (i = 0; i < dr->ncookies; i++) {
+		dr->cookies[i] = pkt->cookies[i];
+
+		viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
+		       i,
+		       (unsigned long long)
+		       pkt->cookies[i].cookie_addr,
+		       (unsigned long long)
+		       pkt->cookies[i].cookie_size);
+	}
+
+	pkt->tag.stype = VIO_SUBTYPE_ACK;
+	pkt->dring_ident = ++dr->ident;
+
+	viodbg(HS, "SEND DRING_REG ACK ident[%llx]\n",
+	       (unsigned long long) pkt->dring_ident);
+
+	len = (sizeof(*pkt) +
+	       (dr->ncookies * sizeof(struct ldc_trans_cookie)));
+	if (send_ctrl(vio, &pkt->tag, len) < 0)
+		goto send_nack;
+
+	vio->dr_state |= VIO_DR_STATE_RXREG;
+
+	return 0;
+
+send_nack:
+	pkt->tag.stype = VIO_SUBTYPE_NACK;
+	viodbg(HS, "SEND DRING_REG NACK\n");
+	(void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+
+	return handshake_failure(vio);
+}
+
+static int process_dreg_ack(struct vio_driver_state *vio,
+			    struct vio_dring_register *pkt)
+{
+	struct vio_dring_state *dr;
+
+	viodbg(HS, "GOT DRING_REG ACK ident[%llx] "
+	       "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+	       (unsigned long long) pkt->dring_ident,
+	       pkt->num_descr, pkt->descr_size, pkt->options,
+	       pkt->num_cookies);
+
+	dr = &vio->drings[VIO_DRIVER_TX_RING];
+
+	if (!(vio->dr_state & VIO_DR_STATE_TXREQ))
+		return handshake_failure(vio);
+
+	dr->ident = pkt->dring_ident;
+	vio->dr_state |= VIO_DR_STATE_TXREG;
+
+	if (all_drings_registered(vio)) {
+		if (send_rdx(vio) < 0)
+			return handshake_failure(vio);
+		vio->hs_state = VIO_HS_SENT_RDX;
+	}
+	return 0;
+}
+
+static int process_dreg_nack(struct vio_driver_state *vio,
+			     struct vio_dring_register *pkt)
+{
+	viodbg(HS, "GOT DRING_REG NACK ident[%llx] "
+	       "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+	       (unsigned long long) pkt->dring_ident,
+	       pkt->num_descr, pkt->descr_size, pkt->options,
+	       pkt->num_cookies);
+
+	return handshake_failure(vio);
+}
+
+static int process_dreg(struct vio_driver_state *vio,
+			struct vio_dring_register *pkt)
+{
+	if (!(vio->hs_state & VIO_HS_GOTVERS))
+		return handshake_failure(vio);
+
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return process_dreg_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return process_dreg_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return process_dreg_nack(vio, pkt);
+
+	default:
+		return handshake_failure(vio);
+	}
+}
+
+static int process_dunreg(struct vio_driver_state *vio,
+			  struct vio_dring_unregister *pkt)
+{
+	struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_RX_RING];
+
+	viodbg(HS, "GOT DRING_UNREG\n");
+
+	if (pkt->dring_ident != dr->ident)
+		return 0;
+
+	vio->dr_state &= ~VIO_DR_STATE_RXREG;
+
+	memset(dr, 0, sizeof(*dr));
+
+	kfree(vio->desc_buf);
+	vio->desc_buf = NULL;
+	vio->desc_buf_len = 0;
+
+	return 0;
+}
+
+static int process_rdx_info(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	viodbg(HS, "GOT RDX INFO\n");
+
+	pkt->tag.stype = VIO_SUBTYPE_ACK;
+	viodbg(HS, "SEND RDX ACK\n");
+	if (send_ctrl(vio, &pkt->tag, sizeof(*pkt)) < 0)
+		return handshake_failure(vio);
+
+	vio->hs_state |= VIO_HS_SENT_RDX_ACK;
+	return 0;
+}
+
+static int process_rdx_ack(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	viodbg(HS, "GOT RDX ACK\n");
+
+	if (!(vio->hs_state & VIO_HS_SENT_RDX))
+		return handshake_failure(vio);
+
+	vio->hs_state |= VIO_HS_GOT_RDX_ACK;
+	return 0;
+}
+
+static int process_rdx_nack(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	viodbg(HS, "GOT RDX NACK\n");
+
+	return handshake_failure(vio);
+}
+
+static int process_rdx(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	if (!all_drings_registered(vio))
+		handshake_failure(vio);
+
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return process_rdx_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return process_rdx_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return process_rdx_nack(vio, pkt);
+
+	default:
+		return handshake_failure(vio);
+	}
+}
+
+int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt)
+{
+	struct vio_msg_tag *tag = pkt;
+	u8 prev_state = vio->hs_state;
+	int err;
+
+	switch (tag->stype_env) {
+	case VIO_VER_INFO:
+		err = process_ver(vio, pkt);
+		break;
+
+	case VIO_ATTR_INFO:
+		err = process_attr(vio, pkt);
+		break;
+
+	case VIO_DRING_REG:
+		err = process_dreg(vio, pkt);
+		break;
+
+	case VIO_DRING_UNREG:
+		err = process_dunreg(vio, pkt);
+		break;
+
+	case VIO_RDX:
+		err = process_rdx(vio, pkt);
+		break;
+
+	default:
+		err = process_unknown(vio, pkt);
+		break;
+	}
+	if (!err &&
+	    vio->hs_state != prev_state &&
+	    (vio->hs_state & VIO_HS_COMPLETE))
+		vio->ops->handshake_complete(vio);
+
+	return err;
+}
+EXPORT_SYMBOL(vio_control_pkt_engine);
+
+void vio_conn_reset(struct vio_driver_state *vio)
+{
+}
+EXPORT_SYMBOL(vio_conn_reset);
+
+/* The issue is that the Solaris virtual disk server just mirrors the
+ * SID values it gets from the client peer.  So we work around that
+ * here in vio_{validate,send}_sid() so that the drivers don't need
+ * to be aware of this crap.
+ */
+int vio_validate_sid(struct vio_driver_state *vio, struct vio_msg_tag *tp)
+{
+	u32 sid;
+
+	/* Always let VERSION+INFO packets through unchecked, they
+	 * define the new SID.
+	 */
+	if (tp->type == VIO_TYPE_CTRL &&
+	    tp->stype == VIO_SUBTYPE_INFO &&
+	    tp->stype_env == VIO_VER_INFO)
+		return 0;
+
+	/* Ok, now figure out which SID to use.  */
+	switch (vio->dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_NETWORK_SWITCH:
+	case VDEV_DISK_SERVER:
+	default:
+		sid = vio->_peer_sid;
+		break;
+
+	case VDEV_DISK:
+		sid = vio->_local_sid;
+		break;
+	}
+
+	if (sid == tp->sid)
+		return 0;
+	viodbg(DATA, "BAD SID tag->sid[%08x] peer_sid[%08x] local_sid[%08x]\n",
+	       tp->sid, vio->_peer_sid, vio->_local_sid);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(vio_validate_sid);
+
+u32 vio_send_sid(struct vio_driver_state *vio)
+{
+	switch (vio->dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_NETWORK_SWITCH:
+	case VDEV_DISK:
+	default:
+		return vio->_local_sid;
+
+	case VDEV_DISK_SERVER:
+		return vio->_peer_sid;
+	}
+}
+EXPORT_SYMBOL(vio_send_sid);
+
+extern int vio_ldc_alloc(struct vio_driver_state *vio,
+			 struct ldc_channel_config *base_cfg,
+			 void *event_arg)
+{
+	struct ldc_channel_config cfg = *base_cfg;
+	struct ldc_channel *lp;
+
+	cfg.tx_irq = vio->vdev->tx_irq;
+	cfg.rx_irq = vio->vdev->rx_irq;
+
+	lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg);
+	if (IS_ERR(lp))
+		return PTR_ERR(lp);
+
+	vio->lp = lp;
+
+	return 0;
+}
+EXPORT_SYMBOL(vio_ldc_alloc);
+
+void vio_ldc_free(struct vio_driver_state *vio)
+{
+	ldc_free(vio->lp);
+	vio->lp = NULL;
+
+	kfree(vio->desc_buf);
+	vio->desc_buf = NULL;
+	vio->desc_buf_len = 0;
+}
+EXPORT_SYMBOL(vio_ldc_free);
+
+void vio_port_up(struct vio_driver_state *vio)
+{
+	unsigned long flags;
+	int err, state;
+
+	spin_lock_irqsave(&vio->lock, flags);
+
+	state = ldc_state(vio->lp);
+
+	err = 0;
+	if (state == LDC_STATE_INIT) {
+		err = ldc_bind(vio->lp, vio->name);
+		if (err)
+			printk(KERN_WARNING "%s: Port %lu bind failed, "
+			       "err=%d\n",
+			       vio->name, vio->vdev->channel_id, err);
+	}
+
+	if (!err) {
+		err = ldc_connect(vio->lp);
+		if (err)
+			printk(KERN_WARNING "%s: Port %lu connect failed, "
+			       "err=%d\n",
+			       vio->name, vio->vdev->channel_id, err);
+	}
+	if (err) {
+		unsigned long expires = jiffies + HZ;
+
+		expires = round_jiffies(expires);
+		mod_timer(&vio->timer, expires);
+	}
+
+	spin_unlock_irqrestore(&vio->lock, flags);
+}
+EXPORT_SYMBOL(vio_port_up);
+
+static void vio_port_timer(unsigned long _arg)
+{
+	struct vio_driver_state *vio = (struct vio_driver_state *) _arg;
+
+	vio_port_up(vio);
+}
+
+int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+		    u8 dev_class, struct vio_version *ver_table,
+		    int ver_table_size, struct vio_driver_ops *ops,
+		    char *name)
+{
+	switch (dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_NETWORK_SWITCH:
+	case VDEV_DISK:
+	case VDEV_DISK_SERVER:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (!ops->send_attr ||
+	    !ops->handle_attr ||
+	    !ops->handshake_complete)
+		return -EINVAL;
+
+	if (!ver_table || ver_table_size < 0)
+		return -EINVAL;
+
+	if (!name)
+		return -EINVAL;
+
+	spin_lock_init(&vio->lock);
+
+	vio->name = name;
+
+	vio->dev_class = dev_class;
+	vio->vdev = vdev;
+
+	vio->ver_table = ver_table;
+	vio->ver_table_entries = ver_table_size;
+
+	vio->ops = ops;
+
+	setup_timer(&vio->timer, vio_port_timer, (unsigned long) vio);
+
+	return 0;
+}
+EXPORT_SYMBOL(vio_driver_init);
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 4a725d8..c4a6d6e 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -14,6 +14,6 @@
 	 NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
 	 NGpage.o NGbzero.o \
 	 copy_in_user.o user_fixup.o memmove.o \
-	 mcount.o ipcsum.o rwsem.o xor.o delay.o
+	 mcount.o ipcsum.o rwsem.o xor.o
 
 obj-y += iomap.o
diff --git a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c
deleted file mode 100644
index fb27e54..0000000
--- a/arch/sparc64/lib/delay.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* delay.c: Delay loops for sparc64
- *
- * Copyright (C) 2004, 2006 David S. Miller <davem@davemloft.net>
- *
- * Based heavily upon x86 variant which is:
- *	Copyright (C) 1993 Linus Torvalds
- *	Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-
-#include <linux/delay.h>
-#include <asm/timer.h>
-
-void __delay(unsigned long loops)
-{
-	unsigned long bclock, now;
-	
-	bclock = tick_ops->get_tick();
-	do {
-		now = tick_ops->get_tick();
-	} while ((now-bclock) < loops);
-}
-
-/* We used to multiply by HZ after shifting down by 32 bits
- * but that runs into problems for higher values of HZ and
- * slow cpus.
- */
-void __const_udelay(unsigned long n)
-{
-	n *= 4;
-
-	n *= (cpu_data(raw_smp_processor_id()).udelay_val * (HZ/4));
-	n >>= 32;
-
-	__delay(n + 1);
-}
-
-void __udelay(unsigned long n)
-{
-	__const_udelay(n * 0x10c7UL);
-}
-
-
-void __ndelay(unsigned long n)
-{
-	__const_udelay(n * 0x5UL);
-}
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index f3e0c14..33c5b7d 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -14,6 +14,7 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/system.h>
+#include <asm/ldc.h>
 
 int prom_service_exists(const char *service_name)
 {
@@ -37,6 +38,10 @@
 /* Reset and reboot the machine with the command 'bcommand'. */
 void prom_reboot(const char *bcommand)
 {
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled)
+		ldom_reboot(bcommand);
+#endif
 	p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
 		  P1275_INOUT(1, 0), bcommand);
 }
@@ -91,6 +96,10 @@
  */
 void prom_halt(void)
 {
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled)
+		ldom_power_off();
+#endif
 again:
 	p1275_cmd("exit", P1275_INOUT(0, 0));
 	goto again; /* PROM is out to get me -DaveM */
@@ -98,6 +107,10 @@
 
 void prom_halt_power_off(void)
 {
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled)
+		ldom_power_off();
+#endif
 	p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
 
 	/* if nothing else helps, we just halt */
diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc64/prom/p1275.c
index 2b32c48..7fcccc0 100644
--- a/arch/sparc64/prom/p1275.c
+++ b/arch/sparc64/prom/p1275.c
@@ -16,6 +16,7 @@
 #include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm/pstate.h>
+#include <asm/ldc.h>
 
 struct {
 	long prom_callback;			/* 0x00 */
diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c
index 500f05e..17b7ecf 100644
--- a/arch/sparc64/prom/tree.c
+++ b/arch/sparc64/prom/tree.c
@@ -13,6 +13,7 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <asm/ldc.h>
 
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
@@ -261,9 +262,17 @@
 int
 prom_setprop(int node, const char *pname, char *value, int size)
 {
-	if(size == 0) return 0;
-	if((pname == 0) || (value == 0)) return 0;
+	if (size == 0)
+		return 0;
+	if ((pname == 0) || (value == 0))
+		return 0;
 	
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled) {
+		ldom_set_var(pname, value);
+		return 0;
+	}
+#endif
 	return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
 					  P1275_ARG(2,P1275_ARG_IN_BUF)|
 					  P1275_INOUT(4, 1), 
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 09c1aca..c86f5eb 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -47,4 +47,13 @@
         If you're involved in UML kernel development and want to use gcov,
         say Y.  If you're unsure, say N.
 
+config DEBUG_STACK_USAGE
+	bool "Stack utilization instrumentation"
+	default N
+	help
+	  Track the maximum kernel stack usage - this will look at each
+	  kernel stack at process exit and log it if it's the deepest
+	  stack seen so far.
+
+	  This option will slow down process creation and destruction somewhat.
 endmenu
diff --git a/arch/um/config.release b/arch/um/config.release
deleted file mode 100644
index fc68bcb..0000000
--- a/arch/um/config.release
+++ /dev/null
@@ -1,333 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_USERMODE=y
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCI is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
-#
-CONFIG_STDIO_CONSOLE=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_SSL=y
-CONFIG_HOSTFS=y
-CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_HOST_2G_2G is not set
-# CONFIG_UML_SMP is not set
-# CONFIG_SMP is not set
-CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
-CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_KMOD=y
-
-#
-# Devices
-#
-CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_MMAPPER is not set
-CONFIG_UML_SOUND=y
-CONFIG_SOUND=y
-CONFIG_HOSTAUDIO=y
-# CONFIG_UML_WATCHDOG is not set
-# CONFIG_TTY_LOG is not set
-CONFIG_FD_CHAN=y
-# CONFIG_NULL_CHAN is not set
-CONFIG_PORT_CHAN=y
-CONFIG_PTY_CHAN=y
-CONFIG_TTY_CHAN=y
-CONFIG_XTERM_CHAN=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=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_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#  
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC 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 device support
-#
-CONFIG_UML_NET=y
-CONFIG_UML_NET_ETHERTAP=y
-CONFIG_UML_NET_TUNTAP=y
-CONFIG_UML_NET_SLIP=y
-CONFIG_UML_NET_DAEMON=y
-CONFIG_UML_NET_MCAST=y
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-CONFIG_SHAPER=m
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_UMSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_EFS_FS=m
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=m
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-CONFIG_MINIX_FS=m
-CONFIG_VXFS_FS=m
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-CONFIG_HPFS_FS=m
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_QNX4FS_FS=m
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-CONFIG_SYSV_FS=m
-CONFIG_UDF_FS=m
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_ZLIB_FS_INFLATE=m
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-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_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
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_PT_PROXY is not set
-# CONFIG_GPROF is not set
-# CONFIG_GCOV is not set
diff --git a/arch/um/defconfig b/arch/um/defconfig
index a54d0ef..a25cd25 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -189,7 +189,7 @@
 # CONFIG_NOCONFIG_CHAN is not set
 CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
 CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
+CONFIG_SSL_CHAN="pts"
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -527,3 +527,4 @@
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 3aa3516..368d3e9 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -203,22 +203,37 @@
 	}
 }
 
-void enable_chan(struct line *line)
+int enable_chan(struct line *line)
 {
 	struct list_head *ele;
 	struct chan *chan;
+	int err;
 
 	list_for_each(ele, &line->chan_list){
 		chan = list_entry(ele, struct chan, list);
-		if(open_one_chan(chan))
+		err = open_one_chan(chan);
+		if (err) {
+			if (chan->primary)
+				goto out_close;
+
 			continue;
+		}
 
 		if(chan->enabled)
 			continue;
-		line_setup_irq(chan->fd, chan->input, chan->output, line,
-			       chan);
+		err = line_setup_irq(chan->fd, chan->input, chan->output, line,
+				     chan);
+		if (err)
+			goto out_close;
+
 		chan->enabled = 1;
 	}
+
+	return 0;
+
+ out_close:
+	close_chan(&line->chan_list, 0);
+	return err;
 }
 
 /* Items are added in IRQ context, when free_irq can't be called, and
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 13f0bf8..4d438f3 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -51,19 +51,21 @@
 /*
  * UML SIGWINCH handling
  *
- * The point of this is to handle SIGWINCH on consoles which have host ttys and
- * relay them inside UML to whatever might be running on the console and cares
- * about the window size (since SIGWINCH notifies about terminal size changes).
+ * The point of this is to handle SIGWINCH on consoles which have host
+ * ttys and relay them inside UML to whatever might be running on the
+ * console and cares about the window size (since SIGWINCH notifies
+ * about terminal size changes).
  *
- * So, we have a separate thread for each host tty attached to a UML device
- * (side-issue - I'm annoyed that one thread can't have multiple controlling
- * ttys for purposed of handling SIGWINCH, but I imagine there are other reasons
- * that doesn't make any sense).
+ * So, we have a separate thread for each host tty attached to a UML
+ * device (side-issue - I'm annoyed that one thread can't have
+ * multiple controlling ttys for the purpose of handling SIGWINCH, but
+ * I imagine there are other reasons that doesn't make any sense).
  *
- * SIGWINCH can't be received synchronously, so you have to set up to receive it
- * as a signal.  That being the case, if you are going to wait for it, it is
- * convenient to sit in sigsuspend() and wait for the signal to bounce you out of
- * it (see below for how we make sure to exit only on SIGWINCH).
+ * SIGWINCH can't be received synchronously, so you have to set up to
+ * receive it as a signal.  That being the case, if you are going to
+ * wait for it, it is convenient to sit in sigsuspend() and wait for
+ * the signal to bounce you out of it (see below for how we make sure
+ * to exit only on SIGWINCH).
  */
 
 static void winch_handler(int sig)
@@ -112,7 +114,8 @@
 
 	err = os_new_tty_pgrp(pty_fd, os_getpid());
 	if(err < 0){
-		printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
+		printk("winch_thread : new_tty_pgrp failed on fd %d, "
+		       "err = %d\n", pty_fd, -err);
 		exit(1);
 	}
 
@@ -126,8 +129,9 @@
 		       "err = %d\n", -count);
 
 	while(1){
-		/* This will be interrupted by SIGWINCH only, since other signals
-		 * are blocked.*/
+		/* This will be interrupted by SIGWINCH only, since
+		 * other signals are blocked.
+		 */
 		sigsuspend(&sigs);
 
 		count = os_write_file(pipe_fd, &c, sizeof(c));
@@ -137,10 +141,10 @@
 	}
 }
 
-static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
+static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
+		       unsigned long *stack_out)
 {
 	struct winch_data data;
-	unsigned long stack;
 	int fds[2], n, err;
 	char c;
 
@@ -153,9 +157,11 @@
 	data = ((struct winch_data) { .pty_fd 		= fd,
 				      .pipe_fd 		= fds[1] } );
 	/* CLONE_FILES so this thread doesn't hold open files which are open
-	 * now, but later closed.  This is a problem with /dev/net/tun.
+	 * now, but later closed in a different thread.  This is a
+	 * problem with /dev/net/tun, which if held open by this
+	 * thread, prevents the TUN/TAP device from being reused.
 	 */
-	err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
+	err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out);
 	if(err < 0){
 		printk("fork of winch_thread failed - errno = %d\n", -err);
 		goto out_close;
@@ -170,7 +176,13 @@
                 err = -EINVAL;
 		goto out_close;
 	}
-	return err ;
+
+	if (os_set_fd_block(*fd_out, 0)) {
+		printk("winch_tramp: failed to set thread_fd non-blocking.\n");
+		goto out_close;
+	}
+
+	return err;
 
  out_close:
 	os_close_file(fds[1]);
@@ -181,25 +193,25 @@
 
 void register_winch(int fd, struct tty_struct *tty)
 {
-	int pid, thread, thread_fd = -1;
-	int count;
+	unsigned long stack;
+	int pid, thread, count, thread_fd = -1;
 	char c = 1;
 
 	if(!isatty(fd))
 		return;
 
 	pid = tcgetpgrp(fd);
-	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
-			     tty) && (pid == -1)){
-		thread = winch_tramp(fd, tty, &thread_fd);
-		if(thread > 0){
-			register_winch_irq(thread_fd, fd, thread, tty);
+	if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) &&
+	    (pid == -1)) {
+		thread = winch_tramp(fd, tty, &thread_fd, &stack);
+		if (thread < 0)
+			return;
 
-			count = os_write_file(thread_fd, &c, sizeof(c));
-			if(count != sizeof(c))
-				printk("register_winch : failed to write "
-				       "synchronization byte, err = %d\n",
-					-count);
-		}
+		register_winch_irq(thread_fd, fd, thread, tty, stack);
+
+		count = os_write_file(thread_fd, &c, sizeof(c));
+		if(count != sizeof(c))
+			printk("register_winch : failed to write "
+			       "synchronization byte, err = %d\n", -count);
 	}
 }
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index 1545384..ca8c9e1 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -8,7 +8,7 @@
 
 static inline void *cow_malloc(int size)
 {
-	return um_kmalloc(size);
+	return kmalloc(size, UM_GFP_KERNEL);
 }
 
 static inline void cow_free(void *ptr)
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index b869e38..8d2008f 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -35,7 +35,7 @@
 {
 	struct sockaddr_un *sun;
 
-	sun = um_kmalloc(sizeof(struct sockaddr_un));
+	sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
 	if(sun == NULL){
 		printk("new_addr: allocation of sockaddr_un failed\n");
 		return NULL;
@@ -83,7 +83,7 @@
 		goto out_close;
 	}
 
-	sun = um_kmalloc(sizeof(struct sockaddr_un));
+	sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
 	if(sun == NULL){
 		printk("new_addr: allocation of sockaddr_un failed\n");
 		err = -ENOMEM;
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 7f083ec..39c01ff 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -37,7 +37,7 @@
 		printk("fd_init : couldn't parse file descriptor '%s'\n", str);
 		return(NULL);
 	}
-	data = um_kmalloc(sizeof(*data));
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
 	if(data == NULL) return(NULL);
 	*data = ((struct fd_chan) { .fd  	= n,
 				    .raw  	= opts->raw });
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index 5eeecf89..1171790 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -68,7 +68,7 @@
 		args = pid_args;
 	}
 
-	pid = run_helper(pre_exec, &data, args, NULL);
+	pid = run_helper(pre_exec, &data, args);
 
 	os_close_file(out_fds[0]);
 	os_close_file(in_fds[1]);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 4bd40bb..3e0b68e 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -454,7 +454,10 @@
 	tty->driver_data = line;
 	line->tty = tty;
 
-	enable_chan(line);
+	err = enable_chan(line);
+	if (err)
+		return err;
+
 	INIT_DELAYED_WORK(&line->task, line_timer_cb);
 
 	if(!line->sigio){
@@ -746,8 +749,24 @@
 	int tty_fd;
 	int pid;
 	struct tty_struct *tty;
+	unsigned long stack;
 };
 
+static void free_winch(struct winch *winch, int free_irq_ok)
+{
+	list_del(&winch->list);
+
+	if (winch->pid != -1)
+		os_kill_process(winch->pid, 1);
+	if (winch->fd != -1)
+		os_close_file(winch->fd);
+	if (winch->stack != 0)
+		free_stack(winch->stack, 0);
+	if (free_irq_ok)
+		free_irq(WINCH_IRQ, winch);
+	kfree(winch);
+}
+
 static irqreturn_t winch_interrupt(int irq, void *data)
 {
 	struct winch *winch = data;
@@ -764,12 +783,13 @@
 				       "errno = %d\n", -err);
 				printk("fd %d is losing SIGWINCH support\n",
 				       winch->tty_fd);
+				free_winch(winch, 0);
 				return IRQ_HANDLED;
 			}
 			goto out;
 		}
 	}
-	tty  = winch->tty;
+	tty = winch->tty;
 	if (tty != NULL) {
 		line = tty->driver_data;
 		chan_window_size(&line->chan_list, &tty->winsize.ws_row,
@@ -782,43 +802,44 @@
 	return IRQ_HANDLED;
 }
 
-void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
+void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
+			unsigned long stack)
 {
 	struct winch *winch;
 
 	winch = kmalloc(sizeof(*winch), GFP_KERNEL);
 	if (winch == NULL) {
 		printk("register_winch_irq - kmalloc failed\n");
-		return;
+		goto cleanup;
 	}
 
 	*winch = ((struct winch) { .list  	= LIST_HEAD_INIT(winch->list),
 				   .fd  	= fd,
 				   .tty_fd 	= tty_fd,
 				   .pid  	= pid,
-				   .tty 	= tty });
+				   .tty 	= tty,
+				   .stack	= stack });
+
+	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
+			   IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			   "winch", winch) < 0) {
+		printk("register_winch_irq - failed to register IRQ\n");
+		goto out_free;
+	}
 
 	spin_lock(&winch_handler_lock);
 	list_add(&winch->list, &winch_handlers);
 	spin_unlock(&winch_handler_lock);
 
-	if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-			  "winch", winch) < 0)
-		printk("register_winch_irq - failed to register IRQ\n");
-}
+	return;
 
-static void free_winch(struct winch *winch)
-{
-	list_del(&winch->list);
-
-	if(winch->pid != -1)
-		os_kill_process(winch->pid, 1);
-	if(winch->fd != -1)
-		os_close_file(winch->fd);
-
-	free_irq(WINCH_IRQ, winch);
+ out_free:
 	kfree(winch);
+ cleanup:
+	os_kill_process(pid, 1);
+	os_close_file(fd);
+	if (stack != 0)
+		free_stack(stack, 0);
 }
 
 static void unregister_winch(struct tty_struct *tty)
@@ -831,7 +852,7 @@
 	list_for_each(ele, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
                 if(winch->tty == tty){
-			free_winch(winch);
+			free_winch(winch, 1);
 			break;
                 }
         }
@@ -847,7 +868,7 @@
 
 	list_for_each_safe(ele, next, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
-		free_winch(winch);
+		free_winch(winch, 1);
 	}
 
 	spin_unlock(&winch_handler_lock);
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index d319db1..236a3df 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -30,7 +30,7 @@
 {
 	struct sockaddr_in *sin;
 
-	sin = um_kmalloc(sizeof(struct sockaddr_in));
+	sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
 	if(sin == NULL){
 		printk("new_addr: allocation of sockaddr_in failed\n");
 		return NULL;
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 62e5ad6..f31e715 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -86,8 +86,9 @@
 	int len;
 
 	req->originlen = sizeof(req->origin);
-	req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
-			    (struct sockaddr *) req->origin, &req->originlen);
+	req->len = recvfrom(fd, &req->request, sizeof(req->request),
+			    MSG_DONTWAIT, (struct sockaddr *) req->origin,
+			    &req->originlen);
 	if (req->len < 0)
 		return 0;
 
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 3503cff..da946e3 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -187,7 +187,7 @@
 	}
 	pe_data.close_me = fds[0];
 	pe_data.stdout = fds[1];
-	pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
+	pid = run_helper(change_pre_exec, &pe_data, argv);
 
 	if (pid > 0)	/* Avoid hang as we won't get data in failure case. */
 		read_output(fds[0], output, output_len);
@@ -217,7 +217,7 @@
 		netmask[2], netmask[3]);
 
 	output_len = UM_KERN_PAGE_SIZE;
-	output = um_kmalloc(output_len);
+	output = kmalloc(output_len, UM_GFP_KERNEL);
 	if(output == NULL)
 		printk("change : failed to allocate output buffer\n");
 
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 483aa15..1316456 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -53,7 +53,7 @@
 			return -EIO;
 		}
 
-		pri->compiled = um_kmalloc(sizeof(struct bpf_program));
+		pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL);
 		if(pri->compiled == NULL){
 			printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
 			return -ENOMEM;
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 3f6357d..c799b00 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -50,7 +50,7 @@
 	if(kern_data == NULL)
 		return NULL;
 
-	data = um_kmalloc(sizeof(*data));
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
 	if(data == NULL)
 		goto err;
 
@@ -188,7 +188,7 @@
 		{ .sock_fd  		= new,
 		  .pipe_fd 		= socket[1] });
 
-	err = run_helper(port_pre_exec, &data, argv, NULL);
+	err = run_helper(port_pre_exec, &data, argv);
 	if(err < 0)
 		goto out_shutdown;
 
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index df4976c..1e3fd61 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
@@ -7,12 +7,14 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <termios.h>
+#include <sys/stat.h>
 #include "chan_user.h"
-#include "user.h"
-#include "kern_util.h"
 #include "os.h"
+#include "user.h"
+#include "kern_constants.h"
 #include "um_malloc.h"
 
 struct pty_chan {
@@ -27,12 +29,14 @@
 {
 	struct pty_chan *data;
 
-	data = um_kmalloc(sizeof(*data));
-	if(data == NULL) return(NULL);
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+	if (data == NULL)
+		return NULL;
+
 	*data = ((struct pty_chan) { .announce  	= opts->announce, 
 				     .dev  		= device,
 				     .raw  		= opts->raw });
-	return(data);
+	return data;
 }
 
 static int pts_open(int input, int output, int primary, void *d,
@@ -43,31 +47,35 @@
 	int fd, err;
 
 	fd = get_pty();
-	if(fd < 0){
+	if (fd < 0) {
 		err = -errno;
-		printk("open_pts : Failed to open pts\n");
+		printk(UM_KERN_ERR "open_pts : Failed to open pts\n");
 		return err;
 	}
-	if(data->raw){
+
+	if (data->raw) {
 		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
-		if(err)
-			return(err);
+		if (err)
+			return err;
 
 		err = raw(fd);
-		if(err)
-			return(err);
+		if (err)
+			return err;
 	}
 
 	dev = ptsname(fd);
 	sprintf(data->dev_name, "%s", dev);
 	*dev_out = data->dev_name;
+
 	if (data->announce)
 		(*data->announce)(dev, data->dev);
-	return(fd);
+
+	return fd;
 }
 
 static int getmaster(char *line)
 {
+	struct stat buf;
 	char *pty, *bank, *cp;
 	int master, err;
 
@@ -75,24 +83,29 @@
 	for (bank = "pqrs"; *bank; bank++) {
 		line[strlen("/dev/pty")] = *bank;
 		*pty = '0';
-		if (os_stat_file(line, NULL) < 0)
+		/* Did we hit the end ? */
+		if ((stat(line, &buf) < 0) && (errno == ENOENT))
 			break;
+
 		for (cp = "0123456789abcdef"; *cp; cp++) {
 			*pty = *cp;
-			master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
+			master = open(line, O_RDWR);
 			if (master >= 0) {
 				char *tp = &line[strlen("/dev/")];
 
 				/* verify slave side is usable */
 				*tp = 't';
-				err = os_access(line, OS_ACC_RW_OK);
+				err = access(line, R_OK | W_OK);
 				*tp = 'p';
-				if(err == 0) return(master);
-				(void) os_close_file(master);
+				if(!err)
+					return master;
+				close(master);
 			}
 		}
 	}
-	return(-1);
+
+	printk(UM_KERN_ERR "getmaster - no usable host pty devices\n");
+	return -ENOENT;
 }
 
 static int pty_open(int input, int output, int primary, void *d,
@@ -103,20 +116,22 @@
 	char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
 
 	fd = getmaster(dev);
-	if(fd < 0)
-		return(-errno);
+	if (fd < 0)
+		return fd;
 
 	if(data->raw){
 		err = raw(fd);
-		if(err)
-			return(err);
+		if (err)
+			return err;
 	}
 	
-	if(data->announce) (*data->announce)(dev, data->dev);
+	if (data->announce)
+		(*data->announce)(dev, data->dev);
 
 	sprintf(data->dev_name, "%s", dev);
 	*dev_out = data->dev_name;
-	return(fd);
+
+	return fd;
 }
 
 const struct chan_ops pty_ops = {
@@ -144,14 +159,3 @@
 	.free		= generic_free,
 	.winch		= 0,
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 78f0e51..c0b73c2 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -85,13 +85,13 @@
 	pe_data.stdin = fd;
 	pe_data.stdout = fds[1];
 	pe_data.close_me = fds[0];
-	err = run_helper(slip_pre_exec, &pe_data, argv, NULL);
+	err = run_helper(slip_pre_exec, &pe_data, argv);
 	if(err < 0)
 		goto out_close;
 	pid = err;
 
 	output_len = UM_KERN_PAGE_SIZE;
-	output = um_kmalloc(output_len);
+	output = kmalloc(output_len, UM_GFP_KERNEL);
 	if(output == NULL){
 		printk("slip_tramp : failed to allocate output buffer\n");
 		os_kill_process(pid, 1);
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 39f889f..0e462f6 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -42,7 +42,7 @@
 
 	pe_data.stdin = fd;
 	pe_data.stdout = fd;
-	pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL);
+	pid = run_helper(slirp_pre_exec, &pe_data, argv);
 
 	return(pid);
 }
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index fd09ad9..875d60d 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -42,8 +42,6 @@
 	.announce 	= ssl_announce,
 	.xterm_title	= "Serial Line #%d",
 	.raw		= 1,
-	.tramp_stack 	= 0,
-	.in_kernel 	= 1,
 };
 
 static int ssl_config(char *str, char **error_out);
@@ -99,7 +97,13 @@
 
 static int ssl_open(struct tty_struct *tty, struct file *filp)
 {
-	return line_open(serial_lines, tty);
+	int err = line_open(serial_lines, tty);
+
+	if (err)
+		printk(KERN_ERR "Failed to open serial line %d, err = %d\n",
+		       tty->index, err);
+
+	return err;
 }
 
 #if 0
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 2bb4193..656036e 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -46,8 +46,6 @@
 	.announce 	= stdio_announce,
 	.xterm_title	= "Virtual Console #%d",
 	.raw		= 1,
-	.tramp_stack 	= 0,
-	.in_kernel 	= 1,
 };
 
 static int con_config(char *str, char **error_out);
@@ -101,7 +99,12 @@
 
 static int con_open(struct tty_struct *tty, struct file *filp)
 {
-	return line_open(vts, tty);
+	int err = line_open(vts, tty);
+	if (err)
+		printk(KERN_ERR "Failed to open console %d, err = %d\n",
+		       tty->index, err);
+
+	return err;
 }
 
 /* Set in an initcall, checked in an exitcall */
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index c07d0d5..a9f87e1 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -29,7 +29,7 @@
 	}
 	str++;
 
-	data = um_kmalloc(sizeof(*data));
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
 	if(data == NULL)
 		return NULL;
 	*data = ((struct tty_chan) { .dev 	= str,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 2e09f16..fc27f6c 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -712,6 +712,8 @@
 	ubd_dev->queue->queuedata = ubd_dev;
 
 	blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG);
+	if(ubd_dev->cow.file != NULL)
+		blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long));
 	err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
 	if(err){
 		*error_out = "Failed to register device";
@@ -1083,7 +1085,7 @@
 {
 	struct io_thread_req *io_req;
 	struct request *req;
-	int n;
+	int n, last_sectors;
 
 	while(1){
 		struct ubd *dev = q->queuedata;
@@ -1099,9 +1101,11 @@
 		}
 
 		req = dev->request;
+		last_sectors = 0;
 		while(dev->start_sg < dev->end_sg){
 			struct scatterlist *sg = &dev->sg[dev->start_sg];
 
+			req->sector += last_sectors;
 			io_req = kmalloc(sizeof(struct io_thread_req),
 					 GFP_ATOMIC);
 			if(io_req == NULL){
@@ -1113,6 +1117,7 @@
 					(unsigned long long) req->sector << 9,
 					sg->offset, sg->length, sg->page);
 
+			last_sectors = sg->length >> 9;
 			n = os_write_file(thread_fd, &io_req,
 					  sizeof(struct io_thread_req *));
 			if(n != sizeof(struct io_thread_req *)){
@@ -1124,7 +1129,6 @@
 				return;
 			}
 
-			req->sector += sg->length >> 9;
 			dev->start_sg++;
 		}
 		dev->end_sg = 0;
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 4707b3f..41d254b 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -43,6 +43,12 @@
 	kernel_fd = fds[0];
 	*fd_out = fds[1];
 
+	err = os_set_fd_block(*fd_out, 0);
+	if (err) {
+		printk("start_io_thread - failed to set nonblocking I/O.\n");
+		goto out_close;
+	}
+
 	pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
 		    NULL);
 	if(pid < 0){
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 571c2b3..fd817e5 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -1,22 +1,20 @@
 /* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
-#include <stdio.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
 #include <termios.h>
-#include <signal.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include "kern_util.h"
 #include "chan_user.h"
-#include "user.h"
 #include "os.h"
+#include "init.h"
+#include "user.h"
 #include "xterm.h"
+#include "kern_constants.h"
 
 struct xterm_chan {
 	int pid;
@@ -25,25 +23,21 @@
 	int device;
 	int raw;
 	struct termios tt;
-	unsigned long stack;
-	int direct_rcv;
 };
 
-/* Not static because it's called directly by the tt mode gdb code */
-void *xterm_init(char *str, int device, const struct chan_opts *opts)
+static void *xterm_init(char *str, int device, const struct chan_opts *opts)
 {
 	struct xterm_chan *data;
 
 	data = malloc(sizeof(*data));
-	if(data == NULL) return(NULL);
-	*data = ((struct xterm_chan) { .pid 		= -1, 
+	if (data == NULL)
+		return NULL;
+	*data = ((struct xterm_chan) { .pid 		= -1,
 				       .helper_pid 	= -1,
-				       .device 		= device, 
+				       .device 		= device,
 				       .title 		= opts->xterm_title,
-				       .raw  		= opts->raw,
-				       .stack 		= opts->tramp_stack,
-				       .direct_rcv 	= !opts->in_kernel } );
-	return(data);
+				       .raw  		= opts->raw } );
+	return data;
 }
 
 /* Only changed by xterm_setup, which is a setup */
@@ -57,16 +51,22 @@
 	terminal_emulator = line;
 
 	line = strchr(line, ',');
-	if(line == NULL) return(0);
+	if (line == NULL)
+		return 0;
+
 	*line++ = '\0';
-	if(*line) title_switch = line;
+	if (*line)
+		title_switch = line;
 
 	line = strchr(line, ',');
-	if(line == NULL) return(0);
-	*line++ = '\0';
-	if(*line) exec_switch = line;
+	if (line == NULL)
+		return 0;
 
-	return(0);
+	*line++ = '\0';
+	if (*line)
+		exec_switch = line;
+
+	return 0;
 }
 
 __uml_setup("xterm=", xterm_setup,
@@ -82,107 +82,128 @@
 "    are 'xterm=gnome-terminal,-t,-x'.\n\n"
 );
 
-/* XXX This badly needs some cleaning up in the error paths
- * Not static because it's called directly by the tt mode gdb code
- */
-int xterm_open(int input, int output, int primary, void *d,
+static int xterm_open(int input, int output, int primary, void *d,
 		      char **dev_out)
 {
 	struct xterm_chan *data = d;
-	unsigned long stack;
 	int pid, fd, new, err;
 	char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
-	char *argv[] = { terminal_emulator, title_switch, title, exec_switch, 
+	char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
 			 "/usr/lib/uml/port-helper", "-uml-socket",
 			 file, NULL };
 
-	if(os_access(argv[4], OS_ACC_X_OK) < 0)
+	if (access(argv[4], X_OK) < 0)
 		argv[4] = "port-helper";
 
 	/* Check that DISPLAY is set, this doesn't guarantee the xterm
 	 * will work but w/o it we can be pretty sure it won't. */
-	if (!getenv("DISPLAY")) {
-		printk("xterm_open: $DISPLAY not set.\n");
+	if (getenv("DISPLAY") == NULL) {
+		printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
 		return -ENODEV;
 	}
 
+	/*
+	 * This business of getting a descriptor to a temp file,
+	 * deleting the file and closing the descriptor is just to get
+	 * a known-unused name for the Unix socket that we really
+	 * want.
+	 */
 	fd = mkstemp(file);
-	if(fd < 0){
+	if (fd < 0) {
 		err = -errno;
-		printk("xterm_open : mkstemp failed, errno = %d\n", errno);
+		printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n",
+		       errno);
 		return err;
 	}
 
-	if(unlink(file)){
+	if (unlink(file)) {
 		err = -errno;
-		printk("xterm_open : unlink failed, errno = %d\n", errno);
+		printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
+		       errno);
 		return err;
 	}
-	os_close_file(fd);
+	close(fd);
 
 	fd = os_create_unix_socket(file, sizeof(file), 1);
-	if(fd < 0){
-		printk("xterm_open : create_unix_socket failed, errno = %d\n", 
-		       -fd);
-		return(fd);
+	if (fd < 0) {
+		printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
+		       "errno = %d\n", -fd);
+		return fd;
 	}
 
 	sprintf(title, data->title, data->device);
-	stack = data->stack;
-	pid = run_helper(NULL, NULL, argv, &stack);
-	if(pid < 0){
-		printk("xterm_open : run_helper failed, errno = %d\n", -pid);
-		return(pid);
+	pid = run_helper(NULL, NULL, argv);
+	if (pid < 0) {
+		err = pid;
+		printk(UM_KERN_ERR "xterm_open : run_helper failed, "
+		       "errno = %d\n", -err);
+		goto out_close1;
 	}
 
-	if (data->direct_rcv) {
-		new = os_rcv_fd(fd, &data->helper_pid);
-	} else {
-		err = os_set_fd_block(fd, 0);
-		if(err < 0){
-			printk("xterm_open : failed to set descriptor "
-			       "non-blocking, err = %d\n", -err);
-			return(err);
-		}
-		new = xterm_fd(fd, &data->helper_pid);
+	err = os_set_fd_block(fd, 0);
+	if (err < 0) {
+		printk(UM_KERN_ERR "xterm_open : failed to set descriptor "
+		       "non-blocking, err = %d\n", -err);
+		goto out_kill;
 	}
-	if(new < 0){
-		printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
-		goto out;
+
+	new = xterm_fd(fd, &data->helper_pid);
+	if (new < 0) {
+		err = new;
+		printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
+		       -err);
+		goto out_kill;
+	}
+
+	err = os_set_fd_block(new, 0);
+	if (err) {
+		printk(UM_KERN_ERR "xterm_open : failed to set xterm "
+		       "descriptor non-blocking, err = %d\n", -err);
+		goto out_close2;
 	}
 
 	CATCH_EINTR(err = tcgetattr(new, &data->tt));
-	if(err){
+	if (err) {
 		new = err;
-		goto out;
+		goto out_close2;
 	}
 
-	if(data->raw){
+	if (data->raw) {
 		err = raw(new);
-		if(err){
+		if (err) {
 			new = err;
-			goto out;
+			goto out_close2;
 		}
 	}
 
+	unlink(file);
 	data->pid = pid;
 	*dev_out = NULL;
- out:
-	unlink(file);
-	return(new);
+
+	return new;
+
+ out_close2:
+	close(new);
+ out_kill:
+	os_kill_process(pid, 1);
+ out_close1:
+	close(fd);
+
+	return err;
 }
 
-/* Not static because it's called directly by the tt mode gdb code */
-void xterm_close(int fd, void *d)
+static void xterm_close(int fd, void *d)
 {
 	struct xterm_chan *data = d;
 	
-	if(data->pid != -1) 
+	if (data->pid != -1)
 		os_kill_process(data->pid, 1);
 	data->pid = -1;
-	if(data->helper_pid != -1) 
+
+	if (data->helper_pid != -1)
 		os_kill_process(data->helper_pid, 0);
 	data->helper_pid = -1;
+
 	os_close_file(fd);
 }
 
@@ -203,14 +224,3 @@
 	.free		= xterm_free,
 	.winch		= 1,
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index a4ce705..b646bcc 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -1,18 +1,14 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
-#include "linux/errno.h"
-#include "linux/slab.h"
-#include "linux/signal.h"
-#include "linux/interrupt.h"
-#include "asm/irq.h"
-#include "irq_user.h"
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/irqreturn.h>
+#include <asm/irq.h>
 #include "irq_kern.h"
-#include "kern_util.h"
 #include "os.h"
-#include "xterm.h"
 
 struct xterm_wait {
 	struct completion ready;
@@ -27,12 +23,13 @@
 	int fd;
 
 	fd = os_rcv_fd(xterm->fd, &xterm->pid);
-	if(fd == -EAGAIN)
-		return(IRQ_NONE);
+	if (fd == -EAGAIN)
+		return IRQ_NONE;
 
 	xterm->new_fd = fd;
 	complete(&xterm->ready);
-	return(IRQ_HANDLED);
+
+	return IRQ_HANDLED;
 }
 
 int xterm_fd(int socket, int *pid_out)
@@ -41,22 +38,21 @@
 	int err, ret;
 
 	data = kmalloc(sizeof(*data), GFP_KERNEL);
-	if(data == NULL){
+	if (data == NULL) {
 		printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n");
-		return(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	/* This is a locked semaphore... */
-	*data = ((struct xterm_wait) 
-		{ .fd 		= socket,
-		  .pid 		= -1,
-		  .new_fd 	= -1 });
+	*data = ((struct xterm_wait) { .fd 		= socket,
+				       .pid 		= -1,
+				       .new_fd	 	= -1 });
 	init_completion(&data->ready);
 
-	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, 
+	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
 			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			     "xterm", data);
-	if (err){
+	if (err) {
 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
 		       "err = %d\n",  err);
 		ret = err;
@@ -76,16 +72,5 @@
  out:
 	kfree(data);
 
-	return(ret);
+	return ret;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index c4b41bb..624b510 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -40,7 +40,7 @@
 extern void deactivate_chan(struct list_head *chans, int irq);
 extern void reactivate_chan(struct list_head *chans, int irq);
 extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
-extern void enable_chan(struct line *line);
+extern int enable_chan(struct line *line);
 extern void close_chan(struct list_head *chans, int delay_free_irq);
 extern int chan_window_size(struct list_head *chans, 
 			     unsigned short *rows_out, 
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 38f16d8..5a2263e 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -12,8 +12,6 @@
 	void (*const announce)(char *dev_name, int dev);
 	char *xterm_title;
 	const int raw;
-	const unsigned long tramp_stack;
-	const int in_kernel;
 };
 
 enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
@@ -44,7 +42,8 @@
 
 struct tty_struct;
 extern void register_winch(int fd,  struct tty_struct *tty);
-extern void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty);
+extern void register_winch_irq(int fd, int tty_fd, int pid,
+			       struct tty_struct *tty, unsigned long stack);
 
 #define __channel_help(fn, prefix) \
 __uml_help(fn, prefix "[0-9]*=<channel description>\n" \
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 7376ee4..6eee343 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -27,6 +27,9 @@
 
 DEFINE(UM_NR_CPUS, NR_CPUS);
 
+DEFINE(UM_GFP_KERNEL, GFP_KERNEL);
+DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC);
+
 /* For crypto assembler code. */
 DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
 
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 4d9fb26..930b261 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -239,11 +239,9 @@
 /* execvp.c */
 extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
 /* helper.c */
-extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-		      unsigned long *stack_out);
+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
 extern int run_helper_thread(int (*proc)(void *), void *arg,
-			     unsigned int flags, unsigned long *stack_out,
-			     int stack_order);
+			     unsigned int flags, unsigned long *stack_out);
 extern int helper_wait(int pid);
 
 
diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h
index e6d7c5a..0ad17cb 100644
--- a/arch/um/include/um_malloc.h
+++ b/arch/um/include/um_malloc.h
@@ -6,11 +6,17 @@
 #ifndef __UM_MALLOC_H__
 #define __UM_MALLOC_H__
 
-extern void *um_kmalloc(int size);
-extern void *um_kmalloc_atomic(int size);
+#include "kern_constants.h"
+
+extern void *__kmalloc(int size, int flags);
+static inline void *kmalloc(int size, int flags)
+{
+	return __kmalloc(size, flags);
+}
+
 extern void kfree(const void *ptr);
 
-extern void *um_vmalloc(int size);
+extern void *vmalloc(unsigned long size);
 extern void vfree(void *ptr);
 
 #endif /* __UM_MALLOC_H__ */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index dba04d8..9870feb 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -30,7 +30,6 @@
 #include "irq_kern.h"
 #include "os.h"
 #include "sigio.h"
-#include "um_malloc.h"
 #include "misc_constants.h"
 #include "as-layout.h"
 
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 8d2c549..bfa52f2 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -46,7 +46,6 @@
 #include "mode.h"
 #include "mode_kern.h"
 #include "choose-mode.h"
-#include "um_malloc.h"
 
 /* This is a per-cpu array.  A processor only modifies its entry and it only
  * cares about its entry, so it's OK if another processor is modifying its
@@ -262,21 +261,6 @@
 {
 }
 
-void *um_kmalloc(int size)
-{
-	return kmalloc(size, GFP_KERNEL);
-}
-
-void *um_kmalloc_atomic(int size)
-{
-	return kmalloc(size, GFP_ATOMIC);
-}
-
-void *um_vmalloc(int size)
-{
-	return vmalloc(size);
-}
-
 int __cant_sleep(void) {
 	return in_atomic() || irqs_disabled() || in_interrupt();
 	/* Is in_interrupt() really needed? */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 627742d..6916c88 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -52,17 +52,9 @@
 	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;
-
-		ret = -EIO;
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp, p);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
         case PTRACE_PEEKUSR:
@@ -72,11 +64,7 @@
 	/* when 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 = -EIO;
-		if (access_process_vm(child, addr, &data, sizeof(data), 
-				      1) != sizeof(data))
-			break;
-		ret = 0;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 9bf944f..b126df4 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -177,6 +177,7 @@
 static int aio_req_fd_r = -1;
 static int aio_req_fd_w = -1;
 static int aio_pid = -1;
+static unsigned long aio_stack;
 
 static int not_aio_thread(void *arg)
 {
@@ -212,7 +213,6 @@
 
 static int init_aio_24(void)
 {
-	unsigned long stack;
 	int fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
@@ -227,7 +227,7 @@
 		goto out_close_pipe;
 
 	err = run_helper_thread(not_aio_thread, NULL,
-				CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+				CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
 	if(err < 0)
 		goto out_close_pipe;
 
@@ -252,7 +252,6 @@
 #define DEFAULT_24_AIO 0
 static int init_aio_26(void)
 {
-	unsigned long stack;
 	int err;
 
 	if(io_setup(256, &ctx)){
@@ -263,7 +262,7 @@
 	}
 
 	err = run_helper_thread(aio_thread, NULL,
-				CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+				CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
 	if(err < 0)
 		return err;
 
@@ -365,8 +364,10 @@
 
 static void exit_aio(void)
 {
-	if(aio_pid != -1)
+	if (aio_pid != -1) {
 		os_kill_process(aio_pid, 1);
+		free_stack(aio_stack, 0);
+	}
 }
 
 __uml_exitcall(exit_aio);
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index acba301..61d3953 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -54,7 +54,7 @@
 		return;
 	}
 
-	output = um_kmalloc(UM_KERN_PAGE_SIZE);
+	output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL);
 	if(output == NULL)
 		printk("etap_change : Failed to allocate output buffer\n");
 	read_output(fd, output, UM_KERN_PAGE_SIZE);
@@ -117,7 +117,7 @@
 	pe_data.control_remote = control_remote;
 	pe_data.control_me = control_me;
 	pe_data.data_me = data_me;
-	pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
+	pid = run_helper(etap_pre_exec, &pe_data, args);
 
 	if(pid < 0)
 		err = pid;
@@ -166,7 +166,7 @@
 	err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], 
 			 control_fds[1], data_fds[0], data_fds[1]);
 	output_len = UM_KERN_PAGE_SIZE;
-	output = um_kmalloc(output_len);
+	output = kmalloc(output_len, UM_GFP_KERNEL);
 	read_output(control_fds[0], output, output_len);
 
 	if(output == NULL)
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 11a9779..f848b4e 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -83,7 +83,7 @@
 	data.stdout = remote;
 	data.close_me = me;
 
-	pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
+	pid = run_helper(tuntap_pre_exec, &data, argv);
 
 	if(pid < 0)
 		return -pid;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 97bed16..d81af7b 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -44,17 +44,13 @@
 /* Returns either the pid of the child process we run or -E* on failure.
  * XXX The alloc_stack here breaks if this is called in the tracing thread, so
  * we need to receive a preallocated stack (a local buffer is ok). */
-int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-	       unsigned long *stack_out)
+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
 {
 	struct helper_data data;
 	unsigned long stack, sp;
 	int pid, fds[2], ret, n;
 
-	if ((stack_out != NULL) && (*stack_out != 0))
-		stack = *stack_out;
-	else
-		stack = alloc_stack(0, __cant_sleep());
+	stack = alloc_stack(0, __cant_sleep());
 	if (stack == 0)
 		return -ENOMEM;
 
@@ -76,8 +72,8 @@
 	data.pre_data = pre_data;
 	data.argv = argv;
 	data.fd = fds[1];
-	data.buf = __cant_sleep() ? um_kmalloc_atomic(PATH_MAX) :
-					um_kmalloc(PATH_MAX);
+	data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
+					kmalloc(PATH_MAX, UM_GFP_KERNEL);
 	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
 	if (pid < 0) {
 		ret = -errno;
@@ -113,22 +109,21 @@
 		close(fds[1]);
 	close(fds[0]);
 out_free:
-	if ((stack_out == NULL) || (*stack_out == 0))
-		free_stack(stack, 0);
+	free_stack(stack, 0);
 	return ret;
 }
 
 int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
-		      unsigned long *stack_out, int stack_order)
+		      unsigned long *stack_out)
 {
 	unsigned long stack, sp;
 	int pid, status, err;
 
-	stack = alloc_stack(stack_order, __cant_sleep());
+	stack = alloc_stack(0, __cant_sleep());
 	if (stack == 0)
 		return -ENOMEM;
 
-	sp = stack + (UM_KERN_PAGE_SIZE << stack_order) - sizeof(void *);
+	sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
 	pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
 	if (pid < 0) {
 		err = -errno;
@@ -147,7 +142,7 @@
 		if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
 			printk("run_helper_thread - thread returned status "
 			       "0x%x\n", status);
-		free_stack(stack, stack_order);
+		free_stack(stack, 0);
 	} else
 		*stack_out = stack;
 	return pid;
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index fb510d4..e85f499 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -235,8 +235,8 @@
 		return __real_malloc(size);
 	else if(size <= UM_KERN_PAGE_SIZE)
 		/* finding contiguous pages can be hard*/
-		ret = um_kmalloc(size);
-	else ret = um_vmalloc(size);
+		ret = kmalloc(size, UM_GFP_KERNEL);
+	else ret = vmalloc(size);
 
 	/* glibc people insist that if malloc fails, errno should be
 	 * set by malloc as well. So we do.
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 8d4e0c6..dc03e9c 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -26,6 +26,7 @@
  * exitcall.
  */
 static int write_sigio_pid = -1;
+static unsigned long write_sigio_stack;
 
 /* These arrays are initialized before the sigio thread is started, and
  * the descriptors closed after it is killed.  So, it can't see them change.
@@ -104,7 +105,7 @@
 	if(n <= polls->size)
 		return 0;
 
-	new = um_kmalloc_atomic(n * sizeof(struct pollfd));
+	new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
 	if(new == NULL){
 		printk("need_poll : failed to allocate new pollfds\n");
 		return -ENOMEM;
@@ -144,8 +145,10 @@
 	return;
  fail:
 	/* Critical section start */
-	if(write_sigio_pid != -1)
+	if (write_sigio_pid != -1) {
 		os_kill_process(write_sigio_pid, 1);
+		free_stack(write_sigio_stack, 0);
+	}
 	write_sigio_pid = -1;
 	close(sigio_private[0]);
 	close(sigio_private[1]);
@@ -230,7 +233,7 @@
 {
 	struct pollfd *p;
 
-	p = um_kmalloc(sizeof(struct pollfd));
+	p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
 	if (p == NULL) {
 		printk("setup_initial_poll : failed to allocate poll\n");
 		return NULL;
@@ -243,7 +246,6 @@
 
 static void write_sigio_workaround(void)
 {
-	unsigned long stack;
 	struct pollfd *p;
 	int err;
 	int l_write_sigio_fds[2];
@@ -293,7 +295,8 @@
 	memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
 
 	write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
-					    CLONE_FILES | CLONE_VM, &stack, 0);
+					    CLONE_FILES | CLONE_VM,
+					    &write_sigio_stack);
 
 	if (write_sigio_pid < 0)
 		goto out_clear;
@@ -356,10 +359,12 @@
 
 static void sigio_cleanup(void)
 {
-	if(write_sigio_pid != -1){
-		os_kill_process(write_sigio_pid, 1);
-		write_sigio_pid = -1;
-	}
+	if (write_sigio_pid == -1)
+		return;
+
+	os_kill_process(write_sigio_pid, 1);
+	free_stack(write_sigio_stack, 0);
+	write_sigio_pid = -1;
 }
 
 __uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 46c00cc..ba9af8d 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -41,7 +41,7 @@
 	if(pid != os_getpgrp())
 		return(0);
 
-	register_winch_irq(-1, fd, -1, data);
+	register_winch_irq(-1, fd, -1, data, 0);
 	return(1);
 }
 
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 3f33165..419b2d5 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -5,7 +5,8 @@
  * so I *must* declare good prototypes for them and then EXPORT them.
  * The kernel code uses the macro defined by include/linux/string.h,
  * so I undef macros; the userspace code does not include that and I
- * add an EXPORT for the glibc one.*/
+ * add an EXPORT for the glibc one.
+ */
 
 #undef strlen
 #undef strstr
@@ -61,12 +62,18 @@
 EXPORT_SYMBOL_PROTO(__xstat);
 EXPORT_SYMBOL_PROTO(__lxstat);
 EXPORT_SYMBOL_PROTO(__lxstat64);
+EXPORT_SYMBOL_PROTO(__fxstat64);
 EXPORT_SYMBOL_PROTO(lseek);
 EXPORT_SYMBOL_PROTO(lseek64);
 EXPORT_SYMBOL_PROTO(chown);
+EXPORT_SYMBOL_PROTO(fchown);
 EXPORT_SYMBOL_PROTO(truncate);
+EXPORT_SYMBOL_PROTO(ftruncate64);
 EXPORT_SYMBOL_PROTO(utime);
+EXPORT_SYMBOL_PROTO(utimes);
+EXPORT_SYMBOL_PROTO(futimes);
 EXPORT_SYMBOL_PROTO(chmod);
+EXPORT_SYMBOL_PROTO(fchmod);
 EXPORT_SYMBOL_PROTO(rename);
 EXPORT_SYMBOL_PROTO(__xmknod);
 
@@ -102,14 +109,3 @@
 
 extern long __guard __attribute__((weak));
 EXPORT_SYMBOL(__guard);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index a9b0934..a458ac9 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -117,24 +117,16 @@
 	int rval;
 
 	switch (request) {
-		unsigned long val, copied;
+		unsigned long val;
 
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
 	case PTRACE_PEEKDATA:
-		copied = access_process_vm(child, addr, &val, sizeof(val), 0);
-		rval = -EIO;
-		if (copied != sizeof(val))
-			break;
-		rval = put_user(val, (unsigned long *)data);
+		rval = generic_ptrace_peekdata(child, addr, data);
 		goto out;
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		rval = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1)
-		    == sizeof(data))
-			break;
-		rval = -EIO;
+		rval = generic_ptrace_pokedata(child, addr, data);
 		goto out;
 
 	/* Read/write the word at location ADDR in the registers.  */
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 8bdd25a..14bf8ce 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -774,8 +774,8 @@
 source "arch/x86_64/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on KALLSYMS && MODULES
 	help
 	  Kprobes allows you to trap at almost any kernel address and
 	  execute a callback function.  register_kprobe() establishes
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 47565c3..782dea8 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -526,7 +526,7 @@
 	.quad sys_init_module
 	.quad sys_delete_module
 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
-	.quad sys_quotactl
+	.quad sys32_quotactl
 	.quad sys_getpgid
 	.quad sys_fchdir
 	.quad quiet_ni_syscall	/* bdflush */
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 1fab487..941c84b 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -73,7 +73,11 @@
 	addq	%rbp, init_level4_pgt + (511*8)(%rip)
 
 	addq	%rbp, level3_ident_pgt + 0(%rip)
+
 	addq	%rbp, level3_kernel_pgt + (510*8)(%rip)
+	addq	%rbp, level3_kernel_pgt + (511*8)(%rip)
+
+	addq	%rbp, level2_fixmap_pgt + (506*8)(%rip)
 
 	/* Add an Identity mapping if I am above 1G */
 	leaq	_text(%rip), %rdi
@@ -314,7 +318,16 @@
 	.fill	510,8,0
 	/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
 	.quad	level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
-	.fill	1,8,0
+	.quad	level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+
+NEXT_PAGE(level2_fixmap_pgt)
+	.fill	506,8,0
+	.quad	level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
+	.fill	5,8,0
+
+NEXT_PAGE(level1_fixmap_pgt)
+	.fill	512,8,0
 
 NEXT_PAGE(level2_ident_pgt)
 	/* Since I easily can, map the first 1G.
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 931c64b..edbbc59 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -296,7 +296,7 @@
 static DEFINE_PER_CPU(local_t, alert_counter);
 static DEFINE_PER_CPU(int, nmi_touch);
 
-void touch_nmi_watchdog (void)
+void touch_nmi_watchdog(void)
 {
 	if (nmi_watchdog > 0) {
 		unsigned cpu;
@@ -306,8 +306,10 @@
 		 * do it ourselves because the alert count increase is not
 		 * atomic.
 		 */
-		for_each_present_cpu (cpu)
-			per_cpu(nmi_touch, cpu) = 1;
+		for_each_present_cpu(cpu) {
+			if (per_cpu(nmi_touch, cpu) != 1)
+				per_cpu(nmi_touch, cpu) = 1;
+		}
 	}
 
  	touch_softlockup_watchdog();
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 9409117..fa6775e 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -313,17 +313,9 @@
 	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);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -367,10 +359,7 @@
 	/* when 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;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index aac1c0b..74cbeb2 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -330,6 +330,7 @@
 
 static void print_trace_address(void *data, unsigned long addr)
 {
+	touch_nmi_watchdog();
 	printk_address(addr);
 }
 
@@ -518,6 +519,7 @@
 	printk("\n");
 	notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
 	show_registers(regs);
+	add_taint(TAINT_DIE);
 	/* Executive summary in case the oops scrolled away */
 	printk(KERN_ALERT "RIP ");
 	printk_address(regs->rip); 
@@ -531,7 +533,7 @@
 	unsigned long flags = oops_begin();
 
 	if (!user_mode(regs))
-		report_bug(regs->rip);
+		report_bug(regs->rip, regs);
 
 	__die(str, regs, err);
 	oops_end(flags);
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 14104ff..06a13d9 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -50,18 +50,8 @@
 	switch (request) {
 	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 *) data);
-
+		ret = generic_ptrace_peekdata(child, addr, data);
 		goto out;
-	}
 
 	/* Read the word at location addr in the USER area.  */
 
@@ -138,10 +128,7 @@
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		if (access_process_vm(child, addr, &data, sizeof(data), 1)
-		    == sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		goto out;
 
 	case PTRACE_POKEUSR:
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 693ab26..c5e62f9 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -482,6 +482,7 @@
 	if (!user_mode(regs))
 		show_stack(NULL, (unsigned long*)regs->areg[1]);
 
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (in_interrupt())
diff --git a/block/Kconfig b/block/Kconfig
index 2859351..6597b60 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -51,4 +51,12 @@
 
 endif # BLOCK
 
+config BLK_DEV_BSG
+	bool "Block layer SG support"
+	depends on (SCSI=y) && EXPERIMENTAL
+	default y
+	---help---
+	Saying Y here will enable generic SG (SCSI generic) v4
+	support for any block device.
+
 source block/Kconfig.iosched
diff --git a/block/Makefile b/block/Makefile
index 4b84d0d..959feeb 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
 
+obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
 obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
 obj-$(CONFIG_IOSCHED_AS)	+= as-iosched.o
 obj-$(CONFIG_IOSCHED_DEADLINE)	+= deadline-iosched.o
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 109e91b..3e316dd 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1322,10 +1322,9 @@
 {
 	struct as_data *ad;
 
-	ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
+	ad = kmalloc_node(sizeof(*ad), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (!ad)
 		return NULL;
-	memset(ad, 0, sizeof(*ad));
 
 	ad->q = q; /* Identify what queue the data belongs to */
 
diff --git a/block/bsg.c b/block/bsg.c
new file mode 100644
index 0000000..576933f
--- /dev/null
+++ b/block/bsg.c
@@ -0,0 +1,1114 @@
+/*
+ * bsg.c - block layer implementation of the sg v3 interface
+ *
+ * Copyright (C) 2004 Jens Axboe <axboe@suse.de> SUSE Labs
+ * Copyright (C) 2004 Peter M. Jones <pjones@redhat.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License version 2.  See the file "COPYING" in the main directory of this
+ *  archive for more details.
+ *
+ */
+/*
+ * TODO
+ *	- Should this get merged, block/scsi_ioctl.c will be migrated into
+ *	  this file. To keep maintenance down, it's easier to have them
+ *	  seperated right now.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/blkdev.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/percpu.h>
+#include <linux/uio.h>
+#include <linux/bsg.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/sg.h>
+
+static char bsg_version[] = "block layer sg (bsg) 0.4";
+
+struct bsg_device {
+	request_queue_t *queue;
+	spinlock_t lock;
+	struct list_head busy_list;
+	struct list_head done_list;
+	struct hlist_node dev_list;
+	atomic_t ref_count;
+	int minor;
+	int queued_cmds;
+	int done_cmds;
+	wait_queue_head_t wq_done;
+	wait_queue_head_t wq_free;
+	char name[BUS_ID_SIZE];
+	int max_queue;
+	unsigned long flags;
+};
+
+enum {
+	BSG_F_BLOCK		= 1,
+	BSG_F_WRITE_PERM	= 2,
+};
+
+#define BSG_DEFAULT_CMDS	64
+#define BSG_MAX_DEVS		32768
+
+#undef BSG_DEBUG
+
+#ifdef BSG_DEBUG
+#define dprintk(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ##args)
+#else
+#define dprintk(fmt, args...)
+#endif
+
+#define list_entry_bc(entry)	list_entry((entry), struct bsg_command, list)
+
+/*
+ * just for testing
+ */
+#define BSG_MAJOR	(240)
+
+static DEFINE_MUTEX(bsg_mutex);
+static int bsg_device_nr, bsg_minor_idx;
+
+#define BSG_LIST_SIZE	(8)
+#define bsg_list_idx(minor)	((minor) & (BSG_LIST_SIZE - 1))
+static struct hlist_head bsg_device_list[BSG_LIST_SIZE];
+
+static struct class *bsg_class;
+static LIST_HEAD(bsg_class_list);
+
+static struct kmem_cache *bsg_cmd_cachep;
+
+/*
+ * our internal command type
+ */
+struct bsg_command {
+	struct bsg_device *bd;
+	struct list_head list;
+	struct request *rq;
+	struct bio *bio;
+	struct bio *bidi_bio;
+	int err;
+	struct sg_io_v4 hdr;
+	struct sg_io_v4 __user *uhdr;
+	char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static void bsg_free_command(struct bsg_command *bc)
+{
+	struct bsg_device *bd = bc->bd;
+	unsigned long flags;
+
+	kmem_cache_free(bsg_cmd_cachep, bc);
+
+	spin_lock_irqsave(&bd->lock, flags);
+	bd->queued_cmds--;
+	spin_unlock_irqrestore(&bd->lock, flags);
+
+	wake_up(&bd->wq_free);
+}
+
+static struct bsg_command *bsg_alloc_command(struct bsg_device *bd)
+{
+	struct bsg_command *bc = ERR_PTR(-EINVAL);
+
+	spin_lock_irq(&bd->lock);
+
+	if (bd->queued_cmds >= bd->max_queue)
+		goto out;
+
+	bd->queued_cmds++;
+	spin_unlock_irq(&bd->lock);
+
+	bc = kmem_cache_alloc(bsg_cmd_cachep, GFP_USER);
+	if (unlikely(!bc)) {
+		spin_lock_irq(&bd->lock);
+		bd->queued_cmds--;
+		bc = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	memset(bc, 0, sizeof(*bc));
+	bc->bd = bd;
+	INIT_LIST_HEAD(&bc->list);
+	dprintk("%s: returning free cmd %p\n", bd->name, bc);
+	return bc;
+out:
+	spin_unlock_irq(&bd->lock);
+	return bc;
+}
+
+static inline void
+bsg_del_done_cmd(struct bsg_device *bd, struct bsg_command *bc)
+{
+	bd->done_cmds--;
+	list_del(&bc->list);
+}
+
+static inline void
+bsg_add_done_cmd(struct bsg_device *bd, struct bsg_command *bc)
+{
+	bd->done_cmds++;
+	list_add_tail(&bc->list, &bd->done_list);
+	wake_up(&bd->wq_done);
+}
+
+static inline int bsg_io_schedule(struct bsg_device *bd, int state)
+{
+	DEFINE_WAIT(wait);
+	int ret = 0;
+
+	spin_lock_irq(&bd->lock);
+
+	BUG_ON(bd->done_cmds > bd->queued_cmds);
+
+	/*
+	 * -ENOSPC or -ENODATA?  I'm going for -ENODATA, meaning "I have no
+	 * work to do", even though we return -ENOSPC after this same test
+	 * during bsg_write() -- there, it means our buffer can't have more
+	 * bsg_commands added to it, thus has no space left.
+	 */
+	if (bd->done_cmds == bd->queued_cmds) {
+		ret = -ENODATA;
+		goto unlock;
+	}
+
+	if (!test_bit(BSG_F_BLOCK, &bd->flags)) {
+		ret = -EAGAIN;
+		goto unlock;
+	}
+
+	prepare_to_wait(&bd->wq_done, &wait, state);
+	spin_unlock_irq(&bd->lock);
+	io_schedule();
+	finish_wait(&bd->wq_done, &wait);
+
+	if ((state == TASK_INTERRUPTIBLE) && signal_pending(current))
+		ret = -ERESTARTSYS;
+
+	return ret;
+unlock:
+	spin_unlock_irq(&bd->lock);
+	return ret;
+}
+
+static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq,
+				struct sg_io_v4 *hdr, int has_write_perm)
+{
+	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+
+	if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
+			   hdr->request_len))
+		return -EFAULT;
+
+	if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
+		if (blk_verify_command(rq->cmd, has_write_perm))
+			return -EPERM;
+	} else if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/*
+	 * fill in request structure
+	 */
+	rq->cmd_len = hdr->request_len;
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+	rq->timeout = (hdr->timeout * HZ) / 1000;
+	if (!rq->timeout)
+		rq->timeout = q->sg_timeout;
+	if (!rq->timeout)
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+
+	return 0;
+}
+
+/*
+ * Check if sg_io_v4 from user is allowed and valid
+ */
+static int
+bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw)
+{
+	int ret = 0;
+
+	if (hdr->guard != 'Q')
+		return -EINVAL;
+	if (hdr->request_len > BLK_MAX_CDB)
+		return -EINVAL;
+	if (hdr->dout_xfer_len > (q->max_sectors << 9) ||
+	    hdr->din_xfer_len > (q->max_sectors << 9))
+		return -EIO;
+
+	switch (hdr->protocol) {
+	case BSG_PROTOCOL_SCSI:
+		switch (hdr->subprotocol) {
+		case BSG_SUB_PROTOCOL_SCSI_CMD:
+		case BSG_SUB_PROTOCOL_SCSI_TRANSPORT:
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	*rw = hdr->dout_xfer_len ? WRITE : READ;
+	return ret;
+}
+
+/*
+ * map sg_io_v4 to a request.
+ */
+static struct request *
+bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
+{
+	request_queue_t *q = bd->queue;
+	struct request *rq, *next_rq = NULL;
+	int ret, rw = 0; /* shut up gcc */
+	unsigned int dxfer_len;
+	void *dxferp = NULL;
+
+	dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp,
+		hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
+		hdr->din_xfer_len);
+
+	ret = bsg_validate_sgv4_hdr(q, hdr, &rw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	/*
+	 * map scatter-gather elements seperately and string them to request
+	 */
+	rq = blk_get_request(q, rw, GFP_KERNEL);
+	if (!rq)
+		return ERR_PTR(-ENOMEM);
+	ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM,
+						       &bd->flags));
+	if (ret)
+		goto out;
+
+	if (rw == WRITE && hdr->din_xfer_len) {
+		if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) {
+			ret = -EOPNOTSUPP;
+			goto out;
+		}
+
+		next_rq = blk_get_request(q, READ, GFP_KERNEL);
+		if (!next_rq) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		rq->next_rq = next_rq;
+
+		dxferp = (void*)(unsigned long)hdr->din_xferp;
+		ret =  blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len);
+		if (ret)
+			goto out;
+	}
+
+	if (hdr->dout_xfer_len) {
+		dxfer_len = hdr->dout_xfer_len;
+		dxferp = (void*)(unsigned long)hdr->dout_xferp;
+	} else if (hdr->din_xfer_len) {
+		dxfer_len = hdr->din_xfer_len;
+		dxferp = (void*)(unsigned long)hdr->din_xferp;
+	} else
+		dxfer_len = 0;
+
+	if (dxfer_len) {
+		ret = blk_rq_map_user(q, rq, dxferp, dxfer_len);
+		if (ret)
+			goto out;
+	}
+	return rq;
+out:
+	blk_put_request(rq);
+	if (next_rq) {
+		blk_rq_unmap_user(next_rq->bio);
+		blk_put_request(next_rq);
+	}
+	return ERR_PTR(ret);
+}
+
+/*
+ * async completion call-back from the block layer, when scsi/ide/whatever
+ * calls end_that_request_last() on a request
+ */
+static void bsg_rq_end_io(struct request *rq, int uptodate)
+{
+	struct bsg_command *bc = rq->end_io_data;
+	struct bsg_device *bd = bc->bd;
+	unsigned long flags;
+
+	dprintk("%s: finished rq %p bc %p, bio %p stat %d\n",
+		bd->name, rq, bc, bc->bio, uptodate);
+
+	bc->hdr.duration = jiffies_to_msecs(jiffies - bc->hdr.duration);
+
+	spin_lock_irqsave(&bd->lock, flags);
+	list_del(&bc->list);
+	bsg_add_done_cmd(bd, bc);
+	spin_unlock_irqrestore(&bd->lock, flags);
+}
+
+/*
+ * do final setup of a 'bc' and submit the matching 'rq' to the block
+ * layer for io
+ */
+static void bsg_add_command(struct bsg_device *bd, request_queue_t *q,
+			    struct bsg_command *bc, struct request *rq)
+{
+	rq->sense = bc->sense;
+	rq->sense_len = 0;
+
+	/*
+	 * add bc command to busy queue and submit rq for io
+	 */
+	bc->rq = rq;
+	bc->bio = rq->bio;
+	if (rq->next_rq)
+		bc->bidi_bio = rq->next_rq->bio;
+	bc->hdr.duration = jiffies;
+	spin_lock_irq(&bd->lock);
+	list_add_tail(&bc->list, &bd->busy_list);
+	spin_unlock_irq(&bd->lock);
+
+	dprintk("%s: queueing rq %p, bc %p\n", bd->name, rq, bc);
+
+	rq->end_io_data = bc;
+	blk_execute_rq_nowait(q, NULL, rq, 1, bsg_rq_end_io);
+}
+
+static inline struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd)
+{
+	struct bsg_command *bc = NULL;
+
+	spin_lock_irq(&bd->lock);
+	if (bd->done_cmds) {
+		bc = list_entry_bc(bd->done_list.next);
+		bsg_del_done_cmd(bd, bc);
+	}
+	spin_unlock_irq(&bd->lock);
+
+	return bc;
+}
+
+/*
+ * Get a finished command from the done list
+ */
+static struct bsg_command *bsg_get_done_cmd(struct bsg_device *bd)
+{
+	struct bsg_command *bc;
+	int ret;
+
+	do {
+		bc = bsg_next_done_cmd(bd);
+		if (bc)
+			break;
+
+		if (!test_bit(BSG_F_BLOCK, &bd->flags)) {
+			bc = ERR_PTR(-EAGAIN);
+			break;
+		}
+
+		ret = wait_event_interruptible(bd->wq_done, bd->done_cmds);
+		if (ret) {
+			bc = ERR_PTR(-ERESTARTSYS);
+			break;
+		}
+	} while (1);
+
+	dprintk("%s: returning done %p\n", bd->name, bc);
+
+	return bc;
+}
+
+static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
+				    struct bio *bio, struct bio *bidi_bio)
+{
+	int ret = 0;
+
+	dprintk("rq %p bio %p %u\n", rq, bio, rq->errors);
+	/*
+	 * fill in all the output members
+	 */
+	hdr->device_status = status_byte(rq->errors);
+	hdr->transport_status = host_byte(rq->errors);
+	hdr->driver_status = driver_byte(rq->errors);
+	hdr->info = 0;
+	if (hdr->device_status || hdr->transport_status || hdr->driver_status)
+		hdr->info |= SG_INFO_CHECK;
+	hdr->din_resid = rq->data_len;
+	hdr->response_len = 0;
+
+	if (rq->sense_len && hdr->response) {
+		int len = min((unsigned int) hdr->max_response_len,
+			      rq->sense_len);
+
+		ret = copy_to_user((void*)(unsigned long)hdr->response,
+				   rq->sense, len);
+		if (!ret)
+			hdr->response_len = len;
+		else
+			ret = -EFAULT;
+	}
+
+	if (rq->next_rq) {
+		blk_rq_unmap_user(bidi_bio);
+		blk_put_request(rq->next_rq);
+	}
+
+	blk_rq_unmap_user(bio);
+	blk_put_request(rq);
+
+	return ret;
+}
+
+static int bsg_complete_all_commands(struct bsg_device *bd)
+{
+	struct bsg_command *bc;
+	int ret, tret;
+
+	dprintk("%s: entered\n", bd->name);
+
+	set_bit(BSG_F_BLOCK, &bd->flags);
+
+	/*
+	 * wait for all commands to complete
+	 */
+	ret = 0;
+	do {
+		ret = bsg_io_schedule(bd, TASK_UNINTERRUPTIBLE);
+		/*
+		 * look for -ENODATA specifically -- we'll sometimes get
+		 * -ERESTARTSYS when we've taken a signal, but we can't
+		 * return until we're done freeing the queue, so ignore
+		 * it.  The signal will get handled when we're done freeing
+		 * the bsg_device.
+		 */
+	} while (ret != -ENODATA);
+
+	/*
+	 * discard done commands
+	 */
+	ret = 0;
+	do {
+		spin_lock_irq(&bd->lock);
+		if (!bd->queued_cmds) {
+			spin_unlock_irq(&bd->lock);
+			break;
+		}
+		spin_unlock_irq(&bd->lock);
+
+		bc = bsg_get_done_cmd(bd);
+		if (IS_ERR(bc))
+			break;
+
+		tret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio,
+						bc->bidi_bio);
+		if (!ret)
+			ret = tret;
+
+		bsg_free_command(bc);
+	} while (1);
+
+	return ret;
+}
+
+static ssize_t
+__bsg_read(char __user *buf, size_t count, struct bsg_device *bd,
+	   const struct iovec *iov, ssize_t *bytes_read)
+{
+	struct bsg_command *bc;
+	int nr_commands, ret;
+
+	if (count % sizeof(struct sg_io_v4))
+		return -EINVAL;
+
+	ret = 0;
+	nr_commands = count / sizeof(struct sg_io_v4);
+	while (nr_commands) {
+		bc = bsg_get_done_cmd(bd);
+		if (IS_ERR(bc)) {
+			ret = PTR_ERR(bc);
+			break;
+		}
+
+		/*
+		 * this is the only case where we need to copy data back
+		 * after completing the request. so do that here,
+		 * bsg_complete_work() cannot do that for us
+		 */
+		ret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio,
+					       bc->bidi_bio);
+
+		if (copy_to_user(buf, (char *) &bc->hdr, sizeof(bc->hdr)))
+			ret = -EFAULT;
+
+		bsg_free_command(bc);
+
+		if (ret)
+			break;
+
+		buf += sizeof(struct sg_io_v4);
+		*bytes_read += sizeof(struct sg_io_v4);
+		nr_commands--;
+	}
+
+	return ret;
+}
+
+static inline void bsg_set_block(struct bsg_device *bd, struct file *file)
+{
+	if (file->f_flags & O_NONBLOCK)
+		clear_bit(BSG_F_BLOCK, &bd->flags);
+	else
+		set_bit(BSG_F_BLOCK, &bd->flags);
+}
+
+static inline void bsg_set_write_perm(struct bsg_device *bd, struct file *file)
+{
+	if (file->f_mode & FMODE_WRITE)
+		set_bit(BSG_F_WRITE_PERM, &bd->flags);
+	else
+		clear_bit(BSG_F_WRITE_PERM, &bd->flags);
+}
+
+static inline int err_block_err(int ret)
+{
+	if (ret && ret != -ENOSPC && ret != -ENODATA && ret != -EAGAIN)
+		return 1;
+
+	return 0;
+}
+
+static ssize_t
+bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct bsg_device *bd = file->private_data;
+	int ret;
+	ssize_t bytes_read;
+
+	dprintk("%s: read %Zd bytes\n", bd->name, count);
+
+	bsg_set_block(bd, file);
+	bytes_read = 0;
+	ret = __bsg_read(buf, count, bd, NULL, &bytes_read);
+	*ppos = bytes_read;
+
+	if (!bytes_read || (bytes_read && err_block_err(ret)))
+		bytes_read = ret;
+
+	return bytes_read;
+}
+
+static ssize_t __bsg_write(struct bsg_device *bd, const char __user *buf,
+			   size_t count, ssize_t *bytes_read)
+{
+	struct bsg_command *bc;
+	struct request *rq;
+	int ret, nr_commands;
+
+	if (count % sizeof(struct sg_io_v4))
+		return -EINVAL;
+
+	nr_commands = count / sizeof(struct sg_io_v4);
+	rq = NULL;
+	bc = NULL;
+	ret = 0;
+	while (nr_commands) {
+		request_queue_t *q = bd->queue;
+
+		bc = bsg_alloc_command(bd);
+		if (IS_ERR(bc)) {
+			ret = PTR_ERR(bc);
+			bc = NULL;
+			break;
+		}
+
+		bc->uhdr = (struct sg_io_v4 __user *) buf;
+		if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		/*
+		 * get a request, fill in the blanks, and add to request queue
+		 */
+		rq = bsg_map_hdr(bd, &bc->hdr);
+		if (IS_ERR(rq)) {
+			ret = PTR_ERR(rq);
+			rq = NULL;
+			break;
+		}
+
+		bsg_add_command(bd, q, bc, rq);
+		bc = NULL;
+		rq = NULL;
+		nr_commands--;
+		buf += sizeof(struct sg_io_v4);
+		*bytes_read += sizeof(struct sg_io_v4);
+	}
+
+	if (bc)
+		bsg_free_command(bc);
+
+	return ret;
+}
+
+static ssize_t
+bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct bsg_device *bd = file->private_data;
+	ssize_t bytes_read;
+	int ret;
+
+	dprintk("%s: write %Zd bytes\n", bd->name, count);
+
+	bsg_set_block(bd, file);
+	bsg_set_write_perm(bd, file);
+
+	bytes_read = 0;
+	ret = __bsg_write(bd, buf, count, &bytes_read);
+	*ppos = bytes_read;
+
+	/*
+	 * return bytes written on non-fatal errors
+	 */
+	if (!bytes_read || (bytes_read && err_block_err(ret)))
+		bytes_read = ret;
+
+	dprintk("%s: returning %Zd\n", bd->name, bytes_read);
+	return bytes_read;
+}
+
+static struct bsg_device *bsg_alloc_device(void)
+{
+	struct bsg_device *bd;
+
+	bd = kzalloc(sizeof(struct bsg_device), GFP_KERNEL);
+	if (unlikely(!bd))
+		return NULL;
+
+	spin_lock_init(&bd->lock);
+
+	bd->max_queue = BSG_DEFAULT_CMDS;
+
+	INIT_LIST_HEAD(&bd->busy_list);
+	INIT_LIST_HEAD(&bd->done_list);
+	INIT_HLIST_NODE(&bd->dev_list);
+
+	init_waitqueue_head(&bd->wq_free);
+	init_waitqueue_head(&bd->wq_done);
+	return bd;
+}
+
+static int bsg_put_device(struct bsg_device *bd)
+{
+	int ret = 0;
+
+	mutex_lock(&bsg_mutex);
+
+	if (!atomic_dec_and_test(&bd->ref_count))
+		goto out;
+
+	dprintk("%s: tearing down\n", bd->name);
+
+	/*
+	 * close can always block
+	 */
+	set_bit(BSG_F_BLOCK, &bd->flags);
+
+	/*
+	 * correct error detection baddies here again. it's the responsibility
+	 * of the app to properly reap commands before close() if it wants
+	 * fool-proof error detection
+	 */
+	ret = bsg_complete_all_commands(bd);
+
+	blk_put_queue(bd->queue);
+	hlist_del(&bd->dev_list);
+	kfree(bd);
+out:
+	mutex_unlock(&bsg_mutex);
+	return ret;
+}
+
+static struct bsg_device *bsg_add_device(struct inode *inode,
+					 struct request_queue *rq,
+					 struct file *file)
+{
+	struct bsg_device *bd = NULL;
+#ifdef BSG_DEBUG
+	unsigned char buf[32];
+#endif
+
+	bd = bsg_alloc_device();
+	if (!bd)
+		return ERR_PTR(-ENOMEM);
+
+	bd->queue = rq;
+	kobject_get(&rq->kobj);
+	bsg_set_block(bd, file);
+
+	atomic_set(&bd->ref_count, 1);
+	bd->minor = iminor(inode);
+	mutex_lock(&bsg_mutex);
+	hlist_add_head(&bd->dev_list, &bsg_device_list[bsg_list_idx(bd->minor)]);
+
+	strncpy(bd->name, rq->bsg_dev.class_dev->class_id, sizeof(bd->name) - 1);
+	dprintk("bound to <%s>, max queue %d\n",
+		format_dev_t(buf, inode->i_rdev), bd->max_queue);
+
+	mutex_unlock(&bsg_mutex);
+	return bd;
+}
+
+static struct bsg_device *__bsg_get_device(int minor)
+{
+	struct hlist_head *list = &bsg_device_list[bsg_list_idx(minor)];
+	struct bsg_device *bd = NULL;
+	struct hlist_node *entry;
+
+	mutex_lock(&bsg_mutex);
+
+	hlist_for_each(entry, list) {
+		bd = hlist_entry(entry, struct bsg_device, dev_list);
+		if (bd->minor == minor) {
+			atomic_inc(&bd->ref_count);
+			break;
+		}
+
+		bd = NULL;
+	}
+
+	mutex_unlock(&bsg_mutex);
+	return bd;
+}
+
+static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
+{
+	struct bsg_device *bd = __bsg_get_device(iminor(inode));
+	struct bsg_class_device *bcd, *__bcd;
+
+	if (bd)
+		return bd;
+
+	/*
+	 * find the class device
+	 */
+	bcd = NULL;
+	mutex_lock(&bsg_mutex);
+	list_for_each_entry(__bcd, &bsg_class_list, list) {
+		if (__bcd->minor == iminor(inode)) {
+			bcd = __bcd;
+			break;
+		}
+	}
+	mutex_unlock(&bsg_mutex);
+
+	if (!bcd)
+		return ERR_PTR(-ENODEV);
+
+	return bsg_add_device(inode, bcd->queue, file);
+}
+
+static int bsg_open(struct inode *inode, struct file *file)
+{
+	struct bsg_device *bd = bsg_get_device(inode, file);
+
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	file->private_data = bd;
+	return 0;
+}
+
+static int bsg_release(struct inode *inode, struct file *file)
+{
+	struct bsg_device *bd = file->private_data;
+
+	file->private_data = NULL;
+	return bsg_put_device(bd);
+}
+
+static unsigned int bsg_poll(struct file *file, poll_table *wait)
+{
+	struct bsg_device *bd = file->private_data;
+	unsigned int mask = 0;
+
+	poll_wait(file, &bd->wq_done, wait);
+	poll_wait(file, &bd->wq_free, wait);
+
+	spin_lock_irq(&bd->lock);
+	if (!list_empty(&bd->done_list))
+		mask |= POLLIN | POLLRDNORM;
+	if (bd->queued_cmds >= bd->max_queue)
+		mask |= POLLOUT;
+	spin_unlock_irq(&bd->lock);
+
+	return mask;
+}
+
+static int
+bsg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	  unsigned long arg)
+{
+	struct bsg_device *bd = file->private_data;
+	int __user *uarg = (int __user *) arg;
+
+	if (!bd)
+		return -ENXIO;
+
+	switch (cmd) {
+		/*
+		 * our own ioctls
+		 */
+	case SG_GET_COMMAND_Q:
+		return put_user(bd->max_queue, uarg);
+	case SG_SET_COMMAND_Q: {
+		int queue;
+
+		if (get_user(queue, uarg))
+			return -EFAULT;
+		if (queue < 1)
+			return -EINVAL;
+
+		spin_lock_irq(&bd->lock);
+		bd->max_queue = queue;
+		spin_unlock_irq(&bd->lock);
+		return 0;
+	}
+
+	/*
+	 * SCSI/sg ioctls
+	 */
+	case SG_GET_VERSION_NUM:
+	case SCSI_IOCTL_GET_IDLUN:
+	case SCSI_IOCTL_GET_BUS_NUMBER:
+	case SG_SET_TIMEOUT:
+	case SG_GET_TIMEOUT:
+	case SG_GET_RESERVED_SIZE:
+	case SG_SET_RESERVED_SIZE:
+	case SG_EMULATED_HOST:
+	case SCSI_IOCTL_SEND_COMMAND: {
+		void __user *uarg = (void __user *) arg;
+		return scsi_cmd_ioctl(file, bd->queue, NULL, cmd, uarg);
+	}
+	case SG_IO: {
+		struct request *rq;
+		struct bio *bio, *bidi_bio = NULL;
+		struct sg_io_v4 hdr;
+
+		if (copy_from_user(&hdr, uarg, sizeof(hdr)))
+			return -EFAULT;
+
+		rq = bsg_map_hdr(bd, &hdr);
+		if (IS_ERR(rq))
+			return PTR_ERR(rq);
+
+		bio = rq->bio;
+		if (rq->next_rq)
+			bidi_bio = rq->next_rq->bio;
+		blk_execute_rq(bd->queue, NULL, rq, 0);
+		blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio);
+
+		if (copy_to_user(uarg, &hdr, sizeof(hdr)))
+			return -EFAULT;
+
+		return 0;
+	}
+	/*
+	 * block device ioctls
+	 */
+	default:
+#if 0
+		return ioctl_by_bdev(bd->bdev, cmd, arg);
+#else
+		return -ENOTTY;
+#endif
+	}
+}
+
+static struct file_operations bsg_fops = {
+	.read		=	bsg_read,
+	.write		=	bsg_write,
+	.poll		=	bsg_poll,
+	.open		=	bsg_open,
+	.release	=	bsg_release,
+	.ioctl		=	bsg_ioctl,
+	.owner		=	THIS_MODULE,
+};
+
+void bsg_unregister_queue(struct request_queue *q)
+{
+	struct bsg_class_device *bcd = &q->bsg_dev;
+
+	if (!bcd->class_dev)
+		return;
+
+	mutex_lock(&bsg_mutex);
+	sysfs_remove_link(&q->kobj, "bsg");
+	class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor));
+	bcd->class_dev = NULL;
+	list_del_init(&bcd->list);
+	bsg_device_nr--;
+	mutex_unlock(&bsg_mutex);
+}
+EXPORT_SYMBOL_GPL(bsg_unregister_queue);
+
+int bsg_register_queue(struct request_queue *q, const char *name)
+{
+	struct bsg_class_device *bcd, *__bcd;
+	dev_t dev;
+	int ret = -EMFILE;
+	struct class_device *class_dev = NULL;
+
+	/*
+	 * we need a proper transport to send commands, not a stacked device
+	 */
+	if (!q->request_fn)
+		return 0;
+
+	bcd = &q->bsg_dev;
+	memset(bcd, 0, sizeof(*bcd));
+	INIT_LIST_HEAD(&bcd->list);
+
+	mutex_lock(&bsg_mutex);
+	if (bsg_device_nr == BSG_MAX_DEVS) {
+		printk(KERN_ERR "bsg: too many bsg devices\n");
+		goto err;
+	}
+
+retry:
+	list_for_each_entry(__bcd, &bsg_class_list, list) {
+		if (__bcd->minor == bsg_minor_idx) {
+			bsg_minor_idx++;
+			if (bsg_minor_idx == BSG_MAX_DEVS)
+				bsg_minor_idx = 0;
+			goto retry;
+		}
+	}
+
+	bcd->minor = bsg_minor_idx++;
+	if (bsg_minor_idx == BSG_MAX_DEVS)
+		bsg_minor_idx = 0;
+
+	bcd->queue = q;
+	dev = MKDEV(BSG_MAJOR, bcd->minor);
+	class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name);
+	if (IS_ERR(class_dev)) {
+		ret = PTR_ERR(class_dev);
+		goto err;
+	}
+	bcd->class_dev = class_dev;
+
+	if (q->kobj.sd) {
+		ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg");
+		if (ret)
+			goto err;
+	}
+
+	list_add_tail(&bcd->list, &bsg_class_list);
+	bsg_device_nr++;
+
+	mutex_unlock(&bsg_mutex);
+	return 0;
+err:
+	if (class_dev)
+		class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor));
+	mutex_unlock(&bsg_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(bsg_register_queue);
+
+static int bsg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
+{
+	int ret;
+	struct scsi_device *sdp = to_scsi_device(cl_dev->dev);
+	struct request_queue *rq = sdp->request_queue;
+
+	if (rq->kobj.parent)
+		ret = bsg_register_queue(rq, kobject_name(rq->kobj.parent));
+	else
+		ret = bsg_register_queue(rq, kobject_name(&sdp->sdev_gendev.kobj));
+	return ret;
+}
+
+static void bsg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
+{
+	bsg_unregister_queue(to_scsi_device(cl_dev->dev)->request_queue);
+}
+
+static struct class_interface bsg_intf = {
+	.add	= bsg_add,
+	.remove	= bsg_remove,
+};
+
+static struct cdev bsg_cdev = {
+	.kobj   = {.name = "bsg", },
+	.owner  = THIS_MODULE,
+};
+
+static int __init bsg_init(void)
+{
+	int ret, i;
+
+	bsg_cmd_cachep = kmem_cache_create("bsg_cmd",
+				sizeof(struct bsg_command), 0, 0, NULL, NULL);
+	if (!bsg_cmd_cachep) {
+		printk(KERN_ERR "bsg: failed creating slab cache\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < BSG_LIST_SIZE; i++)
+		INIT_HLIST_HEAD(&bsg_device_list[i]);
+
+	bsg_class = class_create(THIS_MODULE, "bsg");
+	if (IS_ERR(bsg_class)) {
+		kmem_cache_destroy(bsg_cmd_cachep);
+		return PTR_ERR(bsg_class);
+	}
+
+	ret = register_chrdev_region(MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS, "bsg");
+	if (ret) {
+		kmem_cache_destroy(bsg_cmd_cachep);
+		class_destroy(bsg_class);
+		return ret;
+	}
+
+	cdev_init(&bsg_cdev, &bsg_fops);
+	ret = cdev_add(&bsg_cdev, MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS);
+	if (ret) {
+		kmem_cache_destroy(bsg_cmd_cachep);
+		class_destroy(bsg_class);
+		unregister_chrdev_region(MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS);
+		return ret;
+	}
+
+	ret = scsi_register_interface(&bsg_intf);
+	if (ret) {
+		printk(KERN_ERR "bsg: failed register scsi interface %d\n", ret);
+		kmem_cache_destroy(bsg_cmd_cachep);
+		class_destroy(bsg_class);
+		unregister_chrdev(BSG_MAJOR, "bsg");
+		return ret;
+	}
+
+	printk(KERN_INFO "%s loaded\n", bsg_version);
+	return 0;
+}
+
+MODULE_AUTHOR("Jens Axboe");
+MODULE_DESCRIPTION("Block layer SGSI generic (sg) driver");
+MODULE_LICENSE("GPL");
+
+device_initcall(bsg_init);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index e0aa4da..9755a3c 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1251,9 +1251,9 @@
 {
 	struct cfq_io_context *cic;
 
-	cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask, cfqd->queue->node);
+	cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
+							cfqd->queue->node);
 	if (cic) {
-		memset(cic, 0, sizeof(*cic));
 		cic->last_end_request = jiffies;
 		INIT_LIST_HEAD(&cic->queue_list);
 		cic->dtor = cfq_free_io_context;
@@ -1376,17 +1376,19 @@
 			 * free memory.
 			 */
 			spin_unlock_irq(cfqd->queue->queue_lock);
-			new_cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask|__GFP_NOFAIL, cfqd->queue->node);
+			new_cfqq = kmem_cache_alloc_node(cfq_pool,
+					gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
+					cfqd->queue->node);
 			spin_lock_irq(cfqd->queue->queue_lock);
 			goto retry;
 		} else {
-			cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask, cfqd->queue->node);
+			cfqq = kmem_cache_alloc_node(cfq_pool,
+					gfp_mask | __GFP_ZERO,
+					cfqd->queue->node);
 			if (!cfqq)
 				goto out;
 		}
 
-		memset(cfqq, 0, sizeof(*cfqq));
-
 		RB_CLEAR_NODE(&cfqq->rb_node);
 		INIT_LIST_HEAD(&cfqq->fifo);
 
@@ -2079,12 +2081,10 @@
 {
 	struct cfq_data *cfqd;
 
-	cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL, q->node);
+	cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (!cfqd)
 		return NULL;
 
-	memset(cfqd, 0, sizeof(*cfqd));
-
 	cfqd->service_tree = CFQ_RB_ROOT;
 	INIT_LIST_HEAD(&cfqd->cic_list);
 
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 6d673e9..87ca02a 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -360,10 +360,9 @@
 {
 	struct deadline_data *dd;
 
-	dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
+	dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (!dd)
 		return NULL;
-	memset(dd, 0, sizeof(*dd));
 
 	INIT_LIST_HEAD(&dd->fifo_list[READ]);
 	INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
diff --git a/block/elevator.c b/block/elevator.c
index 4769a25..d265963 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -177,11 +177,10 @@
 	elevator_t *eq;
 	int i;
 
-	eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL, q->node);
+	eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (unlikely(!eq))
 		goto err;
 
-	memset(eq, 0, sizeof(*eq));
 	eq->ops = &e->ops;
 	eq->elevator_type = e;
 	kobject_init(&eq->kobj);
diff --git a/block/genhd.c b/block/genhd.c
index 863a8c0..3af1e7a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -108,28 +108,24 @@
 
 EXPORT_SYMBOL(register_blkdev);
 
-/* todo: make void - error printk here */
-int unregister_blkdev(unsigned int major, const char *name)
+void unregister_blkdev(unsigned int major, const char *name)
 {
 	struct blk_major_name **n;
 	struct blk_major_name *p = NULL;
 	int index = major_to_index(major);
-	int ret = 0;
 
 	mutex_lock(&block_subsys_lock);
 	for (n = &major_names[index]; *n; n = &(*n)->next)
 		if ((*n)->major == major)
 			break;
-	if (!*n || strcmp((*n)->name, name))
-		ret = -EINVAL;
-	else {
+	if (!*n || strcmp((*n)->name, name)) {
+		WARN_ON(1);
+	} else {
 		p = *n;
 		*n = p->next;
 	}
 	mutex_unlock(&block_subsys_lock);
 	kfree(p);
-
-	return ret;
 }
 
 EXPORT_SYMBOL(unregister_blkdev);
@@ -726,21 +722,21 @@
 {
 	struct gendisk *disk;
 
-	disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
+	disk = kmalloc_node(sizeof(struct gendisk),
+				GFP_KERNEL | __GFP_ZERO, node_id);
 	if (disk) {
-		memset(disk, 0, sizeof(struct gendisk));
 		if (!init_disk_stats(disk)) {
 			kfree(disk);
 			return NULL;
 		}
 		if (minors > 1) {
 			int size = (minors - 1) * sizeof(struct hd_struct *);
-			disk->part = kmalloc_node(size, GFP_KERNEL, node_id);
+			disk->part = kmalloc_node(size,
+				GFP_KERNEL | __GFP_ZERO, node_id);
 			if (!disk->part) {
 				kfree(disk);
 				return NULL;
 			}
-			memset(disk->part, 0, size);
 		}
 		disk->minors = minors;
 		kobj_set_kset_s(disk,block_subsys);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index ef42bb2..d7cadf3 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -256,6 +256,7 @@
 	rq->end_io = NULL;
 	rq->end_io_data = NULL;
 	rq->completion_data = NULL;
+	rq->next_rq = NULL;
 }
 
 /**
@@ -1828,11 +1829,11 @@
 {
 	request_queue_t *q;
 
-	q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id);
+	q = kmem_cache_alloc_node(requestq_cachep,
+				gfp_mask | __GFP_ZERO, node_id);
 	if (!q)
 		return NULL;
 
-	memset(q, 0, sizeof(*q));
 	init_timer(&q->unplug_timer);
 
 	snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index e83f1db..a26ba07 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -41,8 +41,6 @@
 
 EXPORT_SYMBOL(scsi_command_size);
 
-#define BLK_DEFAULT_TIMEOUT	(60 * HZ)
-
 #include <scsi/sg.h>
 
 static int sg_get_version(int __user *p)
@@ -114,7 +112,7 @@
 #define safe_for_read(cmd)	[cmd] = CMD_READ_SAFE
 #define safe_for_write(cmd)	[cmd] = CMD_WRITE_SAFE
 
-static int verify_command(struct file *file, unsigned char *cmd)
+int blk_verify_command(unsigned char *cmd, int has_write_perm)
 {
 	static unsigned char cmd_type[256] = {
 
@@ -193,18 +191,11 @@
 		safe_for_write(GPCMD_SET_STREAMING),
 	};
 	unsigned char type = cmd_type[cmd[0]];
-	int has_write_perm = 0;
 
 	/* Anybody who can open the device can do a read-safe command */
 	if (type & CMD_READ_SAFE)
 		return 0;
 
-	/*
-	 * file can be NULL from ioctl_by_bdev()...
-	 */
-	if (file)
-		has_write_perm = file->f_mode & FMODE_WRITE;
-
 	/* Write-safe commands just require a writable open.. */
 	if ((type & CMD_WRITE_SAFE) && has_write_perm)
 		return 0;
@@ -221,25 +212,96 @@
 	/* Otherwise fail it with an "Operation not permitted" */
 	return -EPERM;
 }
+EXPORT_SYMBOL_GPL(blk_verify_command);
+
+int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq,
+		      struct sg_io_hdr *hdr, int has_write_perm)
+{
+	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+
+	if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
+		return -EFAULT;
+	if (blk_verify_command(rq->cmd, has_write_perm))
+		return -EPERM;
+
+	/*
+	 * fill in request structure
+	 */
+	rq->cmd_len = hdr->cmd_len;
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+	rq->timeout = (hdr->timeout * HZ) / 1000;
+	if (!rq->timeout)
+		rq->timeout = q->sg_timeout;
+	if (!rq->timeout)
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq);
+
+/*
+ * unmap a request that was previously mapped to this sg_io_hdr. handles
+ * both sg and non-sg sg_io_hdr.
+ */
+int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr)
+{
+	blk_rq_unmap_user(rq->bio);
+	blk_put_request(rq);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blk_unmap_sghdr_rq);
+
+int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
+			  struct bio *bio)
+{
+	int r, ret = 0;
+
+	/*
+	 * fill in all the output members
+	 */
+	hdr->status = rq->errors & 0xff;
+	hdr->masked_status = status_byte(rq->errors);
+	hdr->msg_status = msg_byte(rq->errors);
+	hdr->host_status = host_byte(rq->errors);
+	hdr->driver_status = driver_byte(rq->errors);
+	hdr->info = 0;
+	if (hdr->masked_status || hdr->host_status || hdr->driver_status)
+		hdr->info |= SG_INFO_CHECK;
+	hdr->resid = rq->data_len;
+	hdr->sb_len_wr = 0;
+
+	if (rq->sense_len && hdr->sbp) {
+		int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
+
+		if (!copy_to_user(hdr->sbp, rq->sense, len))
+			hdr->sb_len_wr = len;
+		else
+			ret = -EFAULT;
+	}
+
+	rq->bio = bio;
+	r = blk_unmap_sghdr_rq(rq, hdr);
+	if (ret)
+		r = ret;
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(blk_complete_sghdr_rq);
 
 static int sg_io(struct file *file, request_queue_t *q,
 		struct gendisk *bd_disk, struct sg_io_hdr *hdr)
 {
-	unsigned long start_time, timeout;
-	int writing = 0, ret = 0;
+	unsigned long start_time;
+	int writing = 0, ret = 0, has_write_perm = 0;
 	struct request *rq;
 	char sense[SCSI_SENSE_BUFFERSIZE];
-	unsigned char cmd[BLK_MAX_CDB];
 	struct bio *bio;
 
 	if (hdr->interface_id != 'S')
 		return -EINVAL;
 	if (hdr->cmd_len > BLK_MAX_CDB)
 		return -EINVAL;
-	if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len))
-		return -EFAULT;
-	if (verify_command(file, cmd))
-		return -EPERM;
 
 	if (hdr->dxfer_len > (q->max_hw_sectors << 9))
 		return -EIO;
@@ -260,25 +322,13 @@
 	if (!rq)
 		return -ENOMEM;
 
-	/*
-	 * fill in request structure
-	 */
-	rq->cmd_len = hdr->cmd_len;
-	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
-	memcpy(rq->cmd, cmd, hdr->cmd_len);
+	if (file)
+		has_write_perm = file->f_mode & FMODE_WRITE;
 
-	memset(sense, 0, sizeof(sense));
-	rq->sense = sense;
-	rq->sense_len = 0;
-
-	rq->cmd_type = REQ_TYPE_BLOCK_PC;
-
-	timeout = msecs_to_jiffies(hdr->timeout);
-	rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
-	if (!rq->timeout)
-		rq->timeout = q->sg_timeout;
-	if (!rq->timeout)
-		rq->timeout = BLK_DEFAULT_TIMEOUT;
+	if (blk_fill_sghdr_rq(q, rq, hdr, has_write_perm)) {
+		blk_put_request(rq);
+		return -EFAULT;
+	}
 
 	if (hdr->iovec_count) {
 		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
@@ -306,6 +356,9 @@
 		goto out;
 
 	bio = rq->bio;
+	memset(sense, 0, sizeof(sense));
+	rq->sense = sense;
+	rq->sense_len = 0;
 	rq->retries = 0;
 
 	start_time = jiffies;
@@ -316,31 +369,9 @@
 	 */
 	blk_execute_rq(q, bd_disk, rq, 0);
 
-	/* write to all output members */
-	hdr->status = 0xff & rq->errors;
-	hdr->masked_status = status_byte(rq->errors);
-	hdr->msg_status = msg_byte(rq->errors);
-	hdr->host_status = host_byte(rq->errors);
-	hdr->driver_status = driver_byte(rq->errors);
-	hdr->info = 0;
-	if (hdr->masked_status || hdr->host_status || hdr->driver_status)
-		hdr->info |= SG_INFO_CHECK;
-	hdr->resid = rq->data_len;
 	hdr->duration = ((jiffies - start_time) * 1000) / HZ;
-	hdr->sb_len_wr = 0;
 
-	if (rq->sense_len && hdr->sbp) {
-		int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
-
-		if (!copy_to_user(hdr->sbp, rq->sense, len))
-			hdr->sb_len_wr = len;
-	}
-
-	if (blk_rq_unmap_user(bio))
-		ret = -EFAULT;
-
-	/* may not have succeeded, but output values written to control
-	 * structure (struct sg_io_hdr).  */
+	return blk_complete_sghdr_rq(rq, hdr, bio);
 out:
 	blk_put_request(rq);
 	return ret;
@@ -427,7 +458,7 @@
 	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
 		goto error;
 
-	err = verify_command(file, rq->cmd);
+	err = blk_verify_command(rq->cmd, file->f_mode & FMODE_WRITE);
 	if (err)
 		goto error;
 
@@ -454,7 +485,7 @@
 		rq->retries = 1;
 		break;
 	default:
-		rq->timeout = BLK_DEFAULT_TIMEOUT;
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
 		break;
 	}
 
@@ -501,7 +532,7 @@
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->data = NULL;
 	rq->data_len = 0;
-	rq->timeout = BLK_DEFAULT_TIMEOUT;
+	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
 	memset(rq->cmd, 0, sizeof(rq->cmd));
 	rq->cmd[0] = cmd;
 	rq->cmd[4] = data;
@@ -517,16 +548,12 @@
 	return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
 }
 
-int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
+int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
+		   struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
 {
-	request_queue_t *q;
 	int err;
 
-	q = bd_disk->queue;
-	if (!q)
-		return -ENXIO;
-
-	if (blk_get_queue(q))
+	if (!q || blk_get_queue(q))
 		return -ENXIO;
 
 	switch (cmd) {
diff --git a/crypto/proc.c b/crypto/proc.c
index 102c751..3d73323 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -23,24 +23,13 @@
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	struct list_head *v;
-	loff_t n = *pos;
-
 	down_read(&crypto_alg_sem);
-	list_for_each(v, &crypto_alg_list)
-		if (!n--)
-			return list_entry(v, struct crypto_alg, cra_list);
-	return NULL;
+	return seq_list_start(&crypto_alg_list, *pos);
 }
 
 static void *c_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	struct list_head *v = p;
-	
-	(*pos)++;
-	v = v->next;
-	return (v == &crypto_alg_list) ?
-		NULL : list_entry(v, struct crypto_alg, cra_list);
+	return seq_list_next(p, &crypto_alg_list, pos);
 }
 
 static void c_stop(struct seq_file *m, void *p)
@@ -50,7 +39,7 @@
 
 static int c_show(struct seq_file *m, void *p)
 {
-	struct crypto_alg *alg = (struct crypto_alg *)p;
+	struct crypto_alg *alg = list_entry(p, struct crypto_alg, cra_list);
 	
 	seq_printf(m, "name         : %s\n", alg->cra_name);
 	seq_printf(m, "driver       : %s\n", alg->cra_driver_name);
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index 5b4fab2..bb4ae62 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -142,7 +142,7 @@
 
 config ATM_FIRESTREAM
 	tristate "Fujitsu FireStream (FS50/FS155) "
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  Driver for the Fujitsu FireStream 155 (MB86697) and
 	  FireStream 50 (MB86695) ATM PCI chips.
@@ -152,7 +152,7 @@
 
 config ATM_ZATM
 	tristate "ZeitNet ZN1221/ZN1225"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM
 	  adapters.
@@ -240,7 +240,7 @@
 
 config ATM_AMBASSADOR
 	tristate "Madge Ambassador (Collage PCI 155 Server)"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	select BITREVERSE
 	help
 	  This is a driver for ATMizer based ATM card produced by Madge
@@ -265,7 +265,7 @@
 
 config ATM_HORIZON
 	tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  This is a driver for the Horizon chipset ATM adapter cards once
 	  produced by Madge Networks Ltd. Say Y (or M to compile as a module
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index ea4fe3e..de2fcce 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -5,8 +5,11 @@
 # Auxiliary display drivers configuration.
 #
 
-menu "Auxiliary Display support"
+menuconfig AUXDISPLAY
 	depends on PARPORT
+	bool "Auxiliary Display support"
+
+if AUXDISPLAY && PARPORT
 
 config KS0108
 	tristate "KS0108 LCD Controller"
@@ -111,4 +114,5 @@
 
 	  If you compile this as a module, you can still override this
 	  value using the module parameters.
-endmenu
+
+endif # AUXDISPLAY
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 91970e9..7647abf 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -127,7 +127,7 @@
 	} else if (allocation < size)
 		return NULL;
 
-	if (!(retval = kmalloc (sizeof *retval, GFP_KERNEL)))
+	if (!(retval = kmalloc_node (sizeof *retval, GFP_KERNEL, dev_to_node(dev))))
 		return retval;
 
 	strlcpy (retval->name, name, sizeof retval->name);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 6e23af1..8f65b88 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -59,17 +59,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called z2ram.
 
-config ATARI_SLM
-	tristate "Atari SLM laser printer support"
-	depends on ATARI
-	help
-	  If you have an Atari SLM laser printer, say Y to include support for
-	  it in the kernel. Otherwise, say N. This driver is also available as
-	  a module ( = code which can be inserted in and removed from the
-	  running kernel whenever you want). The module will be called
-	  acsi_slm. Be warned: the driver needs much ST-RAM and can cause
-	  problems due to that fact!
-
 config BLK_DEV_XD
 	tristate "XT hard disk support"
 	depends on ISA && ISA_DMA_API
@@ -113,7 +102,7 @@
 
 config BLK_CPQ_DA
 	tristate "Compaq SMART2 support"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  This is the driver for Compaq Smart Array controllers.  Everyone
 	  using these boards should say Y here.  See the file
@@ -423,6 +412,19 @@
 	This driver provides Support for ATA over Ethernet block
 	devices like the Coraid EtherDrive (R) Storage Blade.
 
+config SUNVDC
+	tristate "Sun Virtual Disk Client support"
+	depends on SUN_LDOMS
+	help
+	  Support for virtual disk devices as a client under Sun
+	  Logical Domains.
+
 source "drivers/s390/block/Kconfig"
 
+config XILINX_SYSACE
+	tristate "Xilinx SystemACE support"
+	depends on 4xx
+	help
+	  Include support for the Xilinx SystemACE CompactFlash interface
+
 endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index e5f98ac..9ee08ab 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
 obj-$(CONFIG_AMIGA_FLOPPY)	+= amiflop.o
 obj-$(CONFIG_ATARI_FLOPPY)	+= ataflop.o
-obj-$(CONFIG_ATARI_SLM)		+= acsi_slm.o
 obj-$(CONFIG_AMIGA_Z2RAM)	+= z2ram.o
 obj-$(CONFIG_BLK_DEV_RAM)	+= rd.o
 obj-$(CONFIG_BLK_DEV_LOOP)	+= loop.o
@@ -18,7 +17,9 @@
 obj-$(CONFIG_BLK_CPQ_DA)	+= cpqarray.o
 obj-$(CONFIG_BLK_CPQ_CISS_DA)  += cciss.o
 obj-$(CONFIG_BLK_DEV_DAC960)	+= DAC960.o
+obj-$(CONFIG_XILINX_SYSACE)	+= xsysace.o
 obj-$(CONFIG_CDROM_PKTCDVD)	+= pktcdvd.o
+obj-$(CONFIG_SUNVDC)		+= sunvdc.o
 
 obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
 obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
deleted file mode 100644
index 1d9d9b4..0000000
--- a/drivers/block/acsi_slm.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * acsi_slm.c -- Device driver for the Atari SLM laser printer
- *
- * Copyright 1995 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * 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.
- * 
- */
-
-/*
-
-Notes:
-
-The major number for SLM printers is 28 (like ACSI), but as a character
-device, not block device. The minor number is the number of the printer (if
-you have more than one SLM; currently max. 2 (#define-constant) SLMs are
-supported). The device can be opened for reading and writing. If reading it,
-you get some status infos (MODE SENSE data). Writing mode is used for the data
-to be printed. Some ioctls allow to get the printer status and to tune printer
-modes and some internal variables.
-
-A special problem of the SLM driver is the timing and thus the buffering of
-the print data. The problem is that all the data for one page must be present
-in memory when printing starts, else --when swapping occurs-- the timing could
-not be guaranteed. There are several ways to assure this:
-
- 1) Reserve a buffer of 1196k (maximum page size) statically by
-    atari_stram_alloc(). The data are collected there until they're complete,
-	and then printing starts. Since the buffer is reserved, no further
-	considerations about memory and swapping are needed. So this is the
-	simplest method, but it needs a lot of memory for just the SLM.
-
-    An striking advantage of this method is (supposed the SLM_CONT_CNT_REPROG
-	method works, see there), that there are no timing problems with the DMA
-	anymore.
-	
- 2) The other method would be to reserve the buffer dynamically each time
-    printing is required. I could think of looking at mem_map where the
-	largest unallocted ST-RAM area is, taking the area, and then extending it
-	by swapping out the neighbored pages, until the needed size is reached.
-	This requires some mm hacking, but seems possible. The only obstacle could
-	be pages that cannot be swapped out (reserved pages)...
-
- 3) Another possibility would be to leave the real data in user space and to
-    work with two dribble buffers of about 32k in the driver: While the one
-	buffer is DMAed to the SLM, the other can be filled with new data. But
-	to keep the timing, that requires that the user data remain in memory and
-	are not swapped out. Requires mm hacking, too, but maybe not so bad as
-	method 2).
-
-*/
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-#include <asm/atari_SLM.h>
-
-
-#undef	DEBUG
-
-/* Define this if the page data are continuous in physical memory. That
- * requires less reprogramming of the ST-DMA */
-#define	SLM_CONTINUOUS_DMA
-
-/* Use continuous reprogramming of the ST-DMA counter register. This is
- * --strictly speaking-- not allowed, Atari recommends not to look at the
- * counter register while a DMA is going on. But I don't know if that applies
- * only for reading the register, or also writing to it. Writing only works
- * fine for me... The advantage is that the timing becomes absolutely
- * uncritical: Just update each, say 200ms, the counter reg to its maximum,
- * and the DMA will work until the status byte interrupt occurs.
- */
-#define	SLM_CONT_CNT_REPROG
-
-#define CMDSET_TARG_LUN(cmd,targ,lun)			\
-    do {										\
-		cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5;	\
-		cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5;	\
-	} while(0)
-
-#define	START_TIMER(to)	mod_timer(&slm_timer, jiffies + (to))
-#define	STOP_TIMER()	del_timer(&slm_timer)
-
-
-static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 };
-static char slmprint_cmd[6]    = { 0x0a, 0, 0, 0, 0, 0 };
-static char slminquiry_cmd[6]  = { 0x12, 0, 0, 0, 0, 0x80 };
-static char slmmsense_cmd[6]   = { 0x1a, 0, 0, 0, 255, 0 };
-#if 0
-static char slmmselect_cmd[6]  = { 0x15, 0, 0, 0, 0, 0 };
-#endif
-
-
-#define	MAX_SLM		2
-
-static struct slm {
-	unsigned	target;			/* target number */
-	unsigned	lun;			/* LUN in target controller */
-	atomic_t	wr_ok; 			/* set to 0 if output part busy */
-	atomic_t	rd_ok;			/* set to 0 if status part busy */
-} slm_info[MAX_SLM];
-
-int N_SLM_Printers = 0;
-
-/* printer buffer */
-static unsigned char	*SLMBuffer;	/* start of buffer */
-static unsigned char	*BufferP;	/* current position in buffer */
-static int				BufferSize;	/* length of buffer for page size */
-
-typedef enum { IDLE, FILLING, PRINTING } SLMSTATE;
-static SLMSTATE			SLMState;
-static int				SLMBufOwner;	/* SLM# currently using the buffer */
-
-/* DMA variables */
-#ifndef SLM_CONT_CNT_REPROG
-static unsigned long	SLMCurAddr;		/* current base addr of DMA chunk */
-static unsigned long	SLMEndAddr;		/* expected end addr */
-static unsigned long	SLMSliceSize;	/* size of one DMA chunk */
-#endif
-static int				SLMError;
-
-/* wait queues */
-static DECLARE_WAIT_QUEUE_HEAD(slm_wait);	/* waiting for buffer */
-static DECLARE_WAIT_QUEUE_HEAD(print_wait);	/* waiting for printing finished */
-
-/* status codes */
-#define	SLMSTAT_OK		0x00
-#define	SLMSTAT_ORNERY	0x02
-#define	SLMSTAT_TONER	0x03
-#define	SLMSTAT_WARMUP	0x04
-#define	SLMSTAT_PAPER	0x05
-#define	SLMSTAT_DRUM	0x06
-#define	SLMSTAT_INJAM	0x07
-#define	SLMSTAT_THRJAM	0x08
-#define	SLMSTAT_OUTJAM	0x09
-#define	SLMSTAT_COVER	0x0a
-#define	SLMSTAT_FUSER	0x0b
-#define	SLMSTAT_IMAGER	0x0c
-#define	SLMSTAT_MOTOR	0x0d
-#define	SLMSTAT_VIDEO	0x0e
-#define	SLMSTAT_SYSTO	0x10
-#define	SLMSTAT_OPCODE	0x12
-#define	SLMSTAT_DEVNUM	0x15
-#define	SLMSTAT_PARAM	0x1a
-#define	SLMSTAT_ACSITO	0x1b	/* driver defined */
-#define	SLMSTAT_NOTALL	0x1c	/* driver defined */
-
-static char *SLMErrors[] = {
-	/* 0x00 */	"OK and ready",
-	/* 0x01 */	NULL,
-	/* 0x02 */	"ornery printer",
-	/* 0x03 */	"toner empty",
-	/* 0x04 */	"warming up",
-	/* 0x05 */	"paper empty",
-	/* 0x06 */	"drum empty",
-	/* 0x07 */	"input jam",
-	/* 0x08 */	"through jam",
-	/* 0x09 */	"output jam",
-	/* 0x0a */	"cover open",
-	/* 0x0b */	"fuser malfunction",
-	/* 0x0c */	"imager malfunction",
-	/* 0x0d */	"motor malfunction",
-	/* 0x0e */	"video malfunction",
-	/* 0x0f */	NULL,
-	/* 0x10 */	"printer system timeout",
-	/* 0x11 */	NULL,
-	/* 0x12 */	"invalid operation code",
-	/* 0x13 */	NULL,
-	/* 0x14 */	NULL,
-	/* 0x15 */	"invalid device number",
-	/* 0x16 */	NULL,
-	/* 0x17 */	NULL,
-	/* 0x18 */	NULL,
-	/* 0x19 */	NULL,
-	/* 0x1a */	"invalid parameter list",
-	/* 0x1b */	"ACSI timeout",
-	/* 0x1c */	"not all printed"
-};
-
-#define	N_ERRORS	(sizeof(SLMErrors)/sizeof(*SLMErrors))
-
-/* real (driver caused) error? */
-#define	IS_REAL_ERROR(x)	(x > 0x10)
-
-
-static struct {
-	char	*name;
-	int 	w, h;
-} StdPageSize[] = {
-	{ "Letter", 2400, 3180 },
-	{ "Legal",  2400, 4080 },
-	{ "A4",     2336, 3386 },
-	{ "B5",     2016, 2914 }
-};
-
-#define	N_STD_SIZES		(sizeof(StdPageSize)/sizeof(*StdPageSize))
-
-#define	SLM_BUFFER_SIZE	(2336*3386/8)	/* A4 for now */
-#define	SLM_DMA_AMOUNT	255				/* #sectors to program the DMA for */
-
-#ifdef	SLM_CONTINUOUS_DMA
-# define	SLM_DMA_INT_OFFSET	0		/* DMA goes until seccnt 0, no offs */
-# define	SLM_DMA_END_OFFSET	32		/* 32 Byte ST-DMA FIFO */
-# define	SLM_SLICE_SIZE(w) 	(255*512)
-#else
-# define	SLM_DMA_INT_OFFSET	32		/* 32 Byte ST-DMA FIFO */
-# define	SLM_DMA_END_OFFSET	32		/* 32 Byte ST-DMA FIFO */
-# define	SLM_SLICE_SIZE(w)	((254*512)/(w/8)*(w/8))
-#endif
-
-/* calculate the number of jiffies to wait for 'n' bytes */
-#ifdef SLM_CONT_CNT_REPROG
-#define	DMA_TIME_FOR(n)		50
-#define	DMA_STARTUP_TIME	0
-#else
-#define	DMA_TIME_FOR(n)		(n/1400-1)
-#define	DMA_STARTUP_TIME	650
-#endif
-
-/***************************** Prototypes *****************************/
-
-static char *slm_errstr( int stat );
-static int slm_getstats( char *buffer, int device );
-static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
-                         *ppos );
-static void start_print( int device );
-static irqreturn_t slm_interrupt(int irc, void *data);
-static void slm_test_ready( unsigned long dummy );
-static void set_dma_addr( unsigned long paddr );
-static unsigned long get_dma_addr( void );
-static ssize_t slm_write( struct file *file, const char *buf, size_t count,
-                          loff_t *ppos );
-static int slm_ioctl( struct inode *inode, struct file *file, unsigned int
-                      cmd, unsigned long arg );
-static int slm_open( struct inode *inode, struct file *file );
-static int slm_release( struct inode *inode, struct file *file );
-static int slm_req_sense( int device );
-static int slm_mode_sense( int device, char *buffer, int abs_flag );
-#if 0
-static int slm_mode_select( int device, char *buffer, int len, int
-                            default_flag );
-#endif
-static int slm_get_pagesize( int device, int *w, int *h );
-
-/************************* End of Prototypes **************************/
-
-
-static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
-
-static const struct file_operations slm_fops = {
-	.owner =	THIS_MODULE,
-	.read =		slm_read,
-	.write =	slm_write,
-	.ioctl =	slm_ioctl,
-	.open =		slm_open,
-	.release =	slm_release,
-};
-
-
-/* ---------------------------------------------------------------------- */
-/*							   Status Functions							  */
-
-
-static char *slm_errstr( int stat )
-
-{	char *p;
-	static char	str[22];
-
-	stat &= 0x1f;
-	if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat]))
-		return( p );
-	sprintf( str, "unknown status 0x%02x", stat );
-	return( str );
-}
-
-
-static int slm_getstats( char *buffer, int device )
-
-{	int 			len = 0, stat, i, w, h;
-	unsigned char	buf[256];
-	
-	stat = slm_mode_sense( device, buf, 0 );
-	if (IS_REAL_ERROR(stat))
-		return( -EIO );
-	
-#define SHORTDATA(i)		((buf[i] << 8) | buf[i+1])
-#define	BOOLDATA(i,mask)	((buf[i] & mask) ? "on" : "off")
-
-	w = SHORTDATA( 3 );
-	h = SHORTDATA( 1 );
-		
-	len += sprintf( buffer+len, "Status\t\t%s\n",
-					slm_errstr( stat ) );
-	len += sprintf( buffer+len, "Page Size\t%dx%d",
-					w, h );
-
-	for( i = 0; i < N_STD_SIZES; ++i ) {
-		if (w == StdPageSize[i].w && h == StdPageSize[i].h)
-			break;
-	}
-	if (i < N_STD_SIZES)
-		len += sprintf( buffer+len, " (%s)", StdPageSize[i].name );
-	buffer[len++] = '\n';
-
-	len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n",
-					SHORTDATA( 5 ), SHORTDATA( 7 ) );
-	len += sprintf( buffer+len, "Manual Feed\t%s\n",
-					BOOLDATA( 9, 0x01 ) );
-	len += sprintf( buffer+len, "Input Select\t%d\n",
-					(buf[9] >> 1) & 7 );
-	len += sprintf( buffer+len, "Auto Select\t%s\n",
-					BOOLDATA( 9, 0x10 ) );
-	len += sprintf( buffer+len, "Prefeed Paper\t%s\n",
-					BOOLDATA( 9, 0x20 ) );
-	len += sprintf( buffer+len, "Thick Pixels\t%s\n",
-					BOOLDATA( 9, 0x40 ) );
-	len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n",
-					SHORTDATA( 12 ), SHORTDATA( 10 ) );
-	len += sprintf( buffer+len, "System Timeout\t%d\n",
-					buf[14] );
-	len += sprintf( buffer+len, "Scan Time\t%d\n",
-					SHORTDATA( 15 ) );
-	len += sprintf( buffer+len, "Page Count\t%d\n",
-					SHORTDATA( 17 ) );
-	len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n",
-					SHORTDATA( 19 ), SHORTDATA( 21 ) );
-	len += sprintf( buffer+len, "Stagger Output\t%s\n",
-					BOOLDATA( 23, 0x01 ) );
-	len += sprintf( buffer+len, "Output Select\t%d\n",
-					(buf[23] >> 1) & 7 );
-	len += sprintf( buffer+len, "Duplex Print\t%s\n",
-					BOOLDATA( 23, 0x10 ) );
-	len += sprintf( buffer+len, "Color Sep.\t%s\n",
-					BOOLDATA( 23, 0x20 ) );
-
-	return( len );
-}
-
-
-static ssize_t slm_read( struct file *file, char *buf, size_t count,
-						 loff_t *ppos )
-
-{
-	struct inode *node = file->f_path.dentry->d_inode;
-	unsigned long page;
-	int length;
-	int end;
-
-	if (!(page = __get_free_page( GFP_KERNEL )))
-		return( -ENOMEM );
-	
-	length = slm_getstats( (char *)page, iminor(node) );
-	if (length < 0) {
-		count = length;
-		goto out;
-	}
-	if (file->f_pos >= length) {
-		count = 0;
-		goto out;
-	}
-	if (count + file->f_pos > length)
-		count = length - file->f_pos;
-	end = count + file->f_pos;
-	if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	file->f_pos = end;
-out:	free_page( page );
-	return( count );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*								   Printing								  */
-
-
-static void start_print( int device )
-
-{	struct slm *sip = &slm_info[device];
-	unsigned char	*cmd;
-	unsigned long	paddr;
-	int				i;
-	
-	stdma_lock( slm_interrupt, NULL );
-
-	CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
-	cmd = slmprint_cmd;
-	paddr = virt_to_phys( SLMBuffer );
-	dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
-	DISABLE_IRQ();
-
-	/* Low on A1 */
-	dma_wd.dma_mode_status = 0x88;
-	MFPDELAY();
-
-	/* send the command bytes except the last */
-	for( i = 0; i < 5; ++i ) {
-		DMA_LONG_WRITE( *cmd++, 0x8a );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) {
-			SLMError = 1;
-			return; /* timeout */
-		}
-	}
-	/* last command byte */
-	DMA_LONG_WRITE( *cmd++, 0x82 );
-	MFPDELAY();
-	/* set DMA address */
-	set_dma_addr( paddr );
-	/* program DMA for write and select sector counter reg */
-	dma_wd.dma_mode_status = 0x192;
-	MFPDELAY();
-	/* program for 255*512 bytes and start DMA */
-	DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
-
-#ifndef SLM_CONT_CNT_REPROG
-	SLMCurAddr = paddr;
-	SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
-#endif
-	START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize ));
-#if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG)
-	printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
-			SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
-#endif
-	
-	ENABLE_IRQ();
-}
-
-
-/* Only called when an error happened or at the end of a page */
-
-static irqreturn_t slm_interrupt(int irc, void *data)
-
-{	unsigned long	addr;
-	int				stat;
-	
-	STOP_TIMER();
-	addr = get_dma_addr();
-	stat = acsi_getstatus();
-	SLMError = (stat < 0)             ? SLMSTAT_ACSITO :
-		       (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
-									    stat;
-
-	dma_wd.dma_mode_status = 0x80;
-	MFPDELAY();
-#ifdef DEBUG
-	printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError );
-#endif
-
-	wake_up( &print_wait );
-	stdma_release();
-	ENABLE_IRQ();
-	return IRQ_HANDLED;
-}
-
-
-static void slm_test_ready( unsigned long dummy )
-
-{
-#ifdef SLM_CONT_CNT_REPROG
-	/* program for 255*512 bytes again */
-	dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
-	START_TIMER( DMA_TIME_FOR(0) );
-#ifdef DEBUG
-	printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n",
-			DMA_TIME_FOR(0), get_dma_addr() );
-#endif
-	
-#else /* !SLM_CONT_CNT_REPROG */
-
-	unsigned long	flags, addr;
-	int				d, ti;
-#ifdef DEBUG
-	struct timeval start_tm, end_tm;
-	int			   did_wait = 0;
-#endif
-
-	local_irq_save(flags);
-
-	addr = get_dma_addr();
-	if ((d = SLMEndAddr - addr) > 0) {
-		local_irq_restore(flags);
-		
-		/* slice not yet finished, decide whether to start another timer or to
-		 * busy-wait */
-		ti = DMA_TIME_FOR( d );
-		if (ti > 0) {
-#ifdef DEBUG
-			printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n",
-					ti, d );
-#endif
-			START_TIMER( ti );
-			return;
-		}
-		/* wait for desired end address to be reached */
-#ifdef DEBUG
-		do_gettimeofday( &start_tm );
-		did_wait = 1;
-#endif
-		local_irq_disable();
-		while( get_dma_addr() < SLMEndAddr )
-			barrier();
-	}
-
-	/* slice finished, start next one */
-	SLMCurAddr += SLMSliceSize;
-
-#ifdef SLM_CONTINUOUS_DMA
-	/* program for 255*512 bytes again */
-	dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
-#else
-	/* set DMA address;
-	 * add 2 bytes for the ones in the SLM controller FIFO! */
-	set_dma_addr( SLMCurAddr + 2 );
-	/* toggle DMA to write and select sector counter reg */
-	dma_wd.dma_mode_status = 0x92;
-	MFPDELAY();
-	dma_wd.dma_mode_status = 0x192;
-	MFPDELAY();
-	/* program for 255*512 bytes and start DMA */
-	DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
-#endif
-	
-	local_irq_restore(flags);
-
-#ifdef DEBUG
-	if (did_wait) {
-		int ms;
-		do_gettimeofday( &end_tm );
-		ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) -
-			 (start_tm.tv_sec*1000000+start_tm.tv_usec); 
-		printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n",
-				ms/1000, ms%1000, d );
-	}
-	else
-		printk( "SLM: didn't wait (!)\n" );
-#endif
-
-	if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) {
-		/* will be last slice, no timer necessary */
-#ifdef DEBUG
-		printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n",
-				SLMCurAddr, SLMEndAddr );
-#endif
-	}
-	else {
-		/* not last slice */
-		SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
-		START_TIMER( DMA_TIME_FOR( SLMSliceSize ));
-#ifdef DEBUG
-		printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
-				SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
-#endif
-	}
-#endif /* SLM_CONT_CNT_REPROG */
-}
-
-
-static void set_dma_addr( unsigned long paddr )
-
-{	unsigned long flags;
-
-	local_irq_save(flags);
-	dma_wd.dma_lo = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	dma_wd.dma_md = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	if (ATARIHW_PRESENT( EXTD_DMA ))
-		st_dma_ext_dmahi = (unsigned short)paddr;
-	else
-		dma_wd.dma_hi = (unsigned char)paddr;
-	MFPDELAY();
-	local_irq_restore(flags);
-}
-
-
-static unsigned long get_dma_addr( void )
-
-{	unsigned long	addr;
-	
-	addr = dma_wd.dma_lo & 0xff;
-	MFPDELAY();
-	addr |= (dma_wd.dma_md & 0xff) << 8;
-	MFPDELAY();
-	addr |= (dma_wd.dma_hi & 0xff) << 16;
-	MFPDELAY();
-
-	return( addr );
-}
-
-
-static ssize_t slm_write( struct file *file, const char *buf, size_t count,
-						  loff_t *ppos )
-
-{
-	struct inode *node = file->f_path.dentry->d_inode;
-	int		device = iminor(node);
-	int		n, filled, w, h;
-
-	while( SLMState == PRINTING ||
-		   (SLMState == FILLING && SLMBufOwner != device) ) {
-		interruptible_sleep_on( &slm_wait );
-		if (signal_pending(current))
-			return( -ERESTARTSYS );
-	}
-	if (SLMState == IDLE) {
-		/* first data of page: get current page size  */
-		if (slm_get_pagesize( device, &w, &h ))
-			return( -EIO );
-		BufferSize = w*h/8;
-		if (BufferSize > SLM_BUFFER_SIZE)
-			return( -ENOMEM );
-
-		SLMState = FILLING;
-		SLMBufOwner = device;
-	}
-
-	n = count;
-	filled = BufferP - SLMBuffer;
-	if (filled + n > BufferSize)
-		n = BufferSize - filled;
-
-	if (copy_from_user(BufferP, buf, n))
-		return -EFAULT;
-	BufferP += n;
-	filled += n;
-
-	if (filled == BufferSize) {
-		/* Check the paper size again! The user may have switched it in the
-		 * time between starting the data and finishing them. Would end up in
-		 * a trashy page... */
-		if (slm_get_pagesize( device, &w, &h ))
-			return( -EIO );
-		if (BufferSize != w*h/8) {
-			printk( KERN_NOTICE "slm%d: page size changed while printing\n",
-					device );
-			return( -EAGAIN );
-		}
-
-		SLMState = PRINTING;
-		/* choose a slice size that is a multiple of the line size */
-#ifndef SLM_CONT_CNT_REPROG
-		SLMSliceSize = SLM_SLICE_SIZE(w);
-#endif
-		
-		start_print( device );
-		sleep_on( &print_wait );
-		if (SLMError && IS_REAL_ERROR(SLMError)) {
-			printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) );
-			n = -EIO;
-		}
-
-		SLMState = IDLE;
-		BufferP = SLMBuffer;
-		wake_up_interruptible( &slm_wait );
-	}
-	
-	return( n );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*							   ioctl Functions							  */
-
-
-static int slm_ioctl( struct inode *inode, struct file *file,
-					  unsigned int cmd, unsigned long arg )
-
-{	int		device = iminor(inode), err;
-	
-	/* I can think of setting:
-	 *  - manual feed
-	 *  - paper format
-	 *  - copy count
-	 *  - ...
-	 * but haven't implemented that yet :-)
-	 * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data?
-	 */
-	switch( cmd ) {
-
-	  case SLMIORESET:		/* reset buffer, i.e. empty the buffer */
-		if (!(file->f_mode & 2))
-			return( -EINVAL );
-		if (SLMState == PRINTING)
-			return( -EBUSY );
-		SLMState = IDLE;
-		BufferP = SLMBuffer;
-		wake_up_interruptible( &slm_wait );
-		return( 0 );
-		
-	  case SLMIOGSTAT: {	/* get status */
-		int stat;
-		char *str;
-
-		stat = slm_req_sense( device );
-		if (arg) {
-			str = slm_errstr( stat );
-			if (put_user(stat,
-    	    	    	    	     (long *)&((struct SLM_status *)arg)->stat))
-    	    	    	    	return -EFAULT;
-			if (copy_to_user( ((struct SLM_status *)arg)->str, str,
-						 strlen(str) + 1))
-				return -EFAULT;
-		}
-		return( stat );
-	  }
-		
-	  case SLMIOGPSIZE: {	/* get paper size */
-		int w, h;
-		
-		if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
-		
-    	    	if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
-			return -EFAULT;
-		if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height))
-			return -EFAULT;
-		return( 0 );
-	  }
-		
-	  case SLMIOGMFEED:	/* get manual feed */
-		return( -EINVAL );
-
-	  case SLMIOSPSIZE:	/* set paper size */
-		return( -EINVAL );
-
-	  case SLMIOSMFEED:	/* set manual feed */
-		return( -EINVAL );
-
-	}
-	return( -EINVAL );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*							 Opening and Closing						  */
-
-
-static int slm_open( struct inode *inode, struct file *file )
-
-{	int device;
-	struct slm *sip;
-	
-	device = iminor(inode);
-	if (device >= N_SLM_Printers)
-		return( -ENXIO );
-	sip = &slm_info[device];
-
-	if (file->f_mode & 2) {
-		/* open for writing is exclusive */
-		if ( !atomic_dec_and_test(&sip->wr_ok) ) {
-			atomic_inc(&sip->wr_ok);	
-			return( -EBUSY );
-		}
-	}
-	if (file->f_mode & 1) {
-		/* open for reading is exclusive */
-                if ( !atomic_dec_and_test(&sip->rd_ok) ) {
-                        atomic_inc(&sip->rd_ok);
-                        return( -EBUSY );
-                }
-	}
-
-	return( 0 );
-}
-
-
-static int slm_release( struct inode *inode, struct file *file )
-
-{	int device;
-	struct slm *sip;
-	
-	device = iminor(inode);
-	sip = &slm_info[device];
-
-	if (file->f_mode & 2)
-		atomic_inc( &sip->wr_ok );
-	if (file->f_mode & 1)
-		atomic_inc( &sip->rd_ok );
-	
-	return( 0 );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*						 ACSI Primitives for the SLM					  */
-
-
-static int slm_req_sense( int device )
-
-{	int			stat, rv;
-	struct slm *sip = &slm_info[device];
-	
-	stdma_lock( NULL, NULL );
-
-	CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun );
-	if (!acsicmd_nodma( slmreqsense_cmd, 0 ) ||
-		(stat = acsi_getstatus()) < 0)
-		rv = SLMSTAT_ACSITO;
-	else
-		rv = stat & 0x1f;
-
-	ENABLE_IRQ();
-	stdma_release();
-	return( rv );
-}
-
-
-static int slm_mode_sense( int device, char *buffer, int abs_flag )
-
-{	unsigned char	stat, len;
-	int				rv = 0;
-	struct slm		*sip = &slm_info[device];
-	
-	stdma_lock( NULL, NULL );
-
-	CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun );
-	slmmsense_cmd[5] = abs_flag ? 0x80 : 0;
-	if (!acsicmd_nodma( slmmsense_cmd, 0 )) {
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-
-	if (!acsi_extstatus( &stat, 1 )) {
-		acsi_end_extstatus();
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-	
-	if (!acsi_extstatus( &len, 1 )) {
-		acsi_end_extstatus();
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-	buffer[0] = len;
-	if (!acsi_extstatus( buffer+1, len )) {
-		acsi_end_extstatus();
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-	
-	acsi_end_extstatus();
-	rv = stat & 0x1f;
-
-  the_end:
-	ENABLE_IRQ();
-	stdma_release();
-	return( rv );
-}
-
-
-#if 0
-/* currently unused */
-static int slm_mode_select( int device, char *buffer, int len,
-							int default_flag )
-
-{	int			stat, rv;
-	struct slm	*sip = &slm_info[device];
-	
-	stdma_lock( NULL, NULL );
-
-	CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun );
-	slmmselect_cmd[5] = default_flag ? 0x80 : 0;
-	if (!acsicmd_nodma( slmmselect_cmd, 0 )) {
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-
-	if (!default_flag) {
-		unsigned char c = len;
-		if (!acsi_extcmd( &c, 1 )) {
-			rv = SLMSTAT_ACSITO;
-			goto the_end;
-		}
-		if (!acsi_extcmd( buffer, len )) {
-			rv = SLMSTAT_ACSITO;
-			goto the_end;
-		}
-	}
-	
-	stat = acsi_getstatus();
-	rv = (stat < 0 ? SLMSTAT_ACSITO : stat);
-
-  the_end:
-	ENABLE_IRQ();
-	stdma_release();
-	return( rv );
-}
-#endif
-
-
-static int slm_get_pagesize( int device, int *w, int *h )
-
-{	char	buf[256];
-	int		stat;
-	
-	stat = slm_mode_sense( device, buf, 0 );
-	ENABLE_IRQ();
-	stdma_release();
-
-	if (stat != SLMSTAT_OK)
-		return( -EIO );
-
-	*w = (buf[3] << 8) | buf[4];
-	*h = (buf[1] << 8) | buf[2];
-	return( 0 );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*								Initialization							  */
-
-
-int attach_slm( int target, int lun )
-
-{	static int	did_register;
-	int			len;
-
-	if (N_SLM_Printers >= MAX_SLM) {
-		printk( KERN_WARNING "Too much SLMs\n" );
-		return( 0 );
-	}
-	
-	/* do an INQUIRY */
-	udelay(100);
-	CMDSET_TARG_LUN( slminquiry_cmd, target, lun );
-	if (!acsicmd_nodma( slminquiry_cmd, 0 )) {
-	  inq_timeout:
-		printk( KERN_ERR "SLM inquiry command timed out.\n" );
-	  inq_fail:
-		acsi_end_extstatus();
-		return( 0 );
-	}
-	/* read status and header of return data */
-	if (!acsi_extstatus( SLMBuffer, 6 ))
-		goto inq_timeout;
-
-	if (SLMBuffer[1] != 2) { /* device type == printer? */
-		printk( KERN_ERR "SLM inquiry returned device type != printer\n" );
-		goto inq_fail;
-	}
-	len = SLMBuffer[5];
-	
-	/* read id string */
-	if (!acsi_extstatus( SLMBuffer, len ))
-		goto inq_timeout;
-	acsi_end_extstatus();
-	SLMBuffer[len] = 0;
-
-	if (!did_register) {
-		did_register = 1;
-	}
-
-	slm_info[N_SLM_Printers].target = target;
-	slm_info[N_SLM_Printers].lun    = lun;
-	atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 ); 
-	atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 );
-	
-	printk( KERN_INFO "  Printer: %s\n", SLMBuffer );
-	printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
-			N_SLM_Printers, target, lun );
-	N_SLM_Printers++;
-	return( 1 );
-}
-
-int slm_init( void )
-
-{
-	int i;
-	if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) {
-		printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR );
-		return -EBUSY;
-	}
-	
-	if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) {
-		printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" );
-		unregister_chrdev( ACSI_MAJOR, "slm" );
-		return -ENOMEM;
-	}
-	BufferP = SLMBuffer;
-	SLMState = IDLE;
-	
-	return 0;
-}
-
-#ifdef MODULE
-
-/* from acsi.c */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-int init_module(void)
-{
-	int err;
-
-	if ((err = slm_init()))
-		return( err );
-	/* This calls attach_slm() for every target/lun where acsi.c detected a
-	 * printer */
-	acsi_attach_SLMs( attach_slm );
-	return( 0 );
-}
-
-void cleanup_module(void)
-{
-	if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0)
-		printk( KERN_ERR "acsi_slm: cleanup_module failed\n");
-	atari_stram_free( SLMBuffer );
-}
-#endif
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 0fcad43..a2d6612 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1170,7 +1170,7 @@
 	case SG_EMULATED_HOST:
 	case SG_IO:
 	case SCSI_IOCTL_SEND_COMMAND:
-		return scsi_cmd_ioctl(filep, disk, cmd, argp);
+		return scsi_cmd_ioctl(filep, disk->queue, disk, cmd, argp);
 
 	/* scsi_cmd_ioctl would normally handle these, below, but */
 	/* they aren't a good fit for cciss, as CD-ROMs are */
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 4503290..e425daa 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -68,6 +68,7 @@
 #include <linux/loop.h>
 #include <linux/compat.h>
 #include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>		/* for invalidate_bdev() */
 #include <linux/completion.h>
@@ -600,13 +601,6 @@
 	struct loop_device *lo = data;
 	struct bio *bio;
 
-	/*
-	 * loop can be used in an encrypted device,
-	 * hence, it mustn't be stopped at all
-	 * because it could be indirectly used during suspension
-	 */
-	current->flags |= PF_NOFREEZE;
-
 	set_user_nice(current, -20);
 
 	while (!kthread_should_stop() || lo->lo_bio) {
@@ -1574,8 +1568,7 @@
 		loop_del_one(lo);
 
 	blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
-	if (unregister_blkdev(LOOP_MAJOR, "loop"))
-		printk(KERN_WARNING "loop: cannot unregister blkdev\n");
+	unregister_blkdev(LOOP_MAJOR, "loop");
 }
 
 module_init(loop_init);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index c575fb1..c129510 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -122,17 +122,12 @@
 	int result;
 	struct msghdr msg;
 	struct kvec iov;
-	unsigned long flags;
-	sigset_t oldset;
+	sigset_t blocked, oldset;
 
 	/* Allow interception of SIGKILL only
 	 * Don't allow other signals to interrupt the transmission */
-	spin_lock_irqsave(&current->sighand->siglock, flags);
-	oldset = current->blocked;
-	sigfillset(&current->blocked);
-	sigdelsetmask(&current->blocked, sigmask(SIGKILL));
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	siginitsetinv(&blocked, sigmask(SIGKILL));
+	sigprocmask(SIG_SETMASK, &blocked, &oldset);
 
 	do {
 		sock->sk->sk_allocation = GFP_NOIO;
@@ -151,11 +146,9 @@
 
 		if (signal_pending(current)) {
 			siginfo_t info;
-			spin_lock_irqsave(&current->sighand->siglock, flags);
 			printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
-				current->pid, current->comm, 
-				dequeue_signal(current, &current->blocked, &info));
-			spin_unlock_irqrestore(&current->sighand->siglock, flags);
+				current->pid, current->comm,
+				dequeue_signal_lock(current, &current->blocked, &info));
 			result = -EINTR;
 			break;
 		}
@@ -169,10 +162,7 @@
 		buf += result;
 	} while (size > 0);
 
-	spin_lock_irqsave(&current->sighand->siglock, flags);
-	current->blocked = oldset;
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	sigprocmask(SIG_SETMASK, &oldset, NULL);
 
 	return result;
 }
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ce64e86..31be33e 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1593,6 +1593,7 @@
 	long min_sleep_time, residue;
 
 	set_user_nice(current, -20);
+	set_freezable();
 
 	for (;;) {
 		DECLARE_WAITQUEUE(wait, current);
@@ -1652,9 +1653,6 @@
 				}
 			}
 
-			if (signal_pending(current)) {
-				flush_signals(current);
-			}
 			if (kthread_should_stop())
 				break;
 		}
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
new file mode 100644
index 0000000..0f5e3ca
--- /dev/null
+++ b/drivers/block/sunvdc.c
@@ -0,0 +1,972 @@
+/* sunvdc.c: Sun LDOM Virtual Disk Client.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/list.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#define DRV_MODULE_NAME		"sunvdc"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"June 25, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual disk client driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define VDC_TX_RING_SIZE	256
+
+#define WAITING_FOR_LINK_UP	0x01
+#define WAITING_FOR_TX_SPACE	0x02
+#define WAITING_FOR_GEN_CMD	0x04
+#define WAITING_FOR_ANY		-1
+
+struct vdc_req_entry {
+	struct request		*req;
+};
+
+struct vdc_port {
+	struct vio_driver_state	vio;
+
+	struct vdc		*vp;
+
+	struct gendisk		*disk;
+
+	struct vdc_completion	*cmp;
+
+	u64			req_id;
+	u64			seq;
+	struct vdc_req_entry	rq_arr[VDC_TX_RING_SIZE];
+
+	unsigned long		ring_cookies;
+
+	u64			max_xfer_size;
+	u32			vdisk_block_size;
+
+	/* The server fills these in for us in the disk attribute
+	 * ACK packet.
+	 */
+	u64			operations;
+	u32			vdisk_size;
+	u8			vdisk_type;
+	u8			dev_no;
+
+	char			disk_name[32];
+
+	struct vio_disk_geom	geom;
+	struct vio_disk_vtoc	label;
+
+	struct list_head	list;
+};
+
+static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
+{
+	return container_of(vio, struct vdc_port, vio);
+}
+
+struct vdc {
+	/* Protects prot_list.  */
+	spinlock_t		lock;
+
+	struct vio_dev		*dev;
+
+	struct list_head	port_list;
+};
+
+/* Ordered from largest major to lowest */
+static struct vio_version vdc_versions[] = {
+	{ .major = 1, .minor = 0 },
+};
+
+#define VDCBLK_NAME	"vdisk"
+static int vdc_major;
+#define PARTITION_SHIFT	3
+
+static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr)
+{
+	return vio_dring_avail(dr, VDC_TX_RING_SIZE);
+}
+
+static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+	struct gendisk *disk = bdev->bd_disk;
+	struct vdc_port *port = disk->private_data;
+
+	geo->heads = (u8) port->geom.num_hd;
+	geo->sectors = (u8) port->geom.num_sec;
+	geo->cylinders = port->geom.num_cyl;
+
+	return 0;
+}
+
+static struct block_device_operations vdc_fops = {
+	.owner		= THIS_MODULE,
+	.getgeo		= vdc_getgeo,
+};
+
+static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
+{
+	if (vio->cmp &&
+	    (waiting_for == -1 ||
+	     vio->cmp->waiting_for == waiting_for)) {
+		vio->cmp->err = err;
+		complete(&vio->cmp->com);
+		vio->cmp = NULL;
+	}
+}
+
+static void vdc_handshake_complete(struct vio_driver_state *vio)
+{
+	vdc_finish(vio, 0, WAITING_FOR_LINK_UP);
+}
+
+static int vdc_handle_unknown(struct vdc_port *port, void *arg)
+{
+	struct vio_msg_tag *pkt = arg;
+
+	printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+	printk(KERN_ERR PFX "Resetting connection.\n");
+
+	ldc_disconnect(port->vio.lp);
+
+	return -ECONNRESET;
+}
+
+static int vdc_send_attr(struct vio_driver_state *vio)
+{
+	struct vdc_port *port = to_vdc_port(vio);
+	struct vio_disk_attr_info pkt;
+
+	memset(&pkt, 0, sizeof(pkt));
+
+	pkt.tag.type = VIO_TYPE_CTRL;
+	pkt.tag.stype = VIO_SUBTYPE_INFO;
+	pkt.tag.stype_env = VIO_ATTR_INFO;
+	pkt.tag.sid = vio_send_sid(vio);
+
+	pkt.xfer_mode = VIO_DRING_MODE;
+	pkt.vdisk_block_size = port->vdisk_block_size;
+	pkt.max_xfer_size = port->max_xfer_size;
+
+	viodbg(HS, "SEND ATTR xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+	       pkt.xfer_mode, pkt.vdisk_block_size, pkt.max_xfer_size);
+
+	return vio_ldc_send(&port->vio, &pkt, sizeof(pkt));
+}
+
+static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+	struct vdc_port *port = to_vdc_port(vio);
+	struct vio_disk_attr_info *pkt = arg;
+
+	viodbg(HS, "GOT ATTR stype[0x%x] ops[%lx] disk_size[%lu] disk_type[%x] "
+	       "xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+	       pkt->tag.stype, pkt->operations,
+	       pkt->vdisk_size, pkt->vdisk_type,
+	       pkt->xfer_mode, pkt->vdisk_block_size,
+	       pkt->max_xfer_size);
+
+	if (pkt->tag.stype == VIO_SUBTYPE_ACK) {
+		switch (pkt->vdisk_type) {
+		case VD_DISK_TYPE_DISK:
+		case VD_DISK_TYPE_SLICE:
+			break;
+
+		default:
+			printk(KERN_ERR PFX "%s: Bogus vdisk_type 0x%x\n",
+			       vio->name, pkt->vdisk_type);
+			return -ECONNRESET;
+		}
+
+		if (pkt->vdisk_block_size > port->vdisk_block_size) {
+			printk(KERN_ERR PFX "%s: BLOCK size increased "
+			       "%u --> %u\n",
+			       vio->name,
+			       port->vdisk_block_size, pkt->vdisk_block_size);
+			return -ECONNRESET;
+		}
+
+		port->operations = pkt->operations;
+		port->vdisk_size = pkt->vdisk_size;
+		port->vdisk_type = pkt->vdisk_type;
+		if (pkt->max_xfer_size < port->max_xfer_size)
+			port->max_xfer_size = pkt->max_xfer_size;
+		port->vdisk_block_size = pkt->vdisk_block_size;
+		return 0;
+	} else {
+		printk(KERN_ERR PFX "%s: Attribute NACK\n", vio->name);
+
+		return -ECONNRESET;
+	}
+}
+
+static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
+{
+	int err = desc->status;
+
+	vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
+}
+
+static void vdc_end_request(struct request *req, int uptodate, int num_sectors)
+{
+	if (end_that_request_first(req, uptodate, num_sectors))
+		return;
+	add_disk_randomness(req->rq_disk);
+	end_that_request_last(req, uptodate);
+}
+
+static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
+			unsigned int index)
+{
+	struct vio_disk_desc *desc = vio_dring_entry(dr, index);
+	struct vdc_req_entry *rqe = &port->rq_arr[index];
+	struct request *req;
+
+	if (unlikely(desc->hdr.state != VIO_DESC_DONE))
+		return;
+
+	ldc_unmap(port->vio.lp, desc->cookies, desc->ncookies);
+	desc->hdr.state = VIO_DESC_FREE;
+	dr->cons = (index + 1) & (VDC_TX_RING_SIZE - 1);
+
+	req = rqe->req;
+	if (req == NULL) {
+		vdc_end_special(port, desc);
+		return;
+	}
+
+	rqe->req = NULL;
+
+	vdc_end_request(req, !desc->status, desc->size >> 9);
+
+	if (blk_queue_stopped(port->disk->queue))
+		blk_start_queue(port->disk->queue);
+}
+
+static int vdc_ack(struct vdc_port *port, void *msgbuf)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data *pkt = msgbuf;
+
+	if (unlikely(pkt->dring_ident != dr->ident ||
+		     pkt->start_idx != pkt->end_idx ||
+		     pkt->start_idx >= VDC_TX_RING_SIZE))
+		return 0;
+
+	vdc_end_one(port, dr, pkt->start_idx);
+
+	return 0;
+}
+
+static int vdc_nack(struct vdc_port *port, void *msgbuf)
+{
+	/* XXX Implement me XXX */
+	return 0;
+}
+
+static void vdc_event(void *arg, int event)
+{
+	struct vdc_port *port = arg;
+	struct vio_driver_state *vio = &port->vio;
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&vio->lock, flags);
+
+	if (unlikely(event == LDC_EVENT_RESET ||
+		     event == LDC_EVENT_UP)) {
+		vio_link_state_change(vio, event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+		return;
+	}
+
+	if (unlikely(event != LDC_EVENT_DATA_READY)) {
+		printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+		return;
+	}
+
+	err = 0;
+	while (1) {
+		union {
+			struct vio_msg_tag tag;
+			u64 raw[8];
+		} msgbuf;
+
+		err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				vio_conn_reset(vio);
+			break;
+		}
+		if (err == 0)
+			break;
+		viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+		       msgbuf.tag.type,
+		       msgbuf.tag.stype,
+		       msgbuf.tag.stype_env,
+		       msgbuf.tag.sid);
+		err = vio_validate_sid(vio, &msgbuf.tag);
+		if (err < 0)
+			break;
+
+		if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+			if (msgbuf.tag.stype == VIO_SUBTYPE_ACK)
+				err = vdc_ack(port, &msgbuf);
+			else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK)
+				err = vdc_nack(port, &msgbuf);
+			else
+				err = vdc_handle_unknown(port, &msgbuf);
+		} else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+			err = vio_control_pkt_engine(vio, &msgbuf);
+		} else {
+			err = vdc_handle_unknown(port, &msgbuf);
+		}
+		if (err < 0)
+			break;
+	}
+	if (err < 0)
+		vdc_finish(&port->vio, err, WAITING_FOR_ANY);
+	spin_unlock_irqrestore(&vio->lock, flags);
+}
+
+static int __vdc_tx_trigger(struct vdc_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data hdr = {
+		.tag = {
+			.type		= VIO_TYPE_DATA,
+			.stype		= VIO_SUBTYPE_INFO,
+			.stype_env	= VIO_DRING_DATA,
+			.sid		= vio_send_sid(&port->vio),
+		},
+		.dring_ident		= dr->ident,
+		.start_idx		= dr->prod,
+		.end_idx		= dr->prod,
+	};
+	int err, delay;
+
+	hdr.seq = dr->snd_nxt;
+	delay = 1;
+	do {
+		err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+		if (err > 0) {
+			dr->snd_nxt++;
+			break;
+		}
+		udelay(delay);
+		if ((delay <<= 1) > 128)
+			delay = 128;
+	} while (err == -EAGAIN);
+
+	return err;
+}
+
+static int __send_request(struct request *req)
+{
+	struct vdc_port *port = req->rq_disk->private_data;
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct scatterlist sg[port->ring_cookies];
+	struct vdc_req_entry *rqe;
+	struct vio_disk_desc *desc;
+	unsigned int map_perm;
+	int nsg, err, i;
+	u64 len;
+	u8 op;
+
+	map_perm = LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+	if (rq_data_dir(req) == READ) {
+		map_perm |= LDC_MAP_W;
+		op = VD_OP_BREAD;
+	} else {
+		map_perm |= LDC_MAP_R;
+		op = VD_OP_BWRITE;
+	}
+
+	nsg = blk_rq_map_sg(req->q, req, sg);
+
+	len = 0;
+	for (i = 0; i < nsg; i++)
+		len += sg[i].length;
+
+	if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
+		blk_stop_queue(port->disk->queue);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	desc = vio_dring_cur(dr);
+
+	err = ldc_map_sg(port->vio.lp, sg, nsg,
+			 desc->cookies, port->ring_cookies,
+			 map_perm);
+	if (err < 0) {
+		printk(KERN_ERR PFX "ldc_map_sg() failure, err=%d.\n", err);
+		return err;
+	}
+
+	rqe = &port->rq_arr[dr->prod];
+	rqe->req = req;
+
+	desc->hdr.ack = VIO_ACK_ENABLE;
+	desc->req_id = port->req_id;
+	desc->operation = op;
+	if (port->vdisk_type == VD_DISK_TYPE_DISK) {
+		desc->slice = 2;
+	} else {
+		desc->slice = 0;
+	}
+	desc->status = ~0;
+	desc->offset = (req->sector << 9) / port->vdisk_block_size;
+	desc->size = len;
+	desc->ncookies = err;
+
+	/* This has to be a non-SMP write barrier because we are writing
+	 * to memory which is shared with the peer LDOM.
+	 */
+	wmb();
+	desc->hdr.state = VIO_DESC_READY;
+
+	err = __vdc_tx_trigger(port);
+	if (err < 0) {
+		printk(KERN_ERR PFX "vdc_tx_trigger() failure, err=%d\n", err);
+	} else {
+		port->req_id++;
+		dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+	}
+out:
+
+	return err;
+}
+
+static void do_vdc_request(request_queue_t *q)
+{
+	while (1) {
+		struct request *req = elv_next_request(q);
+
+		if (!req)
+			break;
+
+		blkdev_dequeue_request(req);
+		if (__send_request(req) < 0)
+			vdc_end_request(req, 0, req->hard_nr_sectors);
+	}
+}
+
+static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
+{
+	struct vio_dring_state *dr;
+	struct vio_completion comp;
+	struct vio_disk_desc *desc;
+	unsigned int map_perm;
+	unsigned long flags;
+	int op_len, err;
+	void *req_buf;
+
+	if (!(((u64)1 << ((u64)op - 1)) & port->operations))
+		return -EOPNOTSUPP;
+
+	switch (op) {
+	case VD_OP_BREAD:
+	case VD_OP_BWRITE:
+	default:
+		return -EINVAL;
+
+	case VD_OP_FLUSH:
+		op_len = 0;
+		map_perm = 0;
+		break;
+
+	case VD_OP_GET_WCE:
+		op_len = sizeof(u32);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_SET_WCE:
+		op_len = sizeof(u32);
+		map_perm = LDC_MAP_R;
+		break;
+
+	case VD_OP_GET_VTOC:
+		op_len = sizeof(struct vio_disk_vtoc);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_SET_VTOC:
+		op_len = sizeof(struct vio_disk_vtoc);
+		map_perm = LDC_MAP_R;
+		break;
+
+	case VD_OP_GET_DISKGEOM:
+		op_len = sizeof(struct vio_disk_geom);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_SET_DISKGEOM:
+		op_len = sizeof(struct vio_disk_geom);
+		map_perm = LDC_MAP_R;
+		break;
+
+	case VD_OP_SCSICMD:
+		op_len = 16;
+		map_perm = LDC_MAP_RW;
+		break;
+
+	case VD_OP_GET_DEVID:
+		op_len = sizeof(struct vio_disk_devid);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_GET_EFI:
+	case VD_OP_SET_EFI:
+		return -EOPNOTSUPP;
+		break;
+	};
+
+	map_perm |= LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+	op_len = (op_len + 7) & ~7;
+	req_buf = kzalloc(op_len, GFP_KERNEL);
+	if (!req_buf)
+		return -ENOMEM;
+
+	if (len > op_len)
+		len = op_len;
+
+	if (map_perm & LDC_MAP_R)
+		memcpy(req_buf, buf, len);
+
+	spin_lock_irqsave(&port->vio.lock, flags);
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+	/* XXX If we want to use this code generically we have to
+	 * XXX handle TX ring exhaustion etc.
+	 */
+	desc = vio_dring_cur(dr);
+
+	err = ldc_map_single(port->vio.lp, req_buf, op_len,
+			     desc->cookies, port->ring_cookies,
+			     map_perm);
+	if (err < 0) {
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		kfree(req_buf);
+		return err;
+	}
+
+	init_completion(&comp.com);
+	comp.waiting_for = WAITING_FOR_GEN_CMD;
+	port->vio.cmp = &comp;
+
+	desc->hdr.ack = VIO_ACK_ENABLE;
+	desc->req_id = port->req_id;
+	desc->operation = op;
+	desc->slice = 0;
+	desc->status = ~0;
+	desc->offset = 0;
+	desc->size = op_len;
+	desc->ncookies = err;
+
+	/* This has to be a non-SMP write barrier because we are writing
+	 * to memory which is shared with the peer LDOM.
+	 */
+	wmb();
+	desc->hdr.state = VIO_DESC_READY;
+
+	err = __vdc_tx_trigger(port);
+	if (err >= 0) {
+		port->req_id++;
+		dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+
+		wait_for_completion(&comp.com);
+		err = comp.err;
+	} else {
+		port->vio.cmp = NULL;
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+	}
+
+	if (map_perm & LDC_MAP_W)
+		memcpy(buf, req_buf, len);
+
+	kfree(req_buf);
+
+	return err;
+}
+
+static int __devinit vdc_alloc_tx_ring(struct vdc_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	unsigned long len, entry_size;
+	int ncookies;
+	void *dring;
+
+	entry_size = sizeof(struct vio_disk_desc) +
+		(sizeof(struct ldc_trans_cookie) * port->ring_cookies);
+	len = (VDC_TX_RING_SIZE * entry_size);
+
+	ncookies = VIO_MAX_RING_COOKIES;
+	dring = ldc_alloc_exp_dring(port->vio.lp, len,
+				    dr->cookies, &ncookies,
+				    (LDC_MAP_SHADOW |
+				     LDC_MAP_DIRECT |
+				     LDC_MAP_RW));
+	if (IS_ERR(dring))
+		return PTR_ERR(dring);
+
+	dr->base = dring;
+	dr->entry_size = entry_size;
+	dr->num_entries = VDC_TX_RING_SIZE;
+	dr->prod = dr->cons = 0;
+	dr->pending = VDC_TX_RING_SIZE;
+	dr->ncookies = ncookies;
+
+	return 0;
+}
+
+static void vdc_free_tx_ring(struct vdc_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+	if (dr->base) {
+		ldc_free_exp_dring(port->vio.lp, dr->base,
+				   (dr->entry_size * dr->num_entries),
+				   dr->cookies, dr->ncookies);
+		dr->base = NULL;
+		dr->entry_size = 0;
+		dr->num_entries = 0;
+		dr->pending = 0;
+		dr->ncookies = 0;
+	}
+}
+
+static int probe_disk(struct vdc_port *port)
+{
+	struct vio_completion comp;
+	struct request_queue *q;
+	struct gendisk *g;
+	int err;
+
+	init_completion(&comp.com);
+	comp.err = 0;
+	comp.waiting_for = WAITING_FOR_LINK_UP;
+	port->vio.cmp = &comp;
+
+	vio_port_up(&port->vio);
+
+	wait_for_completion(&comp.com);
+	if (comp.err)
+		return comp.err;
+
+	err = generic_request(port, VD_OP_GET_VTOC,
+			      &port->label, sizeof(port->label));
+	if (err < 0) {
+		printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err);
+		return err;
+	}
+
+	err = generic_request(port, VD_OP_GET_DISKGEOM,
+			      &port->geom, sizeof(port->geom));
+	if (err < 0) {
+		printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
+		       "error %d\n", err);
+		return err;
+	}
+
+	port->vdisk_size = ((u64)port->geom.num_cyl *
+			    (u64)port->geom.num_hd *
+			    (u64)port->geom.num_sec);
+
+	q = blk_init_queue(do_vdc_request, &port->vio.lock);
+	if (!q) {
+		printk(KERN_ERR PFX "%s: Could not allocate queue.\n",
+		       port->vio.name);
+		return -ENOMEM;
+	}
+	g = alloc_disk(1 << PARTITION_SHIFT);
+	if (!g) {
+		printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
+		       port->vio.name);
+		blk_cleanup_queue(q);
+		return -ENOMEM;
+	}
+
+	port->disk = g;
+
+	blk_queue_max_hw_segments(q, port->ring_cookies);
+	blk_queue_max_phys_segments(q, port->ring_cookies);
+	blk_queue_max_sectors(q, port->max_xfer_size);
+	g->major = vdc_major;
+	g->first_minor = port->dev_no << PARTITION_SHIFT;
+	strcpy(g->disk_name, port->disk_name);
+
+	g->fops = &vdc_fops;
+	g->queue = q;
+	g->private_data = port;
+	g->driverfs_dev = &port->vio.vdev->dev;
+
+	set_capacity(g, port->vdisk_size);
+
+	printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n",
+	       g->disk_name,
+	       port->vdisk_size, (port->vdisk_size >> (20 - 9)));
+
+	add_disk(g);
+
+	return 0;
+}
+
+static struct ldc_channel_config vdc_ldc_cfg = {
+	.event		= vdc_event,
+	.mtu		= 64,
+	.mode		= LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vdc_vio_ops = {
+	.send_attr		= vdc_send_attr,
+	.handle_attr		= vdc_handle_attr,
+	.handshake_complete	= vdc_handshake_complete,
+};
+
+static int __devinit vdc_port_probe(struct vio_dev *vdev,
+				    const struct vio_device_id *id)
+{
+	struct mdesc_handle *hp;
+	struct vdc_port *port;
+	unsigned long flags;
+	struct vdc *vp;
+	const u64 *port_id;
+	int err;
+
+	vp = dev_get_drvdata(vdev->dev.parent);
+	if (!vp) {
+		printk(KERN_ERR PFX "Cannot find port parent vdc.\n");
+		return -ENODEV;
+	}
+
+	hp = mdesc_grab();
+
+	port_id = mdesc_get_property(hp, vdev->mp, "id", NULL);
+	err = -ENODEV;
+	if (!port_id) {
+		printk(KERN_ERR PFX "Port lacks id property.\n");
+		goto err_out_release_mdesc;
+	}
+	if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) {
+		printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id);
+		goto err_out_release_mdesc;
+	}
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!port) {
+		printk(KERN_ERR PFX "Cannot allocate vdc_port.\n");
+		goto err_out_release_mdesc;
+	}
+
+	port->vp = vp;
+	port->dev_no = *port_id;
+
+	if (port->dev_no >= 26)
+		snprintf(port->disk_name, sizeof(port->disk_name),
+			 VDCBLK_NAME "%c%c",
+			 'a' + (port->dev_no / 26) - 1,
+			 'a' + (port->dev_no % 26));
+	else
+		snprintf(port->disk_name, sizeof(port->disk_name),
+			 VDCBLK_NAME "%c", 'a' + (port->dev_no % 26));
+
+	err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
+			      vdc_versions, ARRAY_SIZE(vdc_versions),
+			      &vdc_vio_ops, port->disk_name);
+	if (err)
+		goto err_out_free_port;
+
+	port->vdisk_block_size = 512;
+	port->max_xfer_size = ((128 * 1024) / port->vdisk_block_size);
+	port->ring_cookies = ((port->max_xfer_size *
+			       port->vdisk_block_size) / PAGE_SIZE) + 2;
+
+	err = vio_ldc_alloc(&port->vio, &vdc_ldc_cfg, port);
+	if (err)
+		goto err_out_free_port;
+
+	err = vdc_alloc_tx_ring(port);
+	if (err)
+		goto err_out_free_ldc;
+
+	err = probe_disk(port);
+	if (err)
+		goto err_out_free_tx_ring;
+
+	INIT_LIST_HEAD(&port->list);
+
+	spin_lock_irqsave(&vp->lock, flags);
+	list_add(&port->list, &vp->port_list);
+	spin_unlock_irqrestore(&vp->lock, flags);
+
+	dev_set_drvdata(&vdev->dev, port);
+
+	mdesc_release(hp);
+
+	return 0;
+
+err_out_free_tx_ring:
+	vdc_free_tx_ring(port);
+
+err_out_free_ldc:
+	vio_ldc_free(&port->vio);
+
+err_out_free_port:
+	kfree(port);
+
+err_out_release_mdesc:
+	mdesc_release(hp);
+	return err;
+}
+
+static int vdc_port_remove(struct vio_dev *vdev)
+{
+	struct vdc_port *port = dev_get_drvdata(&vdev->dev);
+
+	if (port) {
+		del_timer_sync(&port->vio.timer);
+
+		vdc_free_tx_ring(port);
+		vio_ldc_free(&port->vio);
+
+		dev_set_drvdata(&vdev->dev, NULL);
+
+		kfree(port);
+	}
+	return 0;
+}
+
+static struct vio_device_id vdc_port_match[] = {
+	{
+		.type = "vdc-port",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_port_driver = {
+	.id_table	= vdc_port_match,
+	.probe		= vdc_port_probe,
+	.remove		= vdc_port_remove,
+	.driver		= {
+		.name	= "vdc_port",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __devinit vdc_probe(struct vio_dev *vdev,
+			       const struct vio_device_id *id)
+{
+	static int vdc_version_printed;
+	struct vdc *vp;
+
+	if (vdc_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	vp = kzalloc(sizeof(struct vdc), GFP_KERNEL);
+	if (!vp)
+		return -ENOMEM;
+
+	spin_lock_init(&vp->lock);
+	vp->dev = vdev;
+	INIT_LIST_HEAD(&vp->port_list);
+
+	dev_set_drvdata(&vdev->dev, vp);
+
+	return 0;
+}
+
+static int vdc_remove(struct vio_dev *vdev)
+{
+
+	struct vdc *vp = dev_get_drvdata(&vdev->dev);
+
+	if (vp) {
+		kfree(vp);
+		dev_set_drvdata(&vdev->dev, NULL);
+	}
+	return 0;
+}
+
+static struct vio_device_id vdc_match[] = {
+	{
+		.type = "block",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_driver = {
+	.id_table	= vdc_match,
+	.probe		= vdc_probe,
+	.remove		= vdc_remove,
+	.driver		= {
+		.name	= "vdc",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init vdc_init(void)
+{
+	int err;
+
+	err = register_blkdev(0, VDCBLK_NAME);
+	if (err < 0)
+		goto out_err;
+
+	vdc_major = err;
+	err = vio_register_driver(&vdc_driver);
+	if (err)
+		goto out_unregister_blkdev;
+
+	err = vio_register_driver(&vdc_port_driver);
+	if (err)
+		goto out_unregister_vdc;
+
+	return 0;
+
+out_unregister_vdc:
+	vio_unregister_driver(&vdc_driver);
+
+out_unregister_blkdev:
+	unregister_blkdev(vdc_major, VDCBLK_NAME);
+	vdc_major = 0;
+
+out_err:
+	return err;
+}
+
+static void __exit vdc_exit(void)
+{
+	vio_unregister_driver(&vdc_port_driver);
+	vio_unregister_driver(&vdc_driver);
+	unregister_blkdev(vdc_major, VDCBLK_NAME);
+}
+
+module_init(vdc_init);
+module_exit(vdc_exit);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 18c8b6c..8b13d7d 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1709,7 +1709,7 @@
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	void __user *usermem = (void __user *) arg;
 
-	return scsi_cmd_ioctl(filp, disk, cmd, usermem);
+	return scsi_cmd_ioctl(filp, disk->queue, disk, cmd, usermem);
 }
 
 /*
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 6f5d620..dec74bd 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -105,12 +105,6 @@
 	unsigned long	csr_base;
 	unsigned char	__iomem *csr_remap;
 	unsigned long	csr_len;
-#ifdef CONFIG_MM_MAP_MEMORY
-	unsigned long	mem_base;
-	unsigned char	__iomem *mem_remap;
-	unsigned long	mem_len;
-#endif
-
 	unsigned int	win_size; /* PCI window size */
 	unsigned int	mm_size;  /* size in kbytes */
 
@@ -872,10 +866,6 @@
 
 	card->csr_base = pci_resource_start(dev, 0);
 	card->csr_len  = pci_resource_len(dev, 0);
-#ifdef CONFIG_MM_MAP_MEMORY
-	card->mem_base = pci_resource_start(dev, 1);
-	card->mem_len  = pci_resource_len(dev, 1);
-#endif
 
 	printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n",
 	       card->card_number, dev->bus->number, dev->devfn);
@@ -903,27 +893,6 @@
 	printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number,
 	       card->csr_base, card->csr_remap, card->csr_len);
 
-#ifdef CONFIG_MM_MAP_MEMORY
-	if (!request_mem_region(card->mem_base, card->mem_len, "Micro Memory")) {
-		printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number);
-		ret = -ENOMEM;
-
-		goto failed_req_mem;
-	}
-
-	if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) {
-		printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number);
-		ret = -ENOMEM;
-
-		goto failed_remap_mem;
-	}
-
-	printk(KERN_INFO "MM%d: MEM 0x%8lx -> 0x%8lx (0x%lx)\n", card->card_number,
-	       card->mem_base, card->mem_remap, card->mem_len);
-#else
-	printk(KERN_INFO "MM%d: MEM area not remapped (CONFIG_MM_MAP_MEMORY not set)\n",
-	       card->card_number);
-#endif
 	switch(card->dev->device) {
 	case 0x5415:
 		card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG;
@@ -1091,12 +1060,6 @@
 				    card->mm_pages[1].desc,
 				    card->mm_pages[1].page_dma);
  failed_magic:
-#ifdef CONFIG_MM_MAP_MEMORY
-	iounmap(card->mem_remap);
- failed_remap_mem:
-	release_mem_region(card->mem_base, card->mem_len);
- failed_req_mem:
-#endif
 	iounmap(card->csr_remap);
  failed_remap_csr:
 	release_mem_region(card->csr_base, card->csr_len);
@@ -1116,10 +1079,6 @@
 	tasklet_kill(&card->tasklet);
 	iounmap(card->csr_remap);
 	release_mem_region(card->csr_base, card->csr_len);
-#ifdef CONFIG_MM_MAP_MEMORY
-	iounmap(card->mem_remap);
-	release_mem_region(card->mem_base, card->mem_len);
-#endif
 	free_irq(card->irq, card);
 
 	if (card->mm_pages[0].desc)
@@ -1133,23 +1092,18 @@
 	blk_cleanup_queue(card->queue);
 }
 
-static const struct pci_device_id mm_pci_ids[] = { {
-	.vendor =	PCI_VENDOR_ID_MICRO_MEMORY,
-	.device =	PCI_DEVICE_ID_MICRO_MEMORY_5415CN,
-	}, {
-	.vendor =	PCI_VENDOR_ID_MICRO_MEMORY,
-	.device =	PCI_DEVICE_ID_MICRO_MEMORY_5425CN,
-	}, {
-	.vendor =	PCI_VENDOR_ID_MICRO_MEMORY,
-	.device =	PCI_DEVICE_ID_MICRO_MEMORY_6155,
-	}, {
+static const struct pci_device_id mm_pci_ids[] = {
+    {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5415CN)},
+    {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5425CN)},
+    {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_6155)},
+    {
 	.vendor	=	0x8086,
 	.device	=	0xB555,
 	.subvendor=	0x1332,
 	.subdevice=	0x5460,
 	.class	=	0x050000,
 	.class_mask=	0,
-	}, { /* end: all zeroes */ }
+    }, { /* end: all zeroes */ }
 };
 
 MODULE_DEVICE_TABLE(pci, mm_pci_ids);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 68592c3..dae3991 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -252,10 +252,10 @@
 	struct gendisk *disk = bdev->bd_disk;
 	struct viodasd_device *d = disk->private_data;
 
-	geo->sectors = d->sectors ? d->sectors : 0;
+	geo->sectors = d->sectors ? d->sectors : 32;
 	geo->heads = d->tracks ? d->tracks  : 64;
 	geo->cylinders = d->cylinders ? d->cylinders :
-		get_capacity(disk) / (geo->cylinders * geo->heads);
+		get_capacity(disk) / (geo->sectors * geo->heads);
 
 	return 0;
 }
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
new file mode 100644
index 0000000..732ec63
--- /dev/null
+++ b/drivers/block/xsysace.c
@@ -0,0 +1,1164 @@
+/*
+ * Xilinx SystemACE device driver
+ *
+ * Copyright 2007 Secret Lab Technologies Ltd.
+ *
+ * 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 SystemACE chip is designed to configure FPGAs by loading an FPGA
+ * bitstream from a file on a CF card and squirting it into FPGAs connected
+ * to the SystemACE JTAG chain.  It also has the advantage of providing an
+ * MPU interface which can be used to control the FPGA configuration process
+ * and to use the attached CF card for general purpose storage.
+ *
+ * This driver is a block device driver for the SystemACE.
+ *
+ * Initialization:
+ *    The driver registers itself as a platform_device driver at module
+ *    load time.  The platform bus will take care of calling the
+ *    ace_probe() method for all SystemACE instances in the system.  Any
+ *    number of SystemACE instances are supported.  ace_probe() calls
+ *    ace_setup() which initialized all data structures, reads the CF
+ *    id structure and registers the device.
+ *
+ * Processing:
+ *    Just about all of the heavy lifting in this driver is performed by
+ *    a Finite State Machine (FSM).  The driver needs to wait on a number
+ *    of events; some raised by interrupts, some which need to be polled
+ *    for.  Describing all of the behaviour in a FSM seems to be the
+ *    easiest way to keep the complexity low and make it easy to
+ *    understand what the driver is doing.  If the block ops or the
+ *    request function need to interact with the hardware, then they
+ *    simply need to flag the request and kick of FSM processing.
+ *
+ *    The FSM itself is atomic-safe code which can be run from any
+ *    context.  The general process flow is:
+ *    1. obtain the ace->lock spinlock.
+ *    2. loop on ace_fsm_dostate() until the ace->fsm_continue flag is
+ *       cleared.
+ *    3. release the lock.
+ *
+ *    Individual states do not sleep in any way.  If a condition needs to
+ *    be waited for then the state much clear the fsm_continue flag and
+ *    either schedule the FSM to be run again at a later time, or expect
+ *    an interrupt to call the FSM when the desired condition is met.
+ *
+ *    In normal operation, the FSM is processed at interrupt context
+ *    either when the driver's tasklet is scheduled, or when an irq is
+ *    raised by the hardware.  The tasklet can be scheduled at any time.
+ *    The request method in particular schedules the tasklet when a new
+ *    request has been indicated by the block layer.  Once started, the
+ *    FSM proceeds as far as it can processing the request until it
+ *    needs on a hardware event.  At this point, it must yield execution.
+ *
+ *    A state has two options when yielding execution:
+ *    1. ace_fsm_yield()
+ *       - Call if need to poll for event.
+ *       - clears the fsm_continue flag to exit the processing loop
+ *       - reschedules the tasklet to run again as soon as possible
+ *    2. ace_fsm_yieldirq()
+ *       - Call if an irq is expected from the HW
+ *       - clears the fsm_continue flag to exit the processing loop
+ *       - does not reschedule the tasklet so the FSM will not be processed
+ *         again until an irq is received.
+ *    After calling a yield function, the state must return control back
+ *    to the FSM main loop.
+ *
+ *    Additionally, the driver maintains a kernel timer which can process
+ *    the FSM.  If the FSM gets stalled, typically due to a missed
+ *    interrupt, then the kernel timer will expire and the driver can
+ *    continue where it left off.
+ *
+ * To Do:
+ *    - Add FPGA configuration control interface.
+ *    - Request major number from lanana
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/platform_device.h>
+
+MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
+MODULE_DESCRIPTION("Xilinx SystemACE device driver");
+MODULE_LICENSE("GPL");
+
+/* SystemACE register definitions */
+#define ACE_BUSMODE (0x00)
+
+#define ACE_STATUS (0x04)
+#define ACE_STATUS_CFGLOCK      (0x00000001)
+#define ACE_STATUS_MPULOCK      (0x00000002)
+#define ACE_STATUS_CFGERROR     (0x00000004)	/* config controller error */
+#define ACE_STATUS_CFCERROR     (0x00000008)	/* CF controller error */
+#define ACE_STATUS_CFDETECT     (0x00000010)
+#define ACE_STATUS_DATABUFRDY   (0x00000020)
+#define ACE_STATUS_DATABUFMODE  (0x00000040)
+#define ACE_STATUS_CFGDONE      (0x00000080)
+#define ACE_STATUS_RDYFORCFCMD  (0x00000100)
+#define ACE_STATUS_CFGMODEPIN   (0x00000200)
+#define ACE_STATUS_CFGADDR_MASK (0x0000e000)
+#define ACE_STATUS_CFBSY        (0x00020000)
+#define ACE_STATUS_CFRDY        (0x00040000)
+#define ACE_STATUS_CFDWF        (0x00080000)
+#define ACE_STATUS_CFDSC        (0x00100000)
+#define ACE_STATUS_CFDRQ        (0x00200000)
+#define ACE_STATUS_CFCORR       (0x00400000)
+#define ACE_STATUS_CFERR        (0x00800000)
+
+#define ACE_ERROR (0x08)
+#define ACE_CFGLBA (0x0c)
+#define ACE_MPULBA (0x10)
+
+#define ACE_SECCNTCMD (0x14)
+#define ACE_SECCNTCMD_RESET      (0x0100)
+#define ACE_SECCNTCMD_IDENTIFY   (0x0200)
+#define ACE_SECCNTCMD_READ_DATA  (0x0300)
+#define ACE_SECCNTCMD_WRITE_DATA (0x0400)
+#define ACE_SECCNTCMD_ABORT      (0x0600)
+
+#define ACE_VERSION (0x16)
+#define ACE_VERSION_REVISION_MASK (0x00FF)
+#define ACE_VERSION_MINOR_MASK    (0x0F00)
+#define ACE_VERSION_MAJOR_MASK    (0xF000)
+
+#define ACE_CTRL (0x18)
+#define ACE_CTRL_FORCELOCKREQ   (0x0001)
+#define ACE_CTRL_LOCKREQ        (0x0002)
+#define ACE_CTRL_FORCECFGADDR   (0x0004)
+#define ACE_CTRL_FORCECFGMODE   (0x0008)
+#define ACE_CTRL_CFGMODE        (0x0010)
+#define ACE_CTRL_CFGSTART       (0x0020)
+#define ACE_CTRL_CFGSEL         (0x0040)
+#define ACE_CTRL_CFGRESET       (0x0080)
+#define ACE_CTRL_DATABUFRDYIRQ  (0x0100)
+#define ACE_CTRL_ERRORIRQ       (0x0200)
+#define ACE_CTRL_CFGDONEIRQ     (0x0400)
+#define ACE_CTRL_RESETIRQ       (0x0800)
+#define ACE_CTRL_CFGPROG        (0x1000)
+#define ACE_CTRL_CFGADDR_MASK   (0xe000)
+
+#define ACE_FATSTAT (0x1c)
+
+#define ACE_NUM_MINORS 16
+#define ACE_SECTOR_SIZE (512)
+#define ACE_FIFO_SIZE (32)
+#define ACE_BUF_PER_SECTOR (ACE_SECTOR_SIZE / ACE_FIFO_SIZE)
+
+struct ace_reg_ops;
+
+struct ace_device {
+	/* driver state data */
+	int id;
+	int media_change;
+	int users;
+	struct list_head list;
+
+	/* finite state machine data */
+	struct tasklet_struct fsm_tasklet;
+	uint fsm_task;		/* Current activity (ACE_TASK_*) */
+	uint fsm_state;		/* Current state (ACE_FSM_STATE_*) */
+	uint fsm_continue_flag;	/* cleared to exit FSM mainloop */
+	uint fsm_iter_num;
+	struct timer_list stall_timer;
+
+	/* Transfer state/result, use for both id and block request */
+	struct request *req;	/* request being processed */
+	void *data_ptr;		/* pointer to I/O buffer */
+	int data_count;		/* number of buffers remaining */
+	int data_result;	/* Result of transfer; 0 := success */
+
+	int id_req_count;	/* count of id requests */
+	int id_result;
+	struct completion id_completion;	/* used when id req finishes */
+	int in_irq;
+
+	/* Details of hardware device */
+	unsigned long physaddr;
+	void *baseaddr;
+	int irq;
+	int bus_width;		/* 0 := 8 bit; 1 := 16 bit */
+	struct ace_reg_ops *reg_ops;
+	int lock_count;
+
+	/* Block device data structures */
+	spinlock_t lock;
+	struct device *dev;
+	struct request_queue *queue;
+	struct gendisk *gd;
+
+	/* Inserted CF card parameters */
+	struct hd_driveid cf_id;
+};
+
+static int ace_major;
+
+/* ---------------------------------------------------------------------
+ * Low level register access
+ */
+
+struct ace_reg_ops {
+	u16(*in) (struct ace_device * ace, int reg);
+	void (*out) (struct ace_device * ace, int reg, u16 val);
+	void (*datain) (struct ace_device * ace);
+	void (*dataout) (struct ace_device * ace);
+};
+
+/* 8 Bit bus width */
+static u16 ace_in_8(struct ace_device *ace, int reg)
+{
+	void *r = ace->baseaddr + reg;
+	return in_8(r) | (in_8(r + 1) << 8);
+}
+
+static void ace_out_8(struct ace_device *ace, int reg, u16 val)
+{
+	void *r = ace->baseaddr + reg;
+	out_8(r, val);
+	out_8(r + 1, val >> 8);
+}
+
+static void ace_datain_8(struct ace_device *ace)
+{
+	void *r = ace->baseaddr + 0x40;
+	u8 *dst = ace->data_ptr;
+	int i = ACE_FIFO_SIZE;
+	while (i--)
+		*dst++ = in_8(r++);
+	ace->data_ptr = dst;
+}
+
+static void ace_dataout_8(struct ace_device *ace)
+{
+	void *r = ace->baseaddr + 0x40;
+	u8 *src = ace->data_ptr;
+	int i = ACE_FIFO_SIZE;
+	while (i--)
+		out_8(r++, *src++);
+	ace->data_ptr = src;
+}
+
+static struct ace_reg_ops ace_reg_8_ops = {
+	.in = ace_in_8,
+	.out = ace_out_8,
+	.datain = ace_datain_8,
+	.dataout = ace_dataout_8,
+};
+
+/* 16 bit big endian bus attachment */
+static u16 ace_in_be16(struct ace_device *ace, int reg)
+{
+	return in_be16(ace->baseaddr + reg);
+}
+
+static void ace_out_be16(struct ace_device *ace, int reg, u16 val)
+{
+	out_be16(ace->baseaddr + reg, val);
+}
+
+static void ace_datain_be16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *dst = ace->data_ptr;
+	while (i--)
+		*dst++ = in_le16(ace->baseaddr + 0x40);
+	ace->data_ptr = dst;
+}
+
+static void ace_dataout_be16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *src = ace->data_ptr;
+	while (i--)
+		out_le16(ace->baseaddr + 0x40, *src++);
+	ace->data_ptr = src;
+}
+
+/* 16 bit little endian bus attachment */
+static u16 ace_in_le16(struct ace_device *ace, int reg)
+{
+	return in_le16(ace->baseaddr + reg);
+}
+
+static void ace_out_le16(struct ace_device *ace, int reg, u16 val)
+{
+	out_le16(ace->baseaddr + reg, val);
+}
+
+static void ace_datain_le16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *dst = ace->data_ptr;
+	while (i--)
+		*dst++ = in_be16(ace->baseaddr + 0x40);
+	ace->data_ptr = dst;
+}
+
+static void ace_dataout_le16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *src = ace->data_ptr;
+	while (i--)
+		out_be16(ace->baseaddr + 0x40, *src++);
+	ace->data_ptr = src;
+}
+
+static struct ace_reg_ops ace_reg_be16_ops = {
+	.in = ace_in_be16,
+	.out = ace_out_be16,
+	.datain = ace_datain_be16,
+	.dataout = ace_dataout_be16,
+};
+
+static struct ace_reg_ops ace_reg_le16_ops = {
+	.in = ace_in_le16,
+	.out = ace_out_le16,
+	.datain = ace_datain_le16,
+	.dataout = ace_dataout_le16,
+};
+
+static inline u16 ace_in(struct ace_device *ace, int reg)
+{
+	return ace->reg_ops->in(ace, reg);
+}
+
+static inline u32 ace_in32(struct ace_device *ace, int reg)
+{
+	return ace_in(ace, reg) | (ace_in(ace, reg + 2) << 16);
+}
+
+static inline void ace_out(struct ace_device *ace, int reg, u16 val)
+{
+	ace->reg_ops->out(ace, reg, val);
+}
+
+static inline void ace_out32(struct ace_device *ace, int reg, u32 val)
+{
+	ace_out(ace, reg, val);
+	ace_out(ace, reg + 2, val >> 16);
+}
+
+/* ---------------------------------------------------------------------
+ * Debug support functions
+ */
+
+#if defined(DEBUG)
+static void ace_dump_mem(void *base, int len)
+{
+	const char *ptr = base;
+	int i, j;
+
+	for (i = 0; i < len; i += 16) {
+		printk(KERN_INFO "%.8x:", i);
+		for (j = 0; j < 16; j++) {
+			if (!(j % 4))
+				printk(" ");
+			printk("%.2x", ptr[i + j]);
+		}
+		printk(" ");
+		for (j = 0; j < 16; j++)
+			printk("%c", isprint(ptr[i + j]) ? ptr[i + j] : '.');
+		printk("\n");
+	}
+}
+#else
+static inline void ace_dump_mem(void *base, int len)
+{
+}
+#endif
+
+static void ace_dump_regs(struct ace_device *ace)
+{
+	dev_info(ace->dev, "    ctrl:  %.8x  seccnt/cmd: %.4x      ver:%.4x\n"
+		 "    status:%.8x  mpu_lba:%.8x  busmode:%4x\n"
+		 "    error: %.8x  cfg_lba:%.8x  fatstat:%.4x\n",
+		 ace_in32(ace, ACE_CTRL),
+		 ace_in(ace, ACE_SECCNTCMD),
+		 ace_in(ace, ACE_VERSION),
+		 ace_in32(ace, ACE_STATUS),
+		 ace_in32(ace, ACE_MPULBA),
+		 ace_in(ace, ACE_BUSMODE),
+		 ace_in32(ace, ACE_ERROR),
+		 ace_in32(ace, ACE_CFGLBA), ace_in(ace, ACE_FATSTAT));
+}
+
+void ace_fix_driveid(struct hd_driveid *id)
+{
+#if defined(__BIG_ENDIAN)
+	u16 *buf = (void *)id;
+	int i;
+
+	/* All half words have wrong byte order; swap the bytes */
+	for (i = 0; i < sizeof(struct hd_driveid); i += 2, buf++)
+		*buf = le16_to_cpu(*buf);
+
+	/* Some of the data values are 32bit; swap the half words  */
+	id->lba_capacity = ((id->lba_capacity >> 16) & 0x0000FFFF) |
+	    ((id->lba_capacity << 16) & 0xFFFF0000);
+	id->spg = ((id->spg >> 16) & 0x0000FFFF) |
+	    ((id->spg << 16) & 0xFFFF0000);
+#endif
+}
+
+/* ---------------------------------------------------------------------
+ * Finite State Machine (FSM) implementation
+ */
+
+/* FSM tasks; used to direct state transitions */
+#define ACE_TASK_IDLE      0
+#define ACE_TASK_IDENTIFY  1
+#define ACE_TASK_READ      2
+#define ACE_TASK_WRITE     3
+#define ACE_FSM_NUM_TASKS  4
+
+/* FSM state definitions */
+#define ACE_FSM_STATE_IDLE               0
+#define ACE_FSM_STATE_REQ_LOCK           1
+#define ACE_FSM_STATE_WAIT_LOCK          2
+#define ACE_FSM_STATE_WAIT_CFREADY       3
+#define ACE_FSM_STATE_IDENTIFY_PREPARE   4
+#define ACE_FSM_STATE_IDENTIFY_TRANSFER  5
+#define ACE_FSM_STATE_IDENTIFY_COMPLETE  6
+#define ACE_FSM_STATE_REQ_PREPARE        7
+#define ACE_FSM_STATE_REQ_TRANSFER       8
+#define ACE_FSM_STATE_REQ_COMPLETE       9
+#define ACE_FSM_STATE_ERROR             10
+#define ACE_FSM_NUM_STATES              11
+
+/* Set flag to exit FSM loop and reschedule tasklet */
+static inline void ace_fsm_yield(struct ace_device *ace)
+{
+	dev_dbg(ace->dev, "ace_fsm_yield()\n");
+	tasklet_schedule(&ace->fsm_tasklet);
+	ace->fsm_continue_flag = 0;
+}
+
+/* Set flag to exit FSM loop and wait for IRQ to reschedule tasklet */
+static inline void ace_fsm_yieldirq(struct ace_device *ace)
+{
+	dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
+
+	if (ace->irq == NO_IRQ)
+		/* No IRQ assigned, so need to poll */
+		tasklet_schedule(&ace->fsm_tasklet);
+	ace->fsm_continue_flag = 0;
+}
+
+/* Get the next read/write request; ending requests that we don't handle */
+struct request *ace_get_next_request(request_queue_t * q)
+{
+	struct request *req;
+
+	while ((req = elv_next_request(q)) != NULL) {
+		if (blk_fs_request(req))
+			break;
+		end_request(req, 0);
+	}
+	return req;
+}
+
+static void ace_fsm_dostate(struct ace_device *ace)
+{
+	struct request *req;
+	u32 status;
+	u16 val;
+	int count;
+	int i;
+
+#if defined(DEBUG)
+	dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n",
+		ace->fsm_state, ace->id_req_count);
+#endif
+
+	switch (ace->fsm_state) {
+	case ACE_FSM_STATE_IDLE:
+		/* See if there is anything to do */
+		if (ace->id_req_count || ace_get_next_request(ace->queue)) {
+			ace->fsm_iter_num++;
+			ace->fsm_state = ACE_FSM_STATE_REQ_LOCK;
+			mod_timer(&ace->stall_timer, jiffies + HZ);
+			if (!timer_pending(&ace->stall_timer))
+				add_timer(&ace->stall_timer);
+			break;
+		}
+		del_timer(&ace->stall_timer);
+		ace->fsm_continue_flag = 0;
+		break;
+
+	case ACE_FSM_STATE_REQ_LOCK:
+		if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
+			/* Already have the lock, jump to next state */
+			ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
+			break;
+		}
+
+		/* Request the lock */
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val | ACE_CTRL_LOCKREQ);
+		ace->fsm_state = ACE_FSM_STATE_WAIT_LOCK;
+		break;
+
+	case ACE_FSM_STATE_WAIT_LOCK:
+		if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
+			/* got the lock; move to next state */
+			ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
+			break;
+		}
+
+		/* wait a bit for the lock */
+		ace_fsm_yield(ace);
+		break;
+
+	case ACE_FSM_STATE_WAIT_CFREADY:
+		status = ace_in32(ace, ACE_STATUS);
+		if (!(status & ACE_STATUS_RDYFORCFCMD) ||
+		    (status & ACE_STATUS_CFBSY)) {
+			/* CF card isn't ready; it needs to be polled */
+			ace_fsm_yield(ace);
+			break;
+		}
+
+		/* Device is ready for command; determine what to do next */
+		if (ace->id_req_count)
+			ace->fsm_state = ACE_FSM_STATE_IDENTIFY_PREPARE;
+		else
+			ace->fsm_state = ACE_FSM_STATE_REQ_PREPARE;
+		break;
+
+	case ACE_FSM_STATE_IDENTIFY_PREPARE:
+		/* Send identify command */
+		ace->fsm_task = ACE_TASK_IDENTIFY;
+		ace->data_ptr = &ace->cf_id;
+		ace->data_count = ACE_BUF_PER_SECTOR;
+		ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY);
+
+		/* As per datasheet, put config controller in reset */
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
+
+		/* irq handler takes over from this point; wait for the
+		 * transfer to complete */
+		ace->fsm_state = ACE_FSM_STATE_IDENTIFY_TRANSFER;
+		ace_fsm_yieldirq(ace);
+		break;
+
+	case ACE_FSM_STATE_IDENTIFY_TRANSFER:
+		/* Check that the sysace is ready to receive data */
+		status = ace_in32(ace, ACE_STATUS);
+		if (status & ACE_STATUS_CFBSY) {
+			dev_dbg(ace->dev, "CFBSY set; t=%i iter=%i dc=%i\n",
+				ace->fsm_task, ace->fsm_iter_num,
+				ace->data_count);
+			ace_fsm_yield(ace);
+			break;
+		}
+		if (!(status & ACE_STATUS_DATABUFRDY)) {
+			ace_fsm_yield(ace);
+			break;
+		}
+
+		/* Transfer the next buffer */
+		ace->reg_ops->datain(ace);
+		ace->data_count--;
+
+		/* If there are still buffers to be transfers; jump out here */
+		if (ace->data_count != 0) {
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		/* transfer finished; kick state machine */
+		dev_dbg(ace->dev, "identify finished\n");
+		ace->fsm_state = ACE_FSM_STATE_IDENTIFY_COMPLETE;
+		break;
+
+	case ACE_FSM_STATE_IDENTIFY_COMPLETE:
+		ace_fix_driveid(&ace->cf_id);
+		ace_dump_mem(&ace->cf_id, 512);	/* Debug: Dump out disk ID */
+
+		if (ace->data_result) {
+			/* Error occured, disable the disk */
+			ace->media_change = 1;
+			set_capacity(ace->gd, 0);
+			dev_err(ace->dev, "error fetching CF id (%i)\n",
+				ace->data_result);
+		} else {
+			ace->media_change = 0;
+
+			/* Record disk parameters */
+			set_capacity(ace->gd, ace->cf_id.lba_capacity);
+			dev_info(ace->dev, "capacity: %i sectors\n",
+				 ace->cf_id.lba_capacity);
+		}
+
+		/* We're done, drop to IDLE state and notify waiters */
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		ace->id_result = ace->data_result;
+		while (ace->id_req_count) {
+			complete(&ace->id_completion);
+			ace->id_req_count--;
+		}
+		break;
+
+	case ACE_FSM_STATE_REQ_PREPARE:
+		req = ace_get_next_request(ace->queue);
+		if (!req) {
+			ace->fsm_state = ACE_FSM_STATE_IDLE;
+			break;
+		}
+
+		/* Okay, it's a data request, set it up for transfer */
+		dev_dbg(ace->dev,
+			"request: sec=%lx hcnt=%lx, ccnt=%x, dir=%i\n",
+			req->sector, req->hard_nr_sectors,
+			req->current_nr_sectors, rq_data_dir(req));
+
+		ace->req = req;
+		ace->data_ptr = req->buffer;
+		ace->data_count = req->current_nr_sectors * ACE_BUF_PER_SECTOR;
+		ace_out32(ace, ACE_MPULBA, req->sector & 0x0FFFFFFF);
+
+		count = req->hard_nr_sectors;
+		if (rq_data_dir(req)) {
+			/* Kick off write request */
+			dev_dbg(ace->dev, "write data\n");
+			ace->fsm_task = ACE_TASK_WRITE;
+			ace_out(ace, ACE_SECCNTCMD,
+				count | ACE_SECCNTCMD_WRITE_DATA);
+		} else {
+			/* Kick off read request */
+			dev_dbg(ace->dev, "read data\n");
+			ace->fsm_task = ACE_TASK_READ;
+			ace_out(ace, ACE_SECCNTCMD,
+				count | ACE_SECCNTCMD_READ_DATA);
+		}
+
+		/* As per datasheet, put config controller in reset */
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
+
+		/* Move to the transfer state.  The systemace will raise
+		 * an interrupt once there is something to do
+		 */
+		ace->fsm_state = ACE_FSM_STATE_REQ_TRANSFER;
+		if (ace->fsm_task == ACE_TASK_READ)
+			ace_fsm_yieldirq(ace);	/* wait for data ready */
+		break;
+
+	case ACE_FSM_STATE_REQ_TRANSFER:
+		/* Check that the sysace is ready to receive data */
+		status = ace_in32(ace, ACE_STATUS);
+		if (status & ACE_STATUS_CFBSY) {
+			dev_dbg(ace->dev,
+				"CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n",
+				ace->fsm_task, ace->fsm_iter_num,
+				ace->req->current_nr_sectors * 16,
+				ace->data_count, ace->in_irq);
+			ace_fsm_yield(ace);	/* need to poll CFBSY bit */
+			break;
+		}
+		if (!(status & ACE_STATUS_DATABUFRDY)) {
+			dev_dbg(ace->dev,
+				"DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n",
+				ace->fsm_task, ace->fsm_iter_num,
+				ace->req->current_nr_sectors * 16,
+				ace->data_count, ace->in_irq);
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		/* Transfer the next buffer */
+		i = 16;
+		if (ace->fsm_task == ACE_TASK_WRITE)
+			ace->reg_ops->dataout(ace);
+		else
+			ace->reg_ops->datain(ace);
+		ace->data_count--;
+
+		/* If there are still buffers to be transfers; jump out here */
+		if (ace->data_count != 0) {
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		/* bio finished; is there another one? */
+		i = ace->req->current_nr_sectors;
+		if (end_that_request_first(ace->req, 1, i)) {
+			/* dev_dbg(ace->dev, "next block; h=%li c=%i\n",
+			 *      ace->req->hard_nr_sectors,
+			 *      ace->req->current_nr_sectors);
+			 */
+			ace->data_ptr = ace->req->buffer;
+			ace->data_count = ace->req->current_nr_sectors * 16;
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		ace->fsm_state = ACE_FSM_STATE_REQ_COMPLETE;
+		break;
+
+	case ACE_FSM_STATE_REQ_COMPLETE:
+		/* Complete the block request */
+		blkdev_dequeue_request(ace->req);
+		end_that_request_last(ace->req, 1);
+		ace->req = NULL;
+
+		/* Finished request; go to idle state */
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		break;
+
+	default:
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		break;
+	}
+}
+
+static void ace_fsm_tasklet(unsigned long data)
+{
+	struct ace_device *ace = (void *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ace->lock, flags);
+
+	/* Loop over state machine until told to stop */
+	ace->fsm_continue_flag = 1;
+	while (ace->fsm_continue_flag)
+		ace_fsm_dostate(ace);
+
+	spin_unlock_irqrestore(&ace->lock, flags);
+}
+
+static void ace_stall_timer(unsigned long data)
+{
+	struct ace_device *ace = (void *)data;
+	unsigned long flags;
+
+	dev_warn(ace->dev,
+		 "kicking stalled fsm; state=%i task=%i iter=%i dc=%i\n",
+		 ace->fsm_state, ace->fsm_task, ace->fsm_iter_num,
+		 ace->data_count);
+	spin_lock_irqsave(&ace->lock, flags);
+
+	/* Rearm the stall timer *before* entering FSM (which may then
+	 * delete the timer) */
+	mod_timer(&ace->stall_timer, jiffies + HZ);
+
+	/* Loop over state machine until told to stop */
+	ace->fsm_continue_flag = 1;
+	while (ace->fsm_continue_flag)
+		ace_fsm_dostate(ace);
+
+	spin_unlock_irqrestore(&ace->lock, flags);
+}
+
+/* ---------------------------------------------------------------------
+ * Interrupt handling routines
+ */
+static int ace_interrupt_checkstate(struct ace_device *ace)
+{
+	u32 sreg = ace_in32(ace, ACE_STATUS);
+	u16 creg = ace_in(ace, ACE_CTRL);
+
+	/* Check for error occurance */
+	if ((sreg & (ACE_STATUS_CFGERROR | ACE_STATUS_CFCERROR)) &&
+	    (creg & ACE_CTRL_ERRORIRQ)) {
+		dev_err(ace->dev, "transfer failure\n");
+		ace_dump_regs(ace);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static irqreturn_t ace_interrupt(int irq, void *dev_id)
+{
+	u16 creg;
+	struct ace_device *ace = dev_id;
+
+	/* be safe and get the lock */
+	spin_lock(&ace->lock);
+	ace->in_irq = 1;
+
+	/* clear the interrupt */
+	creg = ace_in(ace, ACE_CTRL);
+	ace_out(ace, ACE_CTRL, creg | ACE_CTRL_RESETIRQ);
+	ace_out(ace, ACE_CTRL, creg);
+
+	/* check for IO failures */
+	if (ace_interrupt_checkstate(ace))
+		ace->data_result = -EIO;
+
+	if (ace->fsm_task == 0) {
+		dev_err(ace->dev,
+			"spurious irq; stat=%.8x ctrl=%.8x cmd=%.4x\n",
+			ace_in32(ace, ACE_STATUS), ace_in32(ace, ACE_CTRL),
+			ace_in(ace, ACE_SECCNTCMD));
+		dev_err(ace->dev, "fsm_task=%i fsm_state=%i data_count=%i\n",
+			ace->fsm_task, ace->fsm_state, ace->data_count);
+	}
+
+	/* Loop over state machine until told to stop */
+	ace->fsm_continue_flag = 1;
+	while (ace->fsm_continue_flag)
+		ace_fsm_dostate(ace);
+
+	/* done with interrupt; drop the lock */
+	ace->in_irq = 0;
+	spin_unlock(&ace->lock);
+
+	return IRQ_HANDLED;
+}
+
+/* ---------------------------------------------------------------------
+ * Block ops
+ */
+static void ace_request(request_queue_t * q)
+{
+	struct request *req;
+	struct ace_device *ace;
+
+	req = ace_get_next_request(q);
+
+	if (req) {
+		ace = req->rq_disk->private_data;
+		tasklet_schedule(&ace->fsm_tasklet);
+	}
+}
+
+static int ace_media_changed(struct gendisk *gd)
+{
+	struct ace_device *ace = gd->private_data;
+	dev_dbg(ace->dev, "ace_media_changed(): %i\n", ace->media_change);
+
+	return ace->media_change;
+}
+
+static int ace_revalidate_disk(struct gendisk *gd)
+{
+	struct ace_device *ace = gd->private_data;
+	unsigned long flags;
+
+	dev_dbg(ace->dev, "ace_revalidate_disk()\n");
+
+	if (ace->media_change) {
+		dev_dbg(ace->dev, "requesting cf id and scheduling tasklet\n");
+
+		spin_lock_irqsave(&ace->lock, flags);
+		ace->id_req_count++;
+		spin_unlock_irqrestore(&ace->lock, flags);
+
+		tasklet_schedule(&ace->fsm_tasklet);
+		wait_for_completion(&ace->id_completion);
+	}
+
+	dev_dbg(ace->dev, "revalidate complete\n");
+	return ace->id_result;
+}
+
+static int ace_open(struct inode *inode, struct file *filp)
+{
+	struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+	unsigned long flags;
+
+	dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
+
+	filp->private_data = ace;
+	spin_lock_irqsave(&ace->lock, flags);
+	ace->users++;
+	spin_unlock_irqrestore(&ace->lock, flags);
+
+	check_disk_change(inode->i_bdev);
+	return 0;
+}
+
+static int ace_release(struct inode *inode, struct file *filp)
+{
+	struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+	unsigned long flags;
+	u16 val;
+
+	dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
+
+	spin_lock_irqsave(&ace->lock, flags);
+	ace->users--;
+	if (ace->users == 0) {
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
+	}
+	spin_unlock_irqrestore(&ace->lock, flags);
+	return 0;
+}
+
+static int ace_ioctl(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+	struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
+	struct hd_geometry g;
+	dev_dbg(ace->dev, "ace_ioctl()\n");
+
+	switch (cmd) {
+	case HDIO_GETGEO:
+		g.heads = ace->cf_id.heads;
+		g.sectors = ace->cf_id.sectors;
+		g.cylinders = ace->cf_id.cyls;
+		g.start = 0;
+		return copy_to_user(geo, &g, sizeof(g)) ? -EFAULT : 0;
+
+	default:
+		return -ENOTTY;
+	}
+	return -ENOTTY;
+}
+
+static struct block_device_operations ace_fops = {
+	.owner = THIS_MODULE,
+	.open = ace_open,
+	.release = ace_release,
+	.media_changed = ace_media_changed,
+	.revalidate_disk = ace_revalidate_disk,
+	.ioctl = ace_ioctl,
+};
+
+/* --------------------------------------------------------------------
+ * SystemACE device setup/teardown code
+ */
+static int __devinit ace_setup(struct ace_device *ace)
+{
+	u16 version;
+	u16 val;
+
+	int rc;
+
+	spin_lock_init(&ace->lock);
+	init_completion(&ace->id_completion);
+
+	/*
+	 * Map the device
+	 */
+	ace->baseaddr = ioremap(ace->physaddr, 0x80);
+	if (!ace->baseaddr)
+		goto err_ioremap;
+
+	if (ace->irq != NO_IRQ) {
+		rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
+		if (rc) {
+			/* Failure - fall back to polled mode */
+			dev_err(ace->dev, "request_irq failed\n");
+			ace->irq = NO_IRQ;
+		}
+	}
+
+	/*
+	 * Initialize the state machine tasklet and stall timer
+	 */
+	tasklet_init(&ace->fsm_tasklet, ace_fsm_tasklet, (unsigned long)ace);
+	setup_timer(&ace->stall_timer, ace_stall_timer, (unsigned long)ace);
+
+	/*
+	 * Initialize the request queue
+	 */
+	ace->queue = blk_init_queue(ace_request, &ace->lock);
+	if (ace->queue == NULL)
+		goto err_blk_initq;
+	blk_queue_hardsect_size(ace->queue, 512);
+
+	/*
+	 * Allocate and initialize GD structure
+	 */
+	ace->gd = alloc_disk(ACE_NUM_MINORS);
+	if (!ace->gd)
+		goto err_alloc_disk;
+
+	ace->gd->major = ace_major;
+	ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
+	ace->gd->fops = &ace_fops;
+	ace->gd->queue = ace->queue;
+	ace->gd->private_data = ace;
+	snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
+
+	/* set bus width */
+	if (ace->bus_width == 1) {
+		/* 0x0101 should work regardless of endianess */
+		ace_out_le16(ace, ACE_BUSMODE, 0x0101);
+
+		/* read it back to determine endianess */
+		if (ace_in_le16(ace, ACE_BUSMODE) == 0x0001)
+			ace->reg_ops = &ace_reg_le16_ops;
+		else
+			ace->reg_ops = &ace_reg_be16_ops;
+	} else {
+		ace_out_8(ace, ACE_BUSMODE, 0x00);
+		ace->reg_ops = &ace_reg_8_ops;
+	}
+
+	/* Make sure version register is sane */
+	version = ace_in(ace, ACE_VERSION);
+	if ((version == 0) || (version == 0xFFFF))
+		goto err_read;
+
+	/* Put sysace in a sane state by clearing most control reg bits */
+	ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE |
+		ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
+
+	/* Enable interrupts */
+	val = ace_in(ace, ACE_CTRL);
+	val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ;
+	ace_out(ace, ACE_CTRL, val);
+
+	/* Print the identification */
+	dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n",
+		 (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff);
+	dev_dbg(ace->dev, "physaddr 0x%lx, mapped to 0x%p, irq=%i\n",
+		ace->physaddr, ace->baseaddr, ace->irq);
+
+	ace->media_change = 1;
+	ace_revalidate_disk(ace->gd);
+
+	/* Make the sysace device 'live' */
+	add_disk(ace->gd);
+
+	return 0;
+
+      err_read:
+	put_disk(ace->gd);
+      err_alloc_disk:
+	blk_cleanup_queue(ace->queue);
+      err_blk_initq:
+	iounmap(ace->baseaddr);
+	if (ace->irq != NO_IRQ)
+		free_irq(ace->irq, ace);
+      err_ioremap:
+	printk(KERN_INFO "xsysace: error initializing device at 0x%lx\n",
+	       ace->physaddr);
+	return -ENOMEM;
+}
+
+static void __devexit ace_teardown(struct ace_device *ace)
+{
+	if (ace->gd) {
+		del_gendisk(ace->gd);
+		put_disk(ace->gd);
+	}
+
+	if (ace->queue)
+		blk_cleanup_queue(ace->queue);
+
+	tasklet_kill(&ace->fsm_tasklet);
+
+	if (ace->irq != NO_IRQ)
+		free_irq(ace->irq, ace);
+
+	iounmap(ace->baseaddr);
+}
+
+/* ---------------------------------------------------------------------
+ * Platform Bus Support
+ */
+
+static int __devinit ace_probe(struct device *device)
+{
+	struct platform_device *dev = to_platform_device(device);
+	struct ace_device *ace;
+	int i;
+
+	dev_dbg(device, "ace_probe(%p)\n", device);
+
+	/*
+	 * Allocate the ace device structure
+	 */
+	ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL);
+	if (!ace)
+		goto err_alloc;
+
+	ace->dev = device;
+	ace->id = dev->id;
+	ace->irq = NO_IRQ;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		if (dev->resource[i].flags & IORESOURCE_MEM)
+			ace->physaddr = dev->resource[i].start;
+		if (dev->resource[i].flags & IORESOURCE_IRQ)
+			ace->irq = dev->resource[i].start;
+	}
+
+	/* FIXME: Should get bus_width from the platform_device struct */
+	ace->bus_width = 1;
+
+	dev_set_drvdata(&dev->dev, ace);
+
+	/* Call the bus-independant setup code */
+	if (ace_setup(ace) != 0)
+		goto err_setup;
+
+	return 0;
+
+      err_setup:
+	dev_set_drvdata(&dev->dev, NULL);
+	kfree(ace);
+      err_alloc:
+	printk(KERN_ERR "xsysace: could not initialize device\n");
+	return -ENOMEM;
+}
+
+/*
+ * Platform bus remove() method
+ */
+static int __devexit ace_remove(struct device *device)
+{
+	struct ace_device *ace = dev_get_drvdata(device);
+
+	dev_dbg(device, "ace_remove(%p)\n", device);
+
+	if (ace) {
+		ace_teardown(ace);
+		kfree(ace);
+	}
+
+	return 0;
+}
+
+static struct device_driver ace_driver = {
+	.name = "xsysace",
+	.bus = &platform_bus_type,
+	.probe = ace_probe,
+	.remove = __devexit_p(ace_remove),
+};
+
+/* ---------------------------------------------------------------------
+ * Module init/exit routines
+ */
+static int __init ace_init(void)
+{
+	ace_major = register_blkdev(ace_major, "xsysace");
+	if (ace_major <= 0) {
+		printk(KERN_WARNING "xsysace: register_blkdev() failed\n");
+		return ace_major;
+	}
+
+	pr_debug("Registering Xilinx SystemACE driver, major=%i\n", ace_major);
+	return driver_register(&ace_driver);
+}
+
+static void __exit ace_exit(void)
+{
+	pr_debug("Unregistering Xilinx SystemACE driver\n");
+	driver_unregister(&ace_driver);
+	unregister_blkdev(ace_major, "xsysace");
+}
+
+module_init(ace_init);
+module_exit(ace_exit);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 7cc2685..e40fa98 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -44,9 +44,6 @@
 extern int m68k_realnum_memory;
 extern struct mem_info m68k_memory[NUM_MEMINFO];
 
-#define TRUE                  (1)
-#define FALSE                 (0)
-
 #define Z2MINOR_COMBINED      (0)
 #define Z2MINOR_Z2ONLY        (1)
 #define Z2MINOR_CHIPONLY      (2)
@@ -374,9 +371,7 @@
 {
     int i, j;
     blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
-    if ( unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME ) != 0 )
-	printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
-
+    unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
     del_gendisk(z2ram_gendisk);
     put_disk(z2ram_gendisk);
     blk_cleanup_queue(z2_queue);
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index aa5468f..499019bf 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2695,11 +2695,12 @@
 {
 	void __user *argp = (void __user *)arg;
 	int ret;
+	struct gendisk *disk = ip->i_bdev->bd_disk;
 
 	/*
 	 * Try the generic SCSI command ioctl's first.
 	 */
-	ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp);
+	ret = scsi_cmd_ioctl(file, disk->queue, disk, cmd, argp);
 	if (ret != -ENOTTY)
 		return ret;
 
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index f664868..d8d7125 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -114,7 +114,7 @@
 
 config ROCKETPORT
 	tristate "Comtrol RocketPort support"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
 	help
 	  This driver supports Comtrol RocketPort and RocketModem PCI boards.   
           These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
@@ -157,7 +157,7 @@
 
 config DIGIEPCA
 	tristate "Digiboard Intelligent Async Support"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
 	---help---
 	  This is a driver for Digi International's Xx, Xeve, and Xem series
 	  of cards which provide multiple serial ports. You would need
@@ -213,8 +213,6 @@
 	  This is upgraded (1.9.1) driver from original Moxa drivers with
 	  changes finally resulting in PCI probing.
 
-	  Use at your own risk.
-
 	  This driver can also be built as a module. The module will be called
 	  mxser_new. If you want to do that, say M here.
 
@@ -354,7 +352,7 @@
 
 config STALLION
 	tristate "Stallion EasyIO or EC8/32 support"
-	depends on STALDRV && BROKEN_ON_SMP
+	depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
 	help
 	  If you have an EasyIO or EasyConnection 8/32 multiport Stallion
 	  card, then this is for you; say Y.  Make sure to read
@@ -365,7 +363,7 @@
 
 config ISTALLION
 	tristate "Stallion EC8/64, ONboard, Brumby support"
-	depends on STALDRV && BROKEN_ON_SMP
+	depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
 	help
 	  If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
 	  serial multiport card, say Y here. Make sure to read
@@ -979,15 +977,14 @@
 	depends on CPU_VR41XX
 
 config RAW_DRIVER
-	tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+	tristate "RAW driver (/dev/raw/rawN)"
 	depends on BLOCK
 	help
-	  The raw driver permits block devices to be bound to /dev/raw/rawN. 
-	  Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. 
+	  The raw driver permits block devices to be bound to /dev/raw/rawN.
+	  Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
 	  See the raw(8) manpage for more details.
 
-          The raw driver is deprecated and will be removed soon.
-          Applications should simply open the device (eg /dev/hda1)
+          Applications should preferably open the device (eg /dev/hda1)
           with the O_DIRECT flag.
 
 config MAX_RAW_DEVS
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 2f56ecc..f2996a9 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o consolemap.o \
 				   consolemap_deftbl.o selection.o keyboard.o
 obj-$(CONFIG_HW_CONSOLE)	+= vt.o defkeymap.o
+obj-$(CONFIG_AUDIT)		+= tty_audit.o
 obj-$(CONFIG_MAGIC_SYSRQ)	+= sysrq.o
 obj-$(CONFIG_ESPSERIAL)		+= esp.o
 obj-$(CONFIG_MVME147_SCC)	+= generic_serial.o vme_scc.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 4eaceab..7b02bf1 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -738,6 +738,7 @@
 	}
 	/* If the quotient is zero refuse the change */
 	if (!quot && old_termios) {
+		/* FIXME: Will need updating for new tty in the end */
 		info->tty->termios->c_cflag &= ~CBAUD;
 		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
 		baud = tty_get_baud_rate(info->tty);
@@ -783,7 +784,6 @@
 	/*
 	 * Set up parity check flag
 	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 
 	info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
 	if (I_INPCK(info->tty))
@@ -1367,11 +1367,6 @@
 	unsigned long flags;
 	unsigned int cflag = tty->termios->c_cflag;
 
-	if (   (cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	change_speed(info, old_termios);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 179c7a3..ec116df 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/pm.h>
 #include <linux/apm-emulation.h>
+#include <linux/freezer.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -329,13 +330,8 @@
 			/*
 			 * Wait for the suspend/resume to complete.  If there
 			 * are pending acknowledges, we wait here for them.
-			 *
-			 * Note: we need to ensure that the PM subsystem does
-			 * not kick us out of the wait when it suspends the
-			 * threads.
 			 */
 			flags = current->flags;
-			current->flags |= PF_NOFREEZE;
 
 			wait_event(apm_suspend_waitqueue,
 				   as->suspend_state == SUSPEND_DONE);
@@ -365,13 +361,8 @@
 			/*
 			 * Wait for the suspend/resume to complete.  If there
 			 * are pending acknowledges, we wait here for them.
-			 *
-			 * Note: we need to ensure that the PM subsystem does
-			 * not kick us out of the wait when it suspends the
-			 * threads.
 			 */
 			flags = current->flags;
-			current->flags |= PF_NOFREEZE;
 
 			wait_event_interruptible(apm_suspend_waitqueue,
 					 as->suspend_state == SUSPEND_DONE);
@@ -598,7 +589,6 @@
 		kapmd_tsk = NULL;
 		return ret;
 	}
-	kapmd_tsk->flags |= PF_NOFREEZE;
 	wake_up_process(kapmd_tsk);
 
 #ifdef CONFIG_PROC_FS
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index ed53f54..b6f2639 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -91,11 +91,6 @@
 	unsigned short c;
 	unsigned char cp;
 
-#if 0	/*  Can't seek (pread) on this device  */
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-#endif
-
 	if (!vfd_is_open)
 		return -ENODEV;
 
@@ -139,11 +134,6 @@
 	size_t indx = len;
 	int i, esc = 0;
 
-#if 0	/*  Can't seek (pwrite) on this device  */
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-#endif
-
 	if (!vfd_is_open)
 		return -EBUSY;
 
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index fd40b95..4b3916f 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -177,6 +177,7 @@
 	unsigned long	refcount;
 	unsigned long	sum;
 	unsigned char	*inverse_translations[4];
+	u16		*inverse_trans_unicode;
 	int		readonly;
 };
 
@@ -207,6 +208,41 @@
 	}
 }
 
+static void set_inverse_trans_unicode(struct vc_data *conp,
+				      struct uni_pagedir *p)
+{
+	int i, j, k, glyph;
+	u16 **p1, *p2;
+	u16 *q;
+
+	if (!p) return;
+	q = p->inverse_trans_unicode;
+	if (!q) {
+		q = p->inverse_trans_unicode =
+			kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
+		if (!q)
+			return;
+	}
+	memset(q, 0, MAX_GLYPH * sizeof(u16));
+
+	for (i = 0; i < 32; i++) {
+		p1 = p->uni_pgdir[i];
+		if (!p1)
+			continue;
+		for (j = 0; j < 32; j++) {
+			p2 = p1[j];
+			if (!p2)
+				continue;
+			for (k = 0; k < 64; k++) {
+				glyph = p2[k];
+				if (glyph >= 0 && glyph < MAX_GLYPH
+					       && q[glyph] < 32)
+		  			q[glyph] = (i << 11) + (j << 6) + k;
+			}
+		}
+	}
+}
+
 unsigned short *set_translate(int m, struct vc_data *vc)
 {
 	inv_translate[vc->vc_num] = m;
@@ -217,19 +253,29 @@
  * Inverse translation is impossible for several reasons:
  * 1. The font<->character maps are not 1-1.
  * 2. The text may have been written while a different translation map
- *    was active, or using Unicode.
+ *    was active.
  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
  */
-unsigned char inverse_translate(struct vc_data *conp, int glyph)
+u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
 {
 	struct uni_pagedir *p;
+	int m;
 	if (glyph < 0 || glyph >= MAX_GLYPH)
 		return 0;
-	else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
-		 !p->inverse_translations[inv_translate[conp->vc_num]])
+	else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
 		return glyph;
-	else
-		return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
+	else if (use_unicode) {
+		if (!p->inverse_trans_unicode)
+			return glyph;
+		else
+			return p->inverse_trans_unicode[glyph];
+	} else {
+		m = inv_translate[conp->vc_num];
+		if (!p->inverse_translations[m])
+			return glyph;
+		else
+			return p->inverse_translations[m][glyph];
+	}
 }
 
 static void update_user_maps(void)
@@ -243,6 +289,7 @@
 		p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
 		if (p && p != q) {
 			set_inverse_transl(vc_cons[i].d, p, USER_MAP);
+			set_inverse_trans_unicode(vc_cons[i].d, p);
 			q = p;
 		}
 	}
@@ -353,6 +400,10 @@
 		kfree(p->inverse_translations[i]);
 		p->inverse_translations[i] = NULL;
 	}
+	if (p->inverse_trans_unicode) {
+		kfree(p->inverse_trans_unicode);
+		p->inverse_trans_unicode = NULL;
+	}
 }
 
 void con_free_unimap(struct vc_data *vc)
@@ -511,6 +562,7 @@
 
 	for (i = 0; i <= 3; i++)
 		set_inverse_transl(vc, p, i); /* Update all inverse translations */
+	set_inverse_trans_unicode(vc, p);
   
 	return err;
 }
@@ -561,6 +613,7 @@
 
 	for (i = 0; i <= 3; i++)
 		set_inverse_transl(vc, p, i);	/* Update all inverse translations */
+	set_inverse_trans_unicode(vc, p);
 	dflt = p;
 	return err;
 }
@@ -617,6 +670,19 @@
 		p->readonly = rdonly;
 }
 
+/* may be called during an interrupt */
+u32 conv_8bit_to_uni(unsigned char c)
+{
+	/*
+	 * Always use USER_MAP. This function is used by the keyboard,
+	 * which shouldn't be affected by G0/G1 switching, etc.
+	 * If the user map still contains default values, i.e. the
+	 * direct-to-font mapping, then assume user is using Latin1.
+	 */
+	unsigned short uni = translations[USER_MAP][c];
+	return uni == (0xf000 | c) ? c : uni;
+}
+
 int
 conv_uni_to_pc(struct vc_data *conp, long ucs) 
 {
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index ca376b9..7b08394 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -646,6 +646,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
+#include <linux/firmware.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -680,6 +681,44 @@
 
 #define STD_COM_FLAGS (0)
 
+/* firmware stuff */
+#define ZL_MAX_BLOCKS	16
+#define DRIVER_VERSION	0x02010203
+#define RAM_SIZE 0x80000
+
+#define Z_FPGA_LOADED(X)	((readl(&(X)->init_ctrl) & (1<<17)) != 0)
+
+enum zblock_type {
+	ZBLOCK_PRG = 0,
+	ZBLOCK_FPGA = 1
+};
+
+struct zfile_header {
+	char name[64];
+	char date[32];
+	char aux[32];
+	u32 n_config;
+	u32 config_offset;
+	u32 n_blocks;
+	u32 block_offset;
+	u32 reserved[9];
+} __attribute__ ((packed));
+
+struct zfile_config {
+	char name[64];
+	u32 mailbox;
+	u32 function;
+	u32 n_blocks;
+	u32 block_list[ZL_MAX_BLOCKS];
+} __attribute__ ((packed));
+
+struct zfile_block {
+	u32 type;
+	u32 file_offset;
+	u32 ram_offset;
+	u32 size;
+} __attribute__ ((packed));
+
 static struct tty_driver *cy_serial_driver;
 
 #ifdef CONFIG_ISA
@@ -1851,11 +1890,11 @@
 	struct cyclades_card *cinfo;
 	struct cyclades_port *info;
 	struct tty_struct *tty;
-	static struct FIRM_ID *firm_id;
-	static struct ZFW_CTRL *zfw_ctrl;
-	static struct BOARD_CTRL *board_ctrl;
-	static struct CH_CTRL *ch_ctrl;
-	static struct BUF_CTRL *buf_ctrl;
+	struct FIRM_ID __iomem *firm_id;
+	struct ZFW_CTRL __iomem *zfw_ctrl;
+	struct BOARD_CTRL __iomem *board_ctrl;
+	struct CH_CTRL __iomem *ch_ctrl;
+	struct BUF_CTRL __iomem *buf_ctrl;
 	unsigned long expires = jiffies + HZ;
 	int card, port;
 
@@ -1999,7 +2038,6 @@
 		struct ZFW_CTRL __iomem *zfw_ctrl;
 		struct BOARD_CTRL __iomem *board_ctrl;
 		struct CH_CTRL __iomem *ch_ctrl;
-		int retval;
 
 		base_addr = card->base_addr;
 
@@ -2371,7 +2409,6 @@
 		struct ZFW_CTRL __iomem *zfw_ctrl;
 		struct BOARD_CTRL __iomem *board_ctrl;
 		struct CH_CTRL __iomem *ch_ctrl;
-		int retval;
 
 		base_addr = cinfo->base_addr;
 		firm_id = base_addr + ID_ADDRESS;
@@ -4127,10 +4164,6 @@
 	printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
 #endif
 
-	if (tty->termios->c_cflag == old_termios->c_cflag &&
-			(tty->termios->c_iflag & (IXON | IXANY)) ==
-			(old_termios->c_iflag & (IXON | IXANY)))
-		return;
 	set_line_char(info);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
@@ -4739,17 +4772,295 @@
 }				/* cy_detect_isa */
 
 #ifdef CONFIG_PCI
-static void __devinit plx_init(void __iomem * addr, __u32 initctl)
+static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
+{
+	unsigned int a;
+
+	for (a = 0; a < size && *str; a++, str++)
+		if (*str & 0x80)
+			return -EINVAL;
+
+	for (; a < size; a++, str++)
+		if (*str)
+			return -EINVAL;
+
+	return 0;
+}
+
+static inline void __devinit cyz_fpga_copy(void __iomem *fpga, u8 *data,
+		unsigned int size)
+{
+	for (; size > 0; size--) {
+		cy_writel(fpga, *data++);
+		udelay(10);
+	}
+}
+
+static void __devinit plx_init(struct pci_dev *pdev, int irq,
+		struct RUNTIME_9060 __iomem *addr)
 {
 	/* Reset PLX */
-	cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
 	udelay(100L);
-	cy_writel(addr + initctl, readl(addr + initctl) & ~0x40000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
 
 	/* Reload Config. Registers from EEPROM */
-	cy_writel(addr + initctl, readl(addr + initctl) | 0x20000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
 	udelay(100L);
-	cy_writel(addr + initctl, readl(addr + initctl) & ~0x20000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
+
+	/* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
+	 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
+	 * registers. This will remain here until we find a permanent fix.
+	 */
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+}
+
+static int __devinit __cyz_load_fw(const struct firmware *fw,
+		const char *name, const u32 mailbox, void __iomem *base,
+		void __iomem *fpga)
+{
+	void *ptr = fw->data;
+	struct zfile_header *h = ptr;
+	struct zfile_config *c, *cs;
+	struct zfile_block *b, *bs;
+	unsigned int a, tmp, len = fw->size;
+#define BAD_FW KERN_ERR "Bad firmware: "
+	if (len < sizeof(*h)) {
+		printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
+		return -EINVAL;
+	}
+
+	cs = ptr + h->config_offset;
+	bs = ptr + h->block_offset;
+
+	if ((void *)(cs + h->n_config) > ptr + len ||
+			(void *)(bs + h->n_blocks) > ptr + len) {
+		printk(BAD_FW "too short");
+		return  -EINVAL;
+	}
+
+	if (cyc_isfwstr(h->name, sizeof(h->name)) ||
+			cyc_isfwstr(h->date, sizeof(h->date))) {
+		printk(BAD_FW "bad formatted header string\n");
+		return -EINVAL;
+	}
+
+	if (strncmp(name, h->name, sizeof(h->name))) {
+		printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
+		return -EINVAL;
+	}
+
+	tmp = 0;
+	for (c = cs; c < cs + h->n_config; c++) {
+		for (a = 0; a < c->n_blocks; a++)
+			if (c->block_list[a] > h->n_blocks) {
+				printk(BAD_FW "bad block ref number in cfgs\n");
+				return -EINVAL;
+			}
+		if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
+			tmp++;
+	}
+	if (!tmp) {
+		printk(BAD_FW "nothing appropriate\n");
+		return -EINVAL;
+	}
+
+	for (b = bs; b < bs + h->n_blocks; b++)
+		if (b->file_offset + b->size > len) {
+			printk(BAD_FW "bad block data offset\n");
+			return -EINVAL;
+		}
+
+	/* everything is OK, let's seek'n'load it */
+	for (c = cs; c < cs + h->n_config; c++)
+		if (c->mailbox == mailbox && c->function == 0)
+			break;
+
+	for (a = 0; a < c->n_blocks; a++) {
+		b = &bs[c->block_list[a]];
+		if (b->type == ZBLOCK_FPGA) {
+			if (fpga != NULL)
+				cyz_fpga_copy(fpga, ptr + b->file_offset,
+						b->size);
+		} else {
+			if (base != NULL)
+				memcpy_toio(base + b->ram_offset,
+					       ptr + b->file_offset, b->size);
+		}
+	}
+#undef BAD_FW
+	return 0;
+}
+
+static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
+{
+	const struct firmware *fw;
+	struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
+	struct CUSTOM_REG __iomem *cust = base_addr;
+	struct ZFW_CTRL __iomem *pt_zfwctrl;
+	void __iomem *tmp;
+	u32 mailbox, status;
+	unsigned int i;
+	int retval;
+
+	retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
+	if (retval) {
+		dev_err(&pdev->dev, "can't get firmware\n");
+		goto err;
+	}
+
+	/* Check whether the firmware is already loaded and running. If
+	   positive, skip this board */
+	if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
+		u32 cntval = readl(base_addr + 0x190);
+
+		udelay(100);
+		if (cntval != readl(base_addr + 0x190)) {
+			/* FW counter is working, FW is running */
+			dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
+					"Skipping board.\n");
+			retval = 0;
+			goto err_rel;
+		}
+	}
+
+	/* start boot */
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
+			~0x00030800UL);
+
+	mailbox = readl(&ctl_addr->mail_box_0);
+
+	if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
+		/* stops CPU and set window to beginning of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+		cy_writel(&cust->cpu_stop, 0);
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+		udelay(100);
+	}
+
+	plx_init(pdev, irq, ctl_addr);
+
+	if (mailbox != 0) {
+		/* load FPGA */
+		retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
+				base_addr);
+		if (retval)
+			goto err_rel;
+		if (!Z_FPGA_LOADED(ctl_addr)) {
+			dev_err(&pdev->dev, "fw upload successful, but fw is "
+					"not loaded\n");
+			goto err_rel;
+		}
+	}
+
+	/* stops CPU and set window to beginning of RAM */
+	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+	cy_writel(&cust->cpu_stop, 0);
+	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+	udelay(100);
+
+	/* clear memory */
+	for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+		cy_writeb(tmp, 255);
+	if (mailbox != 0) {
+		/* set window to last 512K of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
+		//sleep(1);
+		for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+			cy_writeb(tmp, 255);
+		/* set window to beginning of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+		//sleep(1);
+	}
+
+	retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
+	release_firmware(fw);
+	if (retval)
+		goto err;
+
+	/* finish boot and start boards */
+	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+	cy_writel(&cust->cpu_start, 0);
+	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+	i = 0;
+	while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
+		msleep(100);
+	if (status != ZFIRM_ID) {
+		if (status == ZFIRM_HLT) {
+			dev_err(&pdev->dev, "you need an external power supply "
+				"for this number of ports. Firmware halted and "
+				"board reset.\n");
+			retval = -EIO;
+			goto err;
+		}
+		dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
+				"some more time\n", status);
+		while ((status = readl(&fid->signature)) != ZFIRM_ID &&
+				i++ < 200)
+			msleep(100);
+		if (status != ZFIRM_ID) {
+			dev_err(&pdev->dev, "Board not started in 20 seconds! "
+					"Giving up. (fid->signature = 0x%x)\n",
+					status);
+			dev_info(&pdev->dev, "*** Warning ***: if you are "
+				"upgrading the FW, please power cycle the "
+				"system before loading the new FW to the "
+				"Cyclades-Z.\n");
+
+			if (Z_FPGA_LOADED(ctl_addr))
+				plx_init(pdev, irq, ctl_addr);
+
+			retval = -EIO;
+			goto err;
+		}
+		dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
+				i / 10);
+	}
+	pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
+
+	dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
+			base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
+			base_addr + readl(&fid->zfwctrl_addr));
+
+	dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
+		readl(&pt_zfwctrl->board_ctrl.fw_version),
+		readl(&pt_zfwctrl->board_ctrl.n_channel));
+
+	if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
+		dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
+			"check the connection between the Z host card and the "
+			"serial expanders.\n");
+
+		if (Z_FPGA_LOADED(ctl_addr))
+			plx_init(pdev, irq, ctl_addr);
+
+		dev_info(&pdev->dev, "Null number of ports detected. Board "
+				"reset.\n");
+		retval = 0;
+		goto err;
+	}
+
+	cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
+	cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
+
+	/*
+	   Early firmware failed to start looking for commands.
+	   This enables firmware interrupts for those commands.
+	 */
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+			(1 << 17));
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+			0x00030800UL);
+
+	plx_init(pdev, irq, ctl_addr);
+
+	return 0;
+err_rel:
+	release_firmware(fw);
+err:
+	return retval;
 }
 
 static int __devinit cy_pci_probe(struct pci_dev *pdev,
@@ -4831,16 +5142,9 @@
 		}
 
 		/* Disable interrupts on the PLX before resetting it */
-		cy_writew(addr0 + 0x68,
-			readw(addr0 + 0x68) & ~0x0900);
+		cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900);
 
-		plx_init(addr0, 0x6c);
-		/* For some yet unknown reason, once the PLX9060 reloads
-		   the EEPROM, the IRQ is lost and, thus, we have to
-		   re-write it to the PCI config. registers.
-		   This will remain here until we find a permanent
-		   fix. */
-		pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+		plx_init(pdev, irq, addr0);
 
 		mailbox = (u32)readl(&ctl_addr->mail_box_0);
 
@@ -4881,6 +5185,9 @@
 			if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
 				cy_writel(addr2 + ID_ADDRESS, 0L);
 
+			retval = cyz_load_fw(pdev, addr2, addr0, irq);
+			if (retval)
+				goto err_unmap;
 			/* This must be a Cyclades-8Zo/PCI.  The extendable
 			   version will have a different device_id and will
 			   be allocated its maximum number of ports. */
@@ -4957,15 +5264,7 @@
 		case PLX_9060:
 		case PLX_9080:
 		default:	/* Old boards, use PLX_9060 */
-
-			plx_init(addr0, 0x6c);
-		/* For some yet unknown reason, once the PLX9060 reloads
-		   the EEPROM, the IRQ is lost and, thus, we have to
-		   re-write it to the PCI config. registers.
-		   This will remain here until we find a permanent
-		   fix. */
-			pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
-
+			plx_init(pdev, irq, addr0);
 			cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
 			break;
 		}
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 5b91bc0..3345641 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -73,9 +73,9 @@
 	free_pages((unsigned long)address, order);
 }
 
-int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
 {
-	drm_sg_mem_t *entry = dev->sg;
+	struct drm_sg_mem *entry = dev->sg;
 	unsigned long pages;
 	int i;
 	int order;
@@ -122,9 +122,9 @@
 }
 EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
 
-int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
 {
-	drm_sg_mem_t *entry = dev->sg;
+	struct drm_sg_mem *entry = dev->sg;
 	void *address = NULL;
 	unsigned long pages;
 	u32 *pci_gart, page_base, bus_address = 0;
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 0891984..2d6f2d0 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -109,31 +109,31 @@
  * \note KW: Actually it's illegal to change either for
  * backwards-compatibility reasons.
  */
-typedef struct drm_clip_rect {
+struct drm_clip_rect {
 	unsigned short x1;
 	unsigned short y1;
 	unsigned short x2;
 	unsigned short y2;
-} drm_clip_rect_t;
+};
 
 /**
  * Drawable information.
  */
-typedef struct drm_drawable_info {
+struct drm_drawable_info {
 	unsigned int num_rects;
-	drm_clip_rect_t *rects;
-} drm_drawable_info_t;
+	struct drm_clip_rect *rects;
+};
 
 /**
  * Texture region,
  */
-typedef struct drm_tex_region {
+struct drm_tex_region {
 	unsigned char next;
 	unsigned char prev;
 	unsigned char in_use;
 	unsigned char padding;
 	unsigned int age;
-} drm_tex_region_t;
+};
 
 /**
  * Hardware lock.
@@ -142,17 +142,17 @@
  * processor bus contention on a multiprocessor system, there should not be any
  * other data stored in the same cache line.
  */
-typedef struct drm_hw_lock {
+struct drm_hw_lock {
 	__volatile__ unsigned int lock;		/**< lock variable */
 	char padding[60];			/**< Pad to cache line */
-} drm_hw_lock_t;
+};
 
 /**
  * DRM_IOCTL_VERSION ioctl argument type.
  *
  * \sa drmGetVersion().
  */
-typedef struct drm_version {
+struct drm_version {
 	int version_major;	  /**< Major version */
 	int version_minor;	  /**< Minor version */
 	int version_patchlevel;	  /**< Patch level */
@@ -162,33 +162,33 @@
 	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 */
-} drm_version_t;
+};
 
 /**
  * DRM_IOCTL_GET_UNIQUE ioctl argument type.
  *
  * \sa drmGetBusid() and drmSetBusId().
  */
-typedef struct drm_unique {
+struct drm_unique {
 	size_t unique_len;	  /**< Length of unique */
 	char __user *unique;	  /**< Unique name for driver instantiation */
-} drm_unique_t;
+};
 
-typedef struct drm_list {
+struct drm_list {
 	int count;		  /**< Length of user-space structures */
-	drm_version_t __user *version;
-} drm_list_t;
+	struct drm_version __user *version;
+};
 
-typedef struct drm_block {
+struct drm_block {
 	int unused;
-} drm_block_t;
+};
 
 /**
  * DRM_IOCTL_CONTROL ioctl argument type.
  *
  * \sa drmCtlInstHandler() and drmCtlUninstHandler().
  */
-typedef struct drm_control {
+struct drm_control {
 	enum {
 		DRM_ADD_COMMAND,
 		DRM_RM_COMMAND,
@@ -196,24 +196,24 @@
 		DRM_UNINST_HANDLER
 	} func;
 	int irq;
-} drm_control_t;
+};
 
 /**
  * Type of memory to map.
  */
-typedef enum drm_map_type {
+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_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
 	_DRM_CONSISTENT = 5,	  /**< Consistent memory for PCI DMA */
-} drm_map_type_t;
+};
 
 /**
  * Memory mapping flags.
  */
-typedef enum drm_map_flags {
+enum drm_map_flags {
 	_DRM_RESTRICTED = 0x01,	     /**< Cannot be mapped to user-virtual */
 	_DRM_READ_ONLY = 0x02,
 	_DRM_LOCKED = 0x04,	     /**< shared, cached, locked */
@@ -221,12 +221,12 @@
 	_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
 	_DRM_CONTAINS_LOCK = 0x20,   /**< SHM page that contains lock */
 	_DRM_REMOVABLE = 0x40	     /**< Removable mapping */
-} drm_map_flags_t;
+};
 
-typedef struct drm_ctx_priv_map {
+struct drm_ctx_priv_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
@@ -234,30 +234,30 @@
  *
  * \sa drmAddMap().
  */
-typedef struct drm_map {
+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 */
-	drm_map_flags_t flags;	 /**< Flags */
+	enum drm_map_type type;	 /**< Type of memory to map */
+	enum drm_map_flags flags;	 /**< Flags */
 	void *handle;		 /**< User-space: "Handle" to pass to mmap() */
 				 /**< Kernel-space: kernel-virtual address */
 	int mtrr;		 /**< MTRR slot used */
 	/*   Private data */
-} drm_map_t;
+};
 
 /**
  * DRM_IOCTL_GET_CLIENT ioctl argument type.
  */
-typedef struct drm_client {
+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 */
-} drm_client_t;
+};
 
-typedef enum {
+enum drm_stat_type {
 	_DRM_STAT_LOCK,
 	_DRM_STAT_OPENS,
 	_DRM_STAT_CLOSES,
@@ -275,23 +275,23 @@
 	_DRM_STAT_SPECIAL,	/**< Special DMA (e.g., priority or polled) */
 	_DRM_STAT_MISSED	/**< Missed DMA opportunity */
 	    /* Add to the *END* of the list */
-} drm_stat_type_t;
+};
 
 /**
  * DRM_IOCTL_GET_STATS ioctl argument type.
  */
-typedef struct drm_stats {
+struct drm_stats {
 	unsigned long count;
 	struct {
 		unsigned long value;
-		drm_stat_type_t type;
+		enum drm_stat_type type;
 	} data[15];
-} drm_stats_t;
+};
 
 /**
  * Hardware locking flags.
  */
-typedef enum drm_lock_flags {
+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 */
@@ -301,17 +301,17 @@
 	   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 {
+struct drm_lock {
 	int context;
-	drm_lock_flags_t flags;
-} drm_lock_t;
+	enum drm_lock_flags flags;
+};
 
 /**
  * DMA flags
@@ -321,7 +321,7 @@
  *
  * \sa drm_dma.
  */
-typedef enum drm_dma_flags {
+enum drm_dma_flags {
 	/* Flags for DMA buffer dispatch */
 	_DRM_DMA_BLOCK = 0x01,	      /**<
 				       * Block until buffer dispatched.
@@ -340,14 +340,14 @@
 	_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 {
+struct drm_buf_desc {
 	int count;		 /**< Number of buffers of this size */
 	int size;		 /**< Size in bytes */
 	int low_mark;		 /**< Low water mark */
@@ -363,44 +363,44 @@
 				  * 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 {
+struct drm_buf_info {
 	int count;		/**< Entries in list */
-	drm_buf_desc_t __user *list;
-} drm_buf_info_t;
+	struct drm_buf_desc __user *list;
+};
 
 /**
  * DRM_IOCTL_FREE_BUFS ioctl argument type.
  */
-typedef struct drm_buf_free {
+struct drm_buf_free {
 	int count;
 	int __user *list;
-} drm_buf_free_t;
+};
 
 /**
  * Buffer information
  *
  * \sa drm_buf_map.
  */
-typedef struct drm_buf_pub {
+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 */
-} drm_buf_pub_t;
+};
 
 /**
  * DRM_IOCTL_MAP_BUFS ioctl argument type.
  */
-typedef struct drm_buf_map {
+struct drm_buf_map {
 	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;
+	struct drm_buf_pub __user *list;	/**< Buffer information */
+};
 
 /**
  * DRM_IOCTL_DMA ioctl argument type.
@@ -409,48 +409,48 @@
  *
  * \sa drmDMA().
  */
-typedef struct drm_dma {
+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 */
-	drm_dma_flags_t flags;		  /**< Flags */
+	enum drm_dma_flags 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 */
-} drm_dma_t;
+};
 
-typedef enum {
+enum drm_ctx_flags {
 	_DRM_CONTEXT_PRESERVED = 0x01,
 	_DRM_CONTEXT_2DONLY = 0x02
-} drm_ctx_flags_t;
+};
 
 /**
  * DRM_IOCTL_ADD_CTX ioctl argument type.
  *
  * \sa drmCreateContext() and drmDestroyContext().
  */
-typedef struct drm_ctx {
+struct drm_ctx {
 	drm_context_t handle;
-	drm_ctx_flags_t flags;
-} drm_ctx_t;
+	enum drm_ctx_flags flags;
+};
 
 /**
  * DRM_IOCTL_RES_CTX ioctl argument type.
  */
-typedef struct drm_ctx_res {
+struct drm_ctx_res {
 	int count;
-	drm_ctx_t __user *contexts;
-} drm_ctx_res_t;
+	struct drm_ctx __user *contexts;
+};
 
 /**
  * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
  */
-typedef struct drm_draw {
+struct drm_draw {
 	drm_drawable_t handle;
-} drm_draw_t;
+};
 
 /**
  * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
@@ -459,52 +459,52 @@
 	DRM_DRAWABLE_CLIPRECTS,
 } drm_drawable_info_type_t;
 
-typedef struct drm_update_draw {
+struct drm_update_draw {
 	drm_drawable_t handle;
 	unsigned int type;
 	unsigned int num;
 	unsigned long long data;
-} drm_update_draw_t;
+};
 
 /**
  * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
  */
-typedef struct drm_auth {
+struct drm_auth {
 	drm_magic_t magic;
-} drm_auth_t;
+};
 
 /**
  * DRM_IOCTL_IRQ_BUSID ioctl argument type.
  *
  * \sa drmGetInterruptFromBusID().
  */
-typedef struct drm_irq_busid {
+struct drm_irq_busid {
 	int irq;	/**< IRQ number */
 	int busnum;	/**< bus number */
 	int devnum;	/**< device number */
 	int funcnum;	/**< function number */
-} drm_irq_busid_t;
+};
 
-typedef enum {
+enum drm_vblank_seq_type {
 	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
 	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
 	_DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
 	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
 	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking */
-} drm_vblank_seq_type_t;
+};
 
 #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
 #define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
 				_DRM_VBLANK_NEXTONMISS)
 
 struct drm_wait_vblank_request {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	unsigned long signal;
 };
 
 struct drm_wait_vblank_reply {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	long tval_sec;
 	long tval_usec;
@@ -515,41 +515,41 @@
  *
  * \sa drmWaitVBlank().
  */
-typedef union drm_wait_vblank {
+union drm_wait_vblank {
 	struct drm_wait_vblank_request request;
 	struct drm_wait_vblank_reply reply;
-} drm_wait_vblank_t;
+};
 
 /**
  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
  *
  * \sa drmAgpEnable().
  */
-typedef struct drm_agp_mode {
+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.
  *
  * \sa drmAgpAlloc() and drmAgpFree().
  */
-typedef struct drm_agp_buffer {
+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 */
-} 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 {
+struct drm_agp_binding {
 	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.
@@ -558,7 +558,7 @@
  * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
  * drmAgpVendorId() and drmAgpDeviceId().
  */
-typedef struct drm_agp_info {
+struct drm_agp_info {
 	int agp_version_major;
 	int agp_version_minor;
 	unsigned long mode;
@@ -570,25 +570,25 @@
 	/* PCI information */
 	unsigned short id_vendor;
 	unsigned short id_device;
-} drm_agp_info_t;
+};
 
 /**
  * DRM_IOCTL_SG_ALLOC ioctl argument type.
  */
-typedef struct drm_scatter_gather {
+struct drm_scatter_gather {
 	unsigned long size;	/**< In bytes -- will round to page boundary */
 	unsigned long handle;	/**< Used for mapping / unmapping */
-} drm_scatter_gather_t;
+};
 
 /**
  * DRM_IOCTL_SET_VERSION ioctl argument type.
  */
-typedef struct drm_set_version {
+struct drm_set_version {
 	int drm_di_major;
 	int drm_di_minor;
 	int drm_dd_major;
 	int drm_dd_minor;
-} drm_set_version_t;
+};
 
 #define DRM_IOCTL_BASE			'd'
 #define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
@@ -596,61 +596,61 @@
 #define DRM_IOW(nr,type)		_IOW(DRM_IOCTL_BASE,nr,type)
 #define DRM_IOWR(nr,type)		_IOWR(DRM_IOCTL_BASE,nr,type)
 
-#define DRM_IOCTL_VERSION		DRM_IOWR(0x00, drm_version_t)
-#define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, drm_unique_t)
-#define DRM_IOCTL_GET_MAGIC		DRM_IOR( 0x02, drm_auth_t)
-#define DRM_IOCTL_IRQ_BUSID		DRM_IOWR(0x03, drm_irq_busid_t)
-#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
-#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
-#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
-#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, drm_set_version_t)
+#define DRM_IOCTL_VERSION		DRM_IOWR(0x00, struct drm_version)
+#define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, struct drm_unique)
+#define DRM_IOCTL_GET_MAGIC		DRM_IOR( 0x02, struct drm_auth)
+#define DRM_IOCTL_IRQ_BUSID		DRM_IOWR(0x03, struct drm_irq_busid)
+#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, struct drm_map)
+#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
+#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
+#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)
 
-#define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, drm_unique_t)
-#define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, drm_auth_t)
-#define DRM_IOCTL_BLOCK			DRM_IOWR(0x12, drm_block_t)
-#define DRM_IOCTL_UNBLOCK		DRM_IOWR(0x13, drm_block_t)
-#define DRM_IOCTL_CONTROL		DRM_IOW( 0x14, drm_control_t)
-#define DRM_IOCTL_ADD_MAP		DRM_IOWR(0x15, drm_map_t)
-#define DRM_IOCTL_ADD_BUFS		DRM_IOWR(0x16, drm_buf_desc_t)
-#define DRM_IOCTL_MARK_BUFS		DRM_IOW( 0x17, drm_buf_desc_t)
-#define DRM_IOCTL_INFO_BUFS		DRM_IOWR(0x18, drm_buf_info_t)
-#define DRM_IOCTL_MAP_BUFS		DRM_IOWR(0x19, drm_buf_map_t)
-#define DRM_IOCTL_FREE_BUFS		DRM_IOW( 0x1a, drm_buf_free_t)
+#define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, struct drm_unique)
+#define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, struct drm_auth)
+#define DRM_IOCTL_BLOCK			DRM_IOWR(0x12, struct drm_block)
+#define DRM_IOCTL_UNBLOCK		DRM_IOWR(0x13, struct drm_block)
+#define DRM_IOCTL_CONTROL		DRM_IOW( 0x14, struct drm_control)
+#define DRM_IOCTL_ADD_MAP		DRM_IOWR(0x15, struct drm_map)
+#define DRM_IOCTL_ADD_BUFS		DRM_IOWR(0x16, struct drm_buf_desc)
+#define DRM_IOCTL_MARK_BUFS		DRM_IOW( 0x17, struct drm_buf_desc)
+#define DRM_IOCTL_INFO_BUFS		DRM_IOWR(0x18, struct drm_buf_info)
+#define DRM_IOCTL_MAP_BUFS		DRM_IOWR(0x19, struct drm_buf_map)
+#define DRM_IOCTL_FREE_BUFS		DRM_IOW( 0x1a, struct drm_buf_free)
 
-#define DRM_IOCTL_RM_MAP		DRM_IOW( 0x1b, drm_map_t)
+#define DRM_IOCTL_RM_MAP		DRM_IOW( 0x1b, struct drm_map)
 
-#define DRM_IOCTL_SET_SAREA_CTX		DRM_IOW( 0x1c, drm_ctx_priv_map_t)
-#define DRM_IOCTL_GET_SAREA_CTX 	DRM_IOWR(0x1d, drm_ctx_priv_map_t)
+#define DRM_IOCTL_SET_SAREA_CTX		DRM_IOW( 0x1c, struct drm_ctx_priv_map)
+#define DRM_IOCTL_GET_SAREA_CTX 	DRM_IOWR(0x1d, struct drm_ctx_priv_map)
 
-#define DRM_IOCTL_ADD_CTX		DRM_IOWR(0x20, drm_ctx_t)
-#define DRM_IOCTL_RM_CTX		DRM_IOWR(0x21, drm_ctx_t)
-#define DRM_IOCTL_MOD_CTX		DRM_IOW( 0x22, drm_ctx_t)
-#define DRM_IOCTL_GET_CTX		DRM_IOWR(0x23, drm_ctx_t)
-#define DRM_IOCTL_SWITCH_CTX		DRM_IOW( 0x24, drm_ctx_t)
-#define DRM_IOCTL_NEW_CTX		DRM_IOW( 0x25, drm_ctx_t)
-#define DRM_IOCTL_RES_CTX		DRM_IOWR(0x26, drm_ctx_res_t)
-#define DRM_IOCTL_ADD_DRAW		DRM_IOWR(0x27, drm_draw_t)
-#define DRM_IOCTL_RM_DRAW		DRM_IOWR(0x28, drm_draw_t)
-#define DRM_IOCTL_DMA			DRM_IOWR(0x29, drm_dma_t)
-#define DRM_IOCTL_LOCK			DRM_IOW( 0x2a, drm_lock_t)
-#define DRM_IOCTL_UNLOCK		DRM_IOW( 0x2b, drm_lock_t)
-#define DRM_IOCTL_FINISH		DRM_IOW( 0x2c, drm_lock_t)
+#define DRM_IOCTL_ADD_CTX		DRM_IOWR(0x20, struct drm_ctx)
+#define DRM_IOCTL_RM_CTX		DRM_IOWR(0x21, struct drm_ctx)
+#define DRM_IOCTL_MOD_CTX		DRM_IOW( 0x22, struct drm_ctx)
+#define DRM_IOCTL_GET_CTX		DRM_IOWR(0x23, struct drm_ctx)
+#define DRM_IOCTL_SWITCH_CTX		DRM_IOW( 0x24, struct drm_ctx)
+#define DRM_IOCTL_NEW_CTX		DRM_IOW( 0x25, struct drm_ctx)
+#define DRM_IOCTL_RES_CTX		DRM_IOWR(0x26, struct drm_ctx_res)
+#define DRM_IOCTL_ADD_DRAW		DRM_IOWR(0x27, struct drm_draw)
+#define DRM_IOCTL_RM_DRAW		DRM_IOWR(0x28, struct drm_draw)
+#define DRM_IOCTL_DMA			DRM_IOWR(0x29, struct drm_dma)
+#define DRM_IOCTL_LOCK			DRM_IOW( 0x2a, struct drm_lock)
+#define DRM_IOCTL_UNLOCK		DRM_IOW( 0x2b, struct drm_lock)
+#define DRM_IOCTL_FINISH		DRM_IOW( 0x2c, struct drm_lock)
 
 #define DRM_IOCTL_AGP_ACQUIRE		DRM_IO(  0x30)
 #define DRM_IOCTL_AGP_RELEASE		DRM_IO(  0x31)
-#define DRM_IOCTL_AGP_ENABLE		DRM_IOW( 0x32, drm_agp_mode_t)
-#define DRM_IOCTL_AGP_INFO		DRM_IOR( 0x33, drm_agp_info_t)
-#define DRM_IOCTL_AGP_ALLOC		DRM_IOWR(0x34, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_FREE		DRM_IOW( 0x35, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_BIND		DRM_IOW( 0x36, drm_agp_binding_t)
-#define DRM_IOCTL_AGP_UNBIND		DRM_IOW( 0x37, drm_agp_binding_t)
+#define DRM_IOCTL_AGP_ENABLE		DRM_IOW( 0x32, struct drm_agp_mode)
+#define DRM_IOCTL_AGP_INFO		DRM_IOR( 0x33, struct drm_agp_info)
+#define DRM_IOCTL_AGP_ALLOC		DRM_IOWR(0x34, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_FREE		DRM_IOW( 0x35, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_BIND		DRM_IOW( 0x36, struct drm_agp_binding)
+#define DRM_IOCTL_AGP_UNBIND		DRM_IOW( 0x37, struct drm_agp_binding)
 
-#define DRM_IOCTL_SG_ALLOC		DRM_IOW( 0x38, drm_scatter_gather_t)
-#define DRM_IOCTL_SG_FREE		DRM_IOW( 0x39, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_ALLOC		DRM_IOW( 0x38, struct drm_scatter_gather)
+#define DRM_IOCTL_SG_FREE		DRM_IOW( 0x39, struct drm_scatter_gather)
 
-#define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, drm_wait_vblank_t)
+#define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, union drm_wait_vblank)
 
-#define DRM_IOCTL_UPDATE_DRAW		DRM_IOW(0x3f, drm_update_draw_t)
+#define DRM_IOCTL_UPDATE_DRAW		DRM_IOW(0x3f, struct drm_update_draw)
 
 /**
  * Device specific ioctls should only be in their respective headers
@@ -663,4 +663,49 @@
 #define DRM_COMMAND_BASE                0x40
 #define DRM_COMMAND_END			0xA0
 
+/* typedef area */
+#ifndef __KERNEL__
+typedef struct drm_clip_rect drm_clip_rect_t;
+typedef struct drm_drawable_info drm_drawable_info_t;
+typedef struct drm_tex_region drm_tex_region_t;
+typedef struct drm_hw_lock drm_hw_lock_t;
+typedef struct drm_version drm_version_t;
+typedef struct drm_unique drm_unique_t;
+typedef struct drm_list drm_list_t;
+typedef struct drm_block drm_block_t;
+typedef struct drm_control drm_control_t;
+typedef enum drm_map_type drm_map_type_t;
+typedef enum drm_map_flags drm_map_flags_t;
+typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
+typedef struct drm_map drm_map_t;
+typedef struct drm_client drm_client_t;
+typedef enum drm_stat_type drm_stat_type_t;
+typedef struct drm_stats drm_stats_t;
+typedef enum drm_lock_flags drm_lock_flags_t;
+typedef struct drm_lock drm_lock_t;
+typedef enum drm_dma_flags drm_dma_flags_t;
+typedef struct drm_buf_desc drm_buf_desc_t;
+typedef struct drm_buf_info drm_buf_info_t;
+typedef struct drm_buf_free drm_buf_free_t;
+typedef struct drm_buf_pub drm_buf_pub_t;
+typedef struct drm_buf_map drm_buf_map_t;
+typedef struct drm_dma drm_dma_t;
+typedef union drm_wait_vblank drm_wait_vblank_t;
+typedef struct drm_agp_mode drm_agp_mode_t;
+typedef enum drm_ctx_flags drm_ctx_flags_t;
+typedef struct drm_ctx drm_ctx_t;
+typedef struct drm_ctx_res drm_ctx_res_t;
+typedef struct drm_draw drm_draw_t;
+typedef struct drm_update_draw drm_update_draw_t;
+typedef struct drm_auth drm_auth_t;
+typedef struct drm_irq_busid drm_irq_busid_t;
+typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
+
+typedef struct drm_agp_buffer drm_agp_buffer_t;
+typedef struct drm_agp_binding drm_agp_binding_t;
+typedef struct drm_agp_info drm_agp_info_t;
+typedef struct drm_scatter_gather drm_scatter_gather_t;
+typedef struct drm_set_version drm_set_version_t;
+#endif
+
 #endif
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index d494315..0df87fc 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -75,6 +75,8 @@
 #include <asm/pgalloc.h>
 #include "drm.h"
 
+#include <linux/idr.h>
+
 #define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
 #define __OS_HAS_MTRR (defined(CONFIG_MTRR))
 
@@ -274,32 +276,23 @@
 	int flags;
 } drm_ioctl_desc_t;
 
-typedef struct drm_devstate {
-	pid_t owner;			/**< X server pid holding x_lock */
-} drm_devstate_t;
-
-typedef struct drm_magic_entry {
-	drm_hash_item_t hash_item;
+struct drm_magic_entry {
 	struct list_head head;
+	struct drm_hash_item hash_item;
 	struct drm_file *priv;
 	struct drm_magic_entry *next;
-} drm_magic_entry_t;
+};
 
-typedef struct drm_magic_head {
-	struct drm_magic_entry *head;
-	struct drm_magic_entry *tail;
-} drm_magic_head_t;
-
-typedef struct drm_vma_entry {
+struct drm_vma_entry {
+	struct list_head head;
 	struct vm_area_struct *vma;
-	struct drm_vma_entry *next;
 	pid_t pid;
-} drm_vma_entry_t;
+};
 
 /**
  * DMA buffer.
  */
-typedef struct drm_buf {
+struct drm_buf {
 	int idx;		       /**< Index into master buflist */
 	int total;		       /**< Buffer size */
 	int order;		       /**< log-base-2(total) */
@@ -325,30 +318,30 @@
 
 	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 {
+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 */
+	struct drm_buf **bufs;		/**< List of pointers to buffers */
+	struct drm_buf **rp;			/**< Read pointer */
+	struct drm_buf **wp;			/**< Write pointer */
+	struct drm_buf **end;		/**< End pointer */
 	spinlock_t read_lock;
 	spinlock_t write_lock;
-} drm_waitlist_t;
+};
 
-typedef struct drm_freelist {
+struct drm_freelist {
 	int initialized;	       /**< Freelist in use */
 	atomic_t count;		       /**< Number of free buffers */
-	drm_buf_t *next;	       /**< End pointer */
+	struct drm_buf *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;
-} drm_freelist_t;
+};
 
 typedef struct drm_dma_handle {
 	dma_addr_t busaddr;
@@ -359,19 +352,19 @@
 /**
  * Buffer entry.  There is one of this for each buffer size order.
  */
-typedef struct drm_buf_entry {
+struct drm_buf_entry {
 	int buf_size;			/**< size */
 	int buf_count;			/**< number of buffers */
-	drm_buf_t *buflist;		/**< buffer list */
+	struct drm_buf *buflist;		/**< buffer list */
 	int seg_count;
 	int page_order;
-	drm_dma_handle_t **seglist;
+	struct drm_dma_handle **seglist;
 
-	drm_freelist_t freelist;
-} drm_buf_entry_t;
+	struct drm_freelist freelist;
+};
 
 /** File private data */
-typedef struct drm_file {
+struct drm_file {
 	int authenticated;
 	int master;
 	int minor;
@@ -379,16 +372,15 @@
 	uid_t uid;
 	drm_magic_t magic;
 	unsigned long ioctl_count;
-	struct drm_file *next;
-	struct drm_file *prev;
+	struct list_head lhead;
 	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 {
+struct drm_queue {
 	atomic_t use_count;		/**< Outstanding uses (+1) */
 	atomic_t finalization;		/**< Finalization in progress */
 	atomic_t block_count;		/**< Count of processes waiting */
@@ -401,16 +393,16 @@
 	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 */
+	enum drm_ctx_flags flags;	/**< Context preserving and 2D-only */
+	struct drm_waitlist waitlist;	/**< Pending buffers */
 	wait_queue_head_t flush_queue;	/**< Processes waiting until flush */
-} drm_queue_t;
+};
 
 /**
  * Lock data.
  */
-typedef struct drm_lock_data {
-	drm_hw_lock_t *hw_lock;		/**< Hardware lock */
+struct drm_lock_data {
+	struct drm_hw_lock *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 */
@@ -418,16 +410,16 @@
 	uint32_t kernel_waiters;
 	uint32_t user_waiters;
 	int idle_has_lock;
-} drm_lock_data_t;
+};
 
 /**
  * DMA data.
  */
-typedef struct drm_device_dma {
+struct drm_device_dma {
 
-	drm_buf_entry_t bufs[DRM_MAX_ORDER + 1];	/**< buffers, grouped by their size order */
+	struct drm_buf_entry 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 */
+	struct drm_buf **buflist;		/**< Vector of pointers into drm_device_dma::bufs */
 	int seg_count;
 	int page_count;			/**< number of pages */
 	unsigned long *pagelist;	/**< page list */
@@ -439,28 +431,27 @@
 		_DRM_DMA_USE_PCI_RO = 0x08
 	} flags;
 
-} drm_device_dma_t;
+};
 
 /**
  * AGP memory entry.  Stored as a doubly linked list.
  */
-typedef struct drm_agp_mem {
+struct drm_agp_mem {
 	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;
+	struct list_head head;
+};
 
 /**
  * AGP data.
  *
  * \sa drm_agp_init() and drm_device::agp.
  */
-typedef struct drm_agp_head {
+struct drm_agp_head {
 	DRM_AGP_KERN agp_info;		/**< AGP device information */
-	drm_agp_mem_t *memory;		/**< memory entries */
+	struct list_head memory;
 	unsigned long mode;		/**< AGP mode */
 	struct agp_bridge_data *bridge;
 	int enabled;			/**< whether the AGP bus as been enabled */
@@ -469,51 +460,51 @@
 	int agp_mtrr;
 	int cant_use_aperture;
 	unsigned long page_mask;
-} drm_agp_head_t;
+};
 
 /**
  * Scatter-gather memory.
  */
-typedef struct drm_sg_mem {
+struct drm_sg_mem {
 	unsigned long handle;
 	void *virtual;
 	int pages;
 	struct page **pagelist;
 	dma_addr_t *busaddr;
-} drm_sg_mem_t;
+};
 
-typedef struct drm_sigdata {
+struct drm_sigdata {
 	int context;
-	drm_hw_lock_t *lock;
-} drm_sigdata_t;
+	struct drm_hw_lock *lock;
+};
 
 /**
  * Mappings list
  */
-typedef struct drm_map_list {
+struct drm_map_list {
 	struct list_head head;		/**< list head */
-	drm_hash_item_t hash;
-	drm_map_t *map;			/**< mapping */
+	struct drm_hash_item hash;
+	struct drm_map *map;			/**< mapping */
 	unsigned int user_token;
-} drm_map_list_t;
+};
 
-typedef drm_map_t drm_local_map_t;
+typedef struct drm_map drm_local_map_t;
 
 /**
  * Context handle list
  */
-typedef struct drm_ctx_list {
+struct drm_ctx_list {
 	struct list_head head;		/**< list head */
 	drm_context_t handle;		/**< context handle */
-	drm_file_t *tag;		/**< associated fd private data */
-} drm_ctx_list_t;
+	struct drm_file *tag;		/**< associated fd private data */
+};
 
-typedef struct drm_vbl_sig {
+struct drm_vbl_sig {
 	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
@@ -523,19 +514,19 @@
 #define DRM_ATI_GART_PCIE 2
 #define DRM_ATI_GART_IGP 3
 
-typedef struct ati_pcigart_info {
+struct drm_ati_pcigart_info {
 	int gart_table_location;
 	int gart_reg_if;
 	void *addr;
 	dma_addr_t bus_addr;
 	drm_local_map_t mapping;
 	int table_size;
-} drm_ati_pcigart_info;
+};
 
 /*
  * Generic memory manager structs
  */
-typedef struct drm_mm_node {
+struct drm_mm_node {
 	struct list_head fl_entry;
 	struct list_head ml_entry;
 	int free;
@@ -543,12 +534,12 @@
 	unsigned long size;
 	struct drm_mm *mm;
 	void *private;
-} drm_mm_node_t;
+};
 
-typedef struct drm_mm {
+struct drm_mm {
 	struct list_head fl_entry;
 	struct list_head ml_entry;
-} drm_mm_t;
+};
 
 /**
  * DRM driver structure. This structure represent the common code for
@@ -560,21 +551,21 @@
 struct drm_driver {
 	int (*load) (struct drm_device *, unsigned long flags);
 	int (*firstopen) (struct drm_device *);
-	int (*open) (struct drm_device *, drm_file_t *);
+	int (*open) (struct drm_device *, struct drm_file *);
 	void (*preclose) (struct drm_device *, struct file * filp);
-	void (*postclose) (struct drm_device *, drm_file_t *);
+	void (*postclose) (struct drm_device *, struct drm_file *);
 	void (*lastclose) (struct drm_device *);
 	int (*unload) (struct drm_device *);
 	int (*dma_ioctl) (DRM_IOCTL_ARGS);
 	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 (*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);
-	int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
-	int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);
+	void (*kernel_context_switch_unlock) (struct drm_device *dev);
+	int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
+	int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
 	int (*dri_library_name) (struct drm_device *dev, char *buf);
 
 	/**
@@ -588,22 +579,23 @@
 	 * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
 	 * (return of 1), or may or may not be AGP (return of 2).
 	 */
-	int (*device_is_agp) (struct drm_device * dev);
+	int (*device_is_agp) (struct drm_device *dev);
 
 	/* these have to be filled in */
 
 	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);
+	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);
 	void (*reclaim_buffers_locked) (struct drm_device *dev,
 					struct file *filp);
 	void (*reclaim_buffers_idlelocked) (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);
+	unsigned long (*get_map_ofs) (struct drm_map * map);
+	unsigned long (*get_reg_ofs) (struct drm_device *dev);
+	void (*set_version) (struct drm_device *dev,
+			     struct drm_set_version *sv);
 
 	int major;
 	int minor;
@@ -625,19 +617,19 @@
  * that may contain multiple heads. Embed one per head of these in the
  * private drm_device structure.
  */
-typedef struct drm_head {
+struct drm_head {
 	int minor;			/**< Minor device number */
 	struct drm_device *dev;
 	struct proc_dir_entry *dev_root;  /**< proc directory entry */
 	dev_t device;			/**< Device number for mknod */
 	struct class_device *dev_class;
-} drm_head_t;
+};
 
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
  */
-typedef struct drm_device {
+struct drm_device {
 	char *unique;			/**< Unique identifier: e.g., busid */
 	int unique_len;			/**< Length of unique field */
 	char *devname;			/**< For /proc/interrupts */
@@ -663,35 +655,33 @@
 	/** \name Performance counters */
 	/*@{ */
 	unsigned long counters;
-	drm_stat_type_t types[15];
+	enum drm_stat_type 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_open_hash_t magiclist;	/**< magic hash table */
+	struct list_head filelist;
+	struct drm_open_hash magiclist;	/**< magic hash table */
 	struct list_head magicfree;
 	/*@} */
 
 	/** \name Memory management */
 	/*@{ */
-	drm_map_list_t *maplist;	/**< Linked list of regions */
+	struct list_head maplist;	/**< Linked list of regions */
 	int map_count;			/**< Number of mappable regions */
-	drm_open_hash_t map_hash;	/**< User token hash table for maps */
+	struct drm_open_hash map_hash;	/**< User token hash table for maps */
 
 	/** \name Context handle management */
 	/*@{ */
-	drm_ctx_list_t *ctxlist;	/**< Linked list of context handles */
+	struct list_head ctxlist;	/**< Linked list of context handles */
 	int ctx_count;			/**< Number of context handles */
 	struct mutex ctxlist_mutex;	/**< For ctxlist */
 
-	drm_map_t **context_sareas;	    /**< per-context SAREA's */
-	int max_context;
+	struct idr ctx_idr;
 
-	drm_vma_entry_t *vmalist;	/**< List of vmas (for debugging) */
-	drm_lock_data_t lock;		/**< Information on hardware lock */
+	struct list_head vmalist;	/**< List of vmas (for debugging) */
+	struct drm_lock_data lock;	/**< Information on hardware lock */
 	/*@} */
 
 	/** \name DMA queues (contexts) */
@@ -699,8 +689,8 @@
 	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 */
+	struct drm_queue **queuelist;	/**< Vector of pointers to DMA queues */
+	struct drm_device_dma *dma;		/**< Optional pointer for DMA support */
 	/*@} */
 
 	/** \name Context support */
@@ -725,8 +715,8 @@
 	atomic_t vbl_received;
 	atomic_t vbl_received2;		/**< number of secondary VBLANK interrupts */
 	spinlock_t vbl_lock;
-	drm_vbl_sig_t vbl_sigs;		/**< signal list to send on VBLANK */
-	drm_vbl_sig_t vbl_sigs2;	/**< signals to send on secondary VBLANK */
+	struct list_head vbl_sigs;		/**< signal list to send on VBLANK */
+	struct list_head vbl_sigs2;	/**< signals to send on secondary VBLANK */
 	unsigned int vbl_pending;
 	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */
 	void (*locked_tasklet_func)(struct drm_device *dev);
@@ -739,7 +729,7 @@
 	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 */
+	struct drm_agp_head *agp;	/**< AGP data */
 
 	struct pci_dev *pdev;		/**< PCI device structure */
 	int pci_vendor;			/**< PCI vendor id */
@@ -747,26 +737,23 @@
 #ifdef __alpha__
 	struct pci_controller *hose;
 #endif
-	drm_sg_mem_t *sg;	/**< Scatter gather memory */
+	struct drm_sg_mem *sg;	/**< Scatter gather memory */
 	unsigned long *ctx_bitmap;	/**< context bitmap */
 	void *dev_private;		/**< device private data */
-	drm_sigdata_t sigdata;	   /**< For block_all_signals */
+	struct drm_sigdata sigdata;	   /**< For block_all_signals */
 	sigset_t sigmask;
 
 	struct drm_driver *driver;
 	drm_local_map_t *agp_buffer_map;
 	unsigned int agp_buffer_token;
-	drm_head_t primary;		/**< primary screen head */
+	struct drm_head primary;		/**< primary screen head */
 
 	/** \name Drawable information */
 	/*@{ */
 	spinlock_t drw_lock;
-	unsigned int drw_bitfield_length;
-	u32 *drw_bitfield;
-	unsigned int drw_info_length;
-	drm_drawable_info_t **drw_info;
+	struct idr drw_idr;
 	/*@} */
-} drm_device_t;
+};
 
 static __inline__ int drm_core_check_feature(struct drm_device *dev,
 					     int feature)
@@ -838,7 +825,7 @@
 		     unsigned int cmd, unsigned long arg);
 extern long drm_compat_ioctl(struct file *filp,
 			     unsigned int cmd, unsigned long arg);
-extern int drm_lastclose(drm_device_t *dev);
+extern int drm_lastclose(struct drm_device *dev);
 
 				/* Device support (drm_fops.h) */
 extern int drm_open(struct inode *inode, struct file *filp);
@@ -857,7 +844,7 @@
 			int request, int *eof, void *data);
 extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
 
-extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
+extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *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);
@@ -896,9 +883,9 @@
 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_ctxbitmap_init(struct drm_device *dev);
+extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
+extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
 
 extern int drm_setsareactx(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg);
@@ -912,8 +899,9 @@
 		      unsigned int cmd, unsigned long arg);
 extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg);
-extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev,
+extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
 						  drm_drawable_t id);
+extern void drm_drawable_free_all(struct drm_device *dev);
 
 				/* Authentication IOCTL support (drm_auth.h) */
 extern int drm_getmagic(struct inode *inode, struct file *filp,
@@ -926,10 +914,10 @@
 		    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(drm_lock_data_t *lock_data, unsigned int context);
-extern int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context);
-extern void drm_idlelock_take(drm_lock_data_t *lock_data);
-extern void drm_idlelock_release(drm_lock_data_t *lock_data);
+extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
+extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
+extern void drm_idlelock_take(struct drm_lock_data *lock_data);
+extern void drm_idlelock_release(struct drm_lock_data *lock_data);
 
 /*
  * These are exported to drivers so that they can implement fencing using
@@ -940,15 +928,15 @@
 extern int drm_kernel_take_hw_lock(struct file *filp);
 
 				/* 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,
-		      unsigned int size, drm_map_type_t type,
-		      drm_map_flags_t flags, drm_local_map_t ** map_ptr);
+extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addmap(struct drm_device *dev, unsigned int offset,
+		      unsigned int size, enum drm_map_type type,
+		      enum drm_map_flags 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(struct drm_device *dev, drm_local_map_t * map);
+extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t * map);
 extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg);
 
@@ -963,56 +951,56 @@
 			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 unsigned long drm_get_resource_start(struct drm_device *dev,
 					    unsigned int resource);
-extern unsigned long drm_get_resource_len(drm_device_t * dev,
+extern unsigned long drm_get_resource_len(struct drm_device *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(struct drm_device *dev);
+extern void drm_dma_takedown(struct drm_device *dev);
+extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf);
+extern void drm_core_reclaim_buffers(struct drm_device *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 irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-extern int drm_irq_uninstall(drm_device_t * dev);
-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_irq_uninstall(struct drm_device *dev);
+extern void drm_driver_irq_preinstall(struct drm_device *dev);
+extern void drm_driver_irq_postinstall(struct drm_device *dev);
+extern void drm_driver_irq_uninstall(struct drm_device *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 void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*));
+extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+extern void drm_vbl_send_signals(struct drm_device *dev);
+extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
 
 				/* AGP/GART support (drm_agpsupport.h) */
-extern drm_agp_head_t *drm_agp_init(drm_device_t * dev);
-extern int drm_agp_acquire(drm_device_t * dev);
+extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+extern int drm_agp_acquire(struct drm_device *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);
+extern int drm_agp_release(struct drm_device *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);
+extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode 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);
+extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info * info);
 extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
 			      unsigned int cmd, unsigned long arg);
-extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
 extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg);
-extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
 extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
-extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
 extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg);
-extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
 extern int drm_agp_bind_ioctl(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,
@@ -1024,16 +1012,18 @@
 				/* Stub support (drm_stub.h) */
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 		       struct drm_driver *driver);
-extern int drm_put_dev(drm_device_t * dev);
-extern int drm_put_head(drm_head_t * head);
+extern int drm_put_dev(struct drm_device *dev);
+extern int drm_put_head(struct drm_head *head);
 extern unsigned int drm_debug;
 extern unsigned int drm_cards_limit;
-extern drm_head_t **drm_heads;
+extern struct drm_head **drm_heads;
 extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
+extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
+
 				/* Proc support (drm_proc.h) */
-extern int drm_proc_init(drm_device_t * dev,
+extern int drm_proc_init(struct drm_device *dev,
 			 int minor,
 			 struct proc_dir_entry *root,
 			 struct proc_dir_entry **dev_root);
@@ -1042,45 +1032,45 @@
 			    struct proc_dir_entry *dev_root);
 
 				/* Scatter Gather Support (drm_scatter.h) */
-extern void drm_sg_cleanup(drm_sg_mem_t * entry);
+extern void drm_sg_cleanup(struct drm_sg_mem * 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,
-				drm_ati_pcigart_info * gart_info);
-extern int drm_ati_pcigart_cleanup(drm_device_t * dev,
-				   drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_init(struct drm_device *dev,
+				struct drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_cleanup(struct drm_device *dev,
+				   struct drm_ati_pcigart_info * gart_info);
 
-extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
+extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *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(struct drm_device *dev, drm_dma_handle_t * dmah);
+extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 
 			       /* sysfs support (drm_sysfs.c) */
 extern struct class *drm_sysfs_create(struct module *owner, char *name);
 extern void drm_sysfs_destroy(struct class *cs);
 extern struct class_device *drm_sysfs_device_add(struct class *cs,
-						 drm_head_t *head);
+						 struct drm_head *head);
 extern void drm_sysfs_device_remove(struct class_device *class_dev);
 
 /*
  * Basic memory manager support (drm_mm.c)
  */
-extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+extern struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
 				       unsigned long size,
 				       unsigned alignment);
-void drm_mm_put_block(drm_mm_node_t * cur);
-extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size,
+void drm_mm_put_block(struct drm_mm_node * cur);
+extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size,
 					 unsigned alignment, int best_match);
-extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
-extern void drm_mm_takedown(drm_mm_t *mm);
-extern int drm_mm_clean(drm_mm_t *mm);
-extern unsigned long drm_mm_tail_space(drm_mm_t *mm);
-extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size);
-extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size);
+extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size);
+extern void drm_mm_takedown(struct drm_mm *mm);
+extern int drm_mm_clean(struct drm_mm *mm);
+extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
+extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
+extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
 
 extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
 extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
@@ -1088,14 +1078,14 @@
 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)
+	struct drm_map_list *_entry;
+	list_for_each_entry(_entry, &dev->maplist, head)
 	    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(struct drm_device *dev)
 {
 	if (dev->driver->device_is_agp != NULL) {
 		int err = (*dev->driver->device_is_agp) (dev);
@@ -1108,7 +1098,7 @@
 	return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
 
-static __inline__ int drm_device_is_pcie(drm_device_t * dev)
+static __inline__ int drm_device_is_pcie(struct drm_device *dev)
 {
 	return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
 }
@@ -1143,7 +1133,7 @@
 
 /*@}*/
 
-extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
+extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
 extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
 
 #endif				/* __KERNEL__ */
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index 40bfd9b..354f0e3 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -48,7 +48,7 @@
  * 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(struct drm_device *dev, struct drm_agp_info *info)
 {
 	DRM_AGP_KERN *kern;
 
@@ -74,16 +74,16 @@
 int drm_agp_info_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_agp_info_t info;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_info info;
 	int err;
 
 	err = drm_agp_info(dev, &info);
 	if (err)
 		return err;
 
-	if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
+	if (copy_to_user((struct drm_agp_info __user *) arg, &info, sizeof(info)))
 		return -EFAULT;
 	return 0;
 }
@@ -97,7 +97,7 @@
  * 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(struct drm_device * dev)
 {
 	if (!dev->agp)
 		return -ENODEV;
@@ -126,9 +126,9 @@
 int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
+	struct drm_file *priv = filp->private_data;
 
-	return drm_agp_acquire((drm_device_t *) priv->head->dev);
+	return drm_agp_acquire((struct drm_device *) priv->head->dev);
 }
 
 /**
@@ -139,7 +139,7 @@
  *
  * 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(struct drm_device * dev)
 {
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
@@ -152,8 +152,8 @@
 int drm_agp_release_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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	return drm_agp_release(dev);
 }
@@ -168,7 +168,7 @@
  * 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(struct drm_device * dev, struct drm_agp_mode mode)
 {
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
@@ -185,11 +185,11 @@
 int drm_agp_enable_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_agp_mode_t mode;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_mode mode;
 
-	if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
+	if (copy_from_user(&mode, (struct drm_agp_mode __user *) arg, sizeof(mode)))
 		return -EFAULT;
 
 	return drm_agp_enable(dev, mode);
@@ -207,9 +207,9 @@
  * 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(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 	DRM_AGP_MEM *memory;
 	unsigned long pages;
 	u32 type;
@@ -232,11 +232,7 @@
 	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;
+	list_add(&entry->head, &dev->agp->memory);
 
 	request->handle = entry->handle;
 	request->physical = memory->physical;
@@ -248,10 +244,10 @@
 int drm_agp_alloc_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_agp_buffer_t request;
-	drm_agp_buffer_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_buffer request;
+	struct drm_agp_buffer __user *argp = (void __user *)arg;
 	int err;
 
 	if (copy_from_user(&request, argp, sizeof(request)))
@@ -262,10 +258,12 @@
 		return err;
 
 	if (copy_to_user(argp, &request, sizeof(request))) {
-		drm_agp_mem_t *entry = dev->agp->memory;
-
-		dev->agp->memory = entry->next;
-		dev->agp->memory->prev = NULL;
+		struct drm_agp_mem *entry;
+		list_for_each_entry(entry, &dev->agp->memory, head) {
+			if (entry->handle == request.handle)
+				break;
+		}
+		list_del(&entry->head);
 		drm_free_agp(entry->memory, entry->pages);
 		drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
 		return -EFAULT;
@@ -283,12 +281,12 @@
  *
  * Walks through drm_agp_head::memory until finding a matching handle.
  */
-static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
+static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
 					   unsigned long handle)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 
-	for (entry = dev->agp->memory; entry; entry = entry->next) {
+	list_for_each_entry(entry, &dev->agp->memory, head) {
 		if (entry->handle == handle)
 			return entry;
 	}
@@ -307,9 +305,9 @@
  * Verifies the AGP device is present and acquired, looks-up the AGP memory
  * entry and passes it to the unbind_agp() function.
  */
-int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 	int ret;
 
 	if (!dev->agp || !dev->agp->acquired)
@@ -328,12 +326,12 @@
 int drm_agp_unbind_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_agp_binding_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_binding request;
 
 	if (copy_from_user
-	    (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+	    (&request, (struct drm_agp_binding __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	return drm_agp_unbind(dev, &request);
@@ -352,9 +350,9 @@
  * is currently bound into the GATT. Looks-up the AGP memory entry and passes
  * it to bind_agp() function.
  */
-int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 	int retcode;
 	int page;
 
@@ -377,12 +375,12 @@
 int drm_agp_bind_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_agp_binding_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_binding request;
 
 	if (copy_from_user
-	    (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+	    (&request, (struct drm_agp_binding __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	return drm_agp_bind(dev, &request);
@@ -402,9 +400,9 @@
  * unbind_agp(). Frees it via free_agp() as well as the entry itself
  * and unlinks from the doubly linked list it's inserted in.
  */
-int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
@@ -413,13 +411,7 @@
 	if (entry->bound)
 		drm_unbind_agp(entry->memory);
 
-	if (entry->prev)
-		entry->prev->next = entry->next;
-	else
-		dev->agp->memory = entry->next;
-
-	if (entry->next)
-		entry->next->prev = entry->prev;
+	list_del(&entry->head);
 
 	drm_free_agp(entry->memory, entry->pages);
 	drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
@@ -430,12 +422,12 @@
 int drm_agp_free_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_agp_buffer_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_buffer request;
 
 	if (copy_from_user
-	    (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
+	    (&request, (struct drm_agp_buffer __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	return drm_agp_free(dev, &request);
@@ -450,9 +442,9 @@
  * via the inter_module_* functions. Creates and initializes a drm_agp_head
  * structure.
  */
-drm_agp_head_t *drm_agp_init(drm_device_t * dev)
+struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 {
-	drm_agp_head_t *head = NULL;
+	struct drm_agp_head *head = NULL;
 
 	if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
 		return NULL;
@@ -472,7 +464,7 @@
 		drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
 		return NULL;
 	}
-	head->memory = NULL;
+	INIT_LIST_HEAD(&head->memory);
 	head->cant_use_aperture = head->agp_info.cant_use_aperture;
 	head->page_mask = head->agp_info.page_mask;
 
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index c7b19d3..7f777da 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -45,15 +45,15 @@
  * the one with matching magic number, while holding the drm_device::struct_mutex
  * lock.
  */
-static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
 {
-	drm_file_t *retval = NULL;
-	drm_magic_entry_t *pt;
-	drm_hash_item_t *hash;
+	struct drm_file *retval = NULL;
+	struct drm_magic_entry *pt;
+	struct drm_hash_item *hash;
 
 	mutex_lock(&dev->struct_mutex);
 	if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
-		pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+		pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
 		retval = pt->priv;
 	}
 	mutex_unlock(&dev->struct_mutex);
@@ -71,10 +71,10 @@
  * associated the magic number hash key in drm_device::magiclist, while holding
  * the drm_device::struct_mutex lock.
  */
-static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
+static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
 			 drm_magic_t magic)
 {
-	drm_magic_entry_t *entry;
+	struct drm_magic_entry *entry;
 
 	DRM_DEBUG("%d\n", magic);
 
@@ -102,10 +102,10 @@
  * Searches and unlinks the entry in drm_device::magiclist with the magic
  * number hash key, while holding the drm_device::struct_mutex lock.
  */
-static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
+static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
 {
-	drm_magic_entry_t *pt;
-	drm_hash_item_t *hash;
+	struct drm_magic_entry *pt;
+	struct drm_hash_item *hash;
 
 	DRM_DEBUG("%d\n", magic);
 
@@ -114,7 +114,7 @@
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
-	pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+	pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
 	drm_ht_remove_item(&dev->magiclist, hash);
 	list_del(&pt->head);
 	mutex_unlock(&dev->struct_mutex);
@@ -142,9 +142,9 @@
 {
 	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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_auth auth;
 
 	/* Find unique magic */
 	if (priv->magic) {
@@ -162,7 +162,7 @@
 	}
 
 	DRM_DEBUG("%u\n", auth.magic);
-	if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
+	if (copy_to_user((struct drm_auth __user *) arg, &auth, sizeof(auth)))
 		return -EFAULT;
 	return 0;
 }
@@ -181,12 +181,12 @@
 int drm_authmagic(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_auth_t auth;
-	drm_file_t *file;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_auth auth;
+	struct drm_file *file;
 
-	if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
+	if (copy_from_user(&auth, (struct drm_auth __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
index c113458..923174c 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -36,26 +36,24 @@
 #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(struct drm_device *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(struct drm_device *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,
+static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
 					     drm_local_map_t *map)
 {
-	struct list_head *list;
-
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
+	struct drm_map_list *entry;
+	list_for_each_entry(entry, &dev->maplist, head) {
 		if (entry->map && map->type == entry->map->type &&
 		    ((entry->map->offset == map->offset) ||
 		     (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
@@ -66,7 +64,7 @@
 	return NULL;
 }
 
-static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
+static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
 			  unsigned long user_token, int hashed_handle)
 {
 	int use_hashed_handle;
@@ -103,12 +101,13 @@
  * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
  * applicable and if supported by the kernel.
  */
-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)
+static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
+			   unsigned int size, enum drm_map_type type,
+			   enum drm_map_flags flags,
+			   struct drm_map_list ** maplist)
 {
-	drm_map_t *map;
-	drm_map_list_t *list;
+	struct drm_map *map;
+	struct drm_map_list *list;
 	drm_dma_handle_t *dmah;
 	unsigned long user_token;
 	int ret;
@@ -214,7 +213,7 @@
 		}
 		break;
 	case _DRM_AGP: {
-		drm_agp_mem_t *entry;
+		struct drm_agp_mem *entry;
 		int valid = 0;
 
 		if (!drm_core_has_AGP(dev)) {
@@ -237,14 +236,14 @@
 		 * skipped and we double check that dev->agp->memory is
 		 * actually set as well as being invalid before EPERM'ing
 		 */
-		for (entry = dev->agp->memory; entry; entry = entry->next) {
+		list_for_each_entry(entry, &dev->agp->memory, head) {
 			if ((map->offset >= entry->bound) &&
 			    (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
 				valid = 1;
 				break;
 			}
 		}
-		if (dev->agp->memory && !valid) {
+		if (!list_empty(&dev->agp->memory) && !valid) {
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 			return -EPERM;
 		}
@@ -289,7 +288,7 @@
 	list->map = map;
 
 	mutex_lock(&dev->struct_mutex);
-	list_add(&list->head, &dev->maplist->head);
+	list_add(&list->head, &dev->maplist);
 
 	/* Assign a 32-bit handle */
 	/* We do it here so that dev->struct_mutex protects the increment */
@@ -312,11 +311,11 @@
 	return 0;
 	}
 
-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)
+int drm_addmap(struct drm_device * dev, unsigned int offset,
+	       unsigned int size, enum drm_map_type type,
+	       enum drm_map_flags flags, drm_local_map_t ** map_ptr)
 {
-	drm_map_list_t *list;
+	struct drm_map_list *list;
 	int rc;
 
 	rc = drm_addmap_core(dev, offset, size, type, flags, &list);
@@ -330,11 +329,11 @@
 int drm_addmap_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_map_t map;
-	drm_map_list_t *maplist;
-	drm_map_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map map;
+	struct drm_map_list *maplist;
+	struct drm_map __user *argp = (void __user *)arg;
 	int err;
 
 	if (!(filp->f_mode & 3))
@@ -353,7 +352,7 @@
 	if (err)
 		return err;
 
-	if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
+	if (copy_to_user(argp, maplist->map, sizeof(struct drm_map)))
 		return -EFAULT;
 
 	/* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
@@ -369,7 +368,7 @@
  * \param inode device inode.
  * \param filp file pointer.
  * \param cmd command.
- * \param arg pointer to a drm_map_t structure.
+ * \param arg pointer to a struct drm_map structure.
  * \return zero on success or a negative value on error.
  *
  * Searches the map on drm_device::maplist, removes it from the list, see if
@@ -378,31 +377,26 @@
  *
  * \sa drm_addmap
  */
-int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
 {
-	struct list_head *list;
-	drm_map_list_t *r_list = NULL;
+	struct drm_map_list *r_list = NULL, *list_t;
 	drm_dma_handle_t dmah;
+	int found = 0;
 
 	/* Find the list entry for the map and remove it */
-	list_for_each(list, &dev->maplist->head) {
-		r_list = list_entry(list, drm_map_list_t, head);
-
+	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
 		if (r_list->map == map) {
-			list_del(list);
+			list_del(&r_list->head);
 			drm_ht_remove_key(&dev->map_hash,
 					  r_list->user_token >> PAGE_SHIFT);
-			drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+			drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+			found = 1;
 			break;
 		}
 	}
 
-	/* List has wrapped around to the head pointer, or it's empty and we
-	 * didn't find anything.
-	 */
-	if (list == (&dev->maplist->head)) {
+	if (!found)
 		return -EINVAL;
-	}
 
 	switch (map->type) {
 	case _DRM_REGISTERS:
@@ -433,7 +427,7 @@
 	return 0;
 }
 
-int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
 {
 	int ret;
 
@@ -456,21 +450,19 @@
 int drm_rmmap_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_map_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map request;
 	drm_local_map_t *map = NULL;
-	struct list_head *list;
+	struct drm_map_list *r_list;
 	int ret;
 
-	if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
+	if (copy_from_user(&request, (struct drm_map __user *) arg, sizeof(request))) {
 		return -EFAULT;
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
-
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map &&
 		    r_list->user_token == (unsigned long)request.handle &&
 		    r_list->map->flags & _DRM_REMOVABLE) {
@@ -482,7 +474,7 @@
 	/* List has wrapped around to the head pointer, or its empty we didn't
 	 * find anything.
 	 */
-	if (list == (&dev->maplist->head)) {
+	if (list_empty(&dev->maplist) || !map) {
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
@@ -513,7 +505,8 @@
  *
  * 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(struct drm_device * dev,
+				  struct drm_buf_entry * entry)
 {
 	int i;
 
@@ -550,20 +543,20 @@
 /**
  * Add AGP buffers for DMA transfers.
  *
- * \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.
+ * \param dev struct drm_device to which the buffers are to be added.
+ * \param request pointer to a struct drm_buf_desc 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(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_entry_t *entry;
-	drm_agp_mem_t *agp_entry;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_entry *entry;
+	struct drm_agp_mem *agp_entry;
+	struct drm_buf *buf;
 	unsigned long offset;
 	unsigned long agp_offset;
 	int count;
@@ -574,7 +567,7 @@
 	int total;
 	int byte_count;
 	int i, valid;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!dma)
 		return -EINVAL;
@@ -606,14 +599,14 @@
 
 	/* Make sure buffers are located in AGP memory that we own */
 	valid = 0;
-	for (agp_entry = dev->agp->memory; agp_entry; agp_entry = agp_entry->next) {
+	list_for_each_entry(agp_entry, &dev->agp->memory, head) {
 		if ((agp_offset >= agp_entry->bound) &&
 		    (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
 			valid = 1;
 			break;
 		}
 	}
-	if (dev->agp->memory && !valid) {
+	if (!list_empty(&dev->agp->memory) && !valid) {
 		DRM_DEBUG("zone invalid\n");
 		return -EINVAL;
 	}
@@ -728,24 +721,24 @@
 EXPORT_SYMBOL(drm_addbufs_agp);
 #endif				/* __OS_HAS_AGP */
 
-int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int count;
 	int order;
 	int size;
 	int total;
 	int page_order;
-	drm_buf_entry_t *entry;
+	struct drm_buf_entry *entry;
 	drm_dma_handle_t *dmah;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int alignment;
 	unsigned long offset;
 	int i;
 	int byte_count;
 	int page_count;
 	unsigned long *temp_pagelist;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
 		return -EINVAL;
@@ -954,11 +947,11 @@
 }
 EXPORT_SYMBOL(drm_addbufs_pci);
 
-static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_entry_t *entry;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_entry *entry;
+	struct drm_buf *buf;
 	unsigned long offset;
 	unsigned long agp_offset;
 	int count;
@@ -969,7 +962,7 @@
 	int total;
 	int byte_count;
 	int i;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!drm_core_check_feature(dev, DRIVER_SG))
 		return -EINVAL;
@@ -1116,11 +1109,11 @@
 	return 0;
 }
 
-static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_entry_t *entry;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_entry *entry;
+	struct drm_buf *buf;
 	unsigned long offset;
 	unsigned long agp_offset;
 	int count;
@@ -1131,7 +1124,7 @@
 	int total;
 	int byte_count;
 	int i;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
 		return -EINVAL;
@@ -1283,7 +1276,7 @@
  * \param inode device inode.
  * \param filp file pointer.
  * \param cmd command.
- * \param arg pointer to a drm_buf_desc_t request.
+ * \param arg pointer to a struct drm_buf_desc request.
  * \return zero on success or a negative number on failure.
  *
  * According with the memory type specified in drm_buf_desc::flags and the
@@ -1294,15 +1287,15 @@
 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;
+	struct drm_buf_desc request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *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,
+	if (copy_from_user(&request, (struct drm_buf_desc __user *) arg,
 			   sizeof(request)))
 		return -EFAULT;
 
@@ -1346,11 +1339,11 @@
 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;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_info_t request;
-	drm_buf_info_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_info request;
+	struct drm_buf_info __user *argp = (void __user *)arg;
 	int i;
 	int count;
 
@@ -1381,10 +1374,10 @@
 	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 =
+				struct drm_buf_desc __user *to =
 				    &request.list[count];
-				drm_buf_entry_t *from = &dma->bufs[i];
-				drm_freelist_t *list = &dma->bufs[i].freelist;
+				struct drm_buf_entry *from = &dma->bufs[i];
+				struct drm_freelist *list = &dma->bufs[i].freelist;
 				if (copy_to_user(&to->count,
 						 &from->buf_count,
 						 sizeof(from->buf_count)) ||
@@ -1434,12 +1427,12 @@
 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;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_desc_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_desc request;
 	int order;
-	drm_buf_entry_t *entry;
+	struct drm_buf_entry *entry;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 		return -EINVAL;
@@ -1448,7 +1441,7 @@
 		return -EINVAL;
 
 	if (copy_from_user(&request,
-			   (drm_buf_desc_t __user *) arg, sizeof(request)))
+			   (struct drm_buf_desc __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d, %d, %d\n",
@@ -1484,13 +1477,13 @@
 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;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_free_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_free request;
 	int i;
 	int idx;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 		return -EINVAL;
@@ -1499,7 +1492,7 @@
 		return -EINVAL;
 
 	if (copy_from_user(&request,
-			   (drm_buf_free_t __user *) arg, sizeof(request)))
+			   (struct drm_buf_free __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", request.count);
@@ -1540,15 +1533,15 @@
 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;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_map_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_map __user *argp = (void __user *)arg;
 	int retcode = 0;
 	const int zero = 0;
 	unsigned long virtual;
 	unsigned long address;
-	drm_buf_map_t request;
+	struct drm_buf_map request;
 	int i;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
@@ -1574,7 +1567,7 @@
 			&& (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;
+			struct drm_map *map = dev->agp_buffer_map;
 			unsigned long token = dev->agp_buffer_token;
 
 			if (!map) {
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index 83094c7..61ad986 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -53,26 +53,14 @@
  * \param ctx_handle context handle.
  *
  * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_mutex
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
  * lock.
  */
-void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
+void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
 {
-	if (ctx_handle < 0)
-		goto failed;
-	if (!dev->ctx_bitmap)
-		goto failed;
-
-	if (ctx_handle < DRM_MAX_CTXBITMAP) {
-		mutex_lock(&dev->struct_mutex);
-		clear_bit(ctx_handle, dev->ctx_bitmap);
-		dev->context_sareas[ctx_handle] = NULL;
-		mutex_unlock(&dev->struct_mutex);
-		return;
-	}
-      failed:
-	DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
-	return;
+	mutex_lock(&dev->struct_mutex);
+	idr_remove(&dev->ctx_idr, ctx_handle);
+	mutex_unlock(&dev->struct_mutex);
 }
 
 /**
@@ -81,62 +69,28 @@
  * \param dev DRM device.
  * \return (non-negative) context handle on success or a negative number on failure.
  *
- * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
- * drm_device::context_sareas to accommodate the new entry while holding the
+ * Allocate a new idr from drm_device::ctx_idr while holding the
  * drm_device::struct_mutex lock.
  */
-static int drm_ctxbitmap_next(drm_device_t * dev)
+static int drm_ctxbitmap_next(struct drm_device * dev)
 {
-	int bit;
+	int new_id;
+	int ret;
 
-	if (!dev->ctx_bitmap)
-		return -1;
-
+again:
+	if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+		DRM_ERROR("Out of memory expanding drawable idr\n");
+		return -ENOMEM;
+	}
 	mutex_lock(&dev->struct_mutex);
-	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) {
-					clear_bit(bit, dev->ctx_bitmap);
-					mutex_unlock(&dev->struct_mutex);
-					return -1;
-				}
-				dev->context_sareas = ctx_sareas;
-				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) {
-					clear_bit(bit, dev->ctx_bitmap);
-					mutex_unlock(&dev->struct_mutex);
-					return -1;
-				}
-				dev->context_sareas[bit] = NULL;
-			}
-		}
+	ret = idr_get_new_above(&dev->ctx_idr, NULL,
+				DRM_RESERVED_CONTEXTS, &new_id);
+	if (ret == -EAGAIN) {
 		mutex_unlock(&dev->struct_mutex);
-		return bit;
+		goto again;
 	}
 	mutex_unlock(&dev->struct_mutex);
-	return -1;
+	return new_id;
 }
 
 /**
@@ -144,31 +98,11 @@
  *
  * \param dev DRM device.
  *
- * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Initialise the drm_device::ctx_idr
  */
-int drm_ctxbitmap_init(drm_device_t * dev)
+int drm_ctxbitmap_init(struct drm_device * dev)
 {
-	int i;
-	int temp;
-
-	mutex_lock(&dev->struct_mutex);
-	dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
-						     DRM_MEM_CTXBITMAP);
-	if (dev->ctx_bitmap == NULL) {
-		mutex_unlock(&dev->struct_mutex);
-		return -ENOMEM;
-	}
-	memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
-	dev->context_sareas = NULL;
-	dev->max_context = -1;
-	mutex_unlock(&dev->struct_mutex);
-
-	for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-		temp = drm_ctxbitmap_next(dev);
-		DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
-	}
-
+	idr_init(&dev->ctx_idr);
 	return 0;
 }
 
@@ -177,17 +111,13 @@
  *
  * \param dev DRM device.
  *
- * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
  */
-void drm_ctxbitmap_cleanup(drm_device_t * dev)
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
 {
 	mutex_lock(&dev->struct_mutex);
-	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);
+	idr_remove_all(&dev->ctx_idr);
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -206,34 +136,34 @@
  * \param arg user argument pointing to a drm_ctx_priv_map structure.
  * \return zero on success or a negative number on failure.
  *
- * Gets the map from drm_device::context_sareas with the handle specified and
+ * Gets the map from drm_device::ctx_idr with the handle specified and
  * returns its handle.
  */
 int drm_getsareactx(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_priv_map_t __user *argp = (void __user *)arg;
-	drm_ctx_priv_map_t request;
-	drm_map_t *map;
-	drm_map_list_t *_entry;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx_priv_map __user *argp = (void __user *)arg;
+	struct drm_ctx_priv_map request;
+	struct drm_map *map;
+	struct drm_map_list *_entry;
 
 	if (copy_from_user(&request, argp, sizeof(request)))
 		return -EFAULT;
 
 	mutex_lock(&dev->struct_mutex);
-	if (dev->max_context < 0
-	    || request.ctx_id >= (unsigned)dev->max_context) {
+
+	map = idr_find(&dev->ctx_idr, request.ctx_id);
+	if (!map) {
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
-	map = dev->context_sareas[request.ctx_id];
 	mutex_unlock(&dev->struct_mutex);
 
 	request.handle = NULL;
-	list_for_each_entry(_entry, &dev->maplist->head, head) {
+	list_for_each_entry(_entry, &dev->maplist, head) {
 		if (_entry->map == map) {
 			request.handle =
 			    (void *)(unsigned long)_entry->user_token;
@@ -258,25 +188,24 @@
  * \return zero on success or a negative number on failure.
  *
  * Searches the mapping specified in \p arg and update the entry in
- * drm_device::context_sareas with it.
+ * drm_device::ctx_idr with it.
  */
 int drm_setsareactx(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_priv_map_t request;
-	drm_map_t *map = NULL;
-	drm_map_list_t *r_list = NULL;
-	struct list_head *list;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx_priv_map request;
+	struct drm_map *map = NULL;
+	struct drm_map_list *r_list = NULL;
 
 	if (copy_from_user(&request,
-			   (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
+			   (struct drm_ctx_priv_map __user *) arg,
+			   sizeof(request)))
 		return -EFAULT;
 
 	mutex_lock(&dev->struct_mutex);
-	list_for_each(list, &dev->maplist->head) {
-		r_list = list_entry(list, drm_map_list_t, head);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map
 		    && r_list->user_token == (unsigned long)request.handle)
 			goto found;
@@ -289,11 +218,10 @@
 	map = r_list->map;
 	if (!map)
 		goto bad;
-	if (dev->max_context < 0)
+
+	if (IS_ERR(idr_replace(&dev->ctx_idr, map, request.ctx_id)))
 		goto bad;
-	if (request.ctx_id >= (unsigned)dev->max_context)
-		goto bad;
-	dev->context_sareas[request.ctx_id] = map;
+
 	mutex_unlock(&dev->struct_mutex);
 	return 0;
 }
@@ -314,7 +242,7 @@
  *
  * 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(struct drm_device * dev, int old, int new)
 {
 	if (test_and_set_bit(0, &dev->context_flag)) {
 		DRM_ERROR("Reentering -- FIXME\n");
@@ -342,7 +270,7 @@
  * 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(struct drm_device * dev, int new)
 {
 	dev->last_context = new;	/* PRE/POST: This is the _only_ writer. */
 	dev->last_switch = jiffies;
@@ -372,9 +300,9 @@
 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;
+	struct drm_ctx_res res;
+	struct drm_ctx_res __user *argp = (void __user *)arg;
+	struct drm_ctx ctx;
 	int i;
 
 	if (copy_from_user(&res, argp, sizeof(res)))
@@ -409,11 +337,11 @@
 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_t __user *argp = (void __user *)arg;
-	drm_ctx_t ctx;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx_list *ctx_entry;
+	struct drm_ctx __user *argp = (void __user *)arg;
+	struct drm_ctx ctx;
 
 	if (copy_from_user(&ctx, argp, sizeof(ctx)))
 		return -EFAULT;
@@ -449,7 +377,7 @@
 	ctx_entry->tag = priv;
 
 	mutex_lock(&dev->ctxlist_mutex);
-	list_add(&ctx_entry->head, &dev->ctxlist->head);
+	list_add(&ctx_entry->head, &dev->ctxlist);
 	++dev->ctx_count;
 	mutex_unlock(&dev->ctxlist_mutex);
 
@@ -477,8 +405,8 @@
 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;
+	struct drm_ctx __user *argp = (void __user *)arg;
+	struct drm_ctx ctx;
 
 	if (copy_from_user(&ctx, argp, sizeof(ctx)))
 		return -EFAULT;
@@ -505,11 +433,11 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx ctx;
 
-	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+	if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", ctx.handle);
@@ -530,11 +458,11 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx ctx;
 
-	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+	if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", ctx.handle);
@@ -557,11 +485,11 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx ctx;
 
-	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+	if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", ctx.handle);
@@ -575,10 +503,10 @@
 	}
 
 	mutex_lock(&dev->ctxlist_mutex);
-	if (!list_empty(&dev->ctxlist->head)) {
-		drm_ctx_list_t *pos, *n;
+	if (!list_empty(&dev->ctxlist)) {
+		struct drm_ctx_list *pos, *n;
 
-		list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
 			if (pos->handle == ctx.handle) {
 				list_del(&pos->head);
 				drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
index 32ed19c..802fbdb 100644
--- a/drivers/char/drm/drm_dma.c
+++ b/drivers/char/drm/drm_dma.c
@@ -43,7 +43,7 @@
  *
  * Allocate and initialize a drm_device_dma structure.
  */
-int drm_dma_setup(drm_device_t * dev)
+int drm_dma_setup(struct drm_device *dev)
 {
 	int i;
 
@@ -67,9 +67,9 @@
  * Free all pages associated with DMA buffers, the buffers and pages lists, and
  * finally the drm_device::dma structure itself.
  */
-void drm_dma_takedown(drm_device_t * dev)
+void drm_dma_takedown(struct drm_device *dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i, j;
 
 	if (!dma)
@@ -129,7 +129,7 @@
  *
  * Resets the fields of \p buf.
  */
-void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
+void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
 {
 	if (!buf)
 		return;
@@ -152,9 +152,9 @@
  *
  * 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(struct drm_device *dev, struct file *filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma)
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
index b33313b..d6cdba5 100644
--- a/drivers/char/drm/drm_drawable.c
+++ b/drivers/char/drm/drm_drawable.c
@@ -44,83 +44,30 @@
 {
 	DRM_DEVICE;
 	unsigned long irqflags;
-	int i, j;
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned int bitfield_length = dev->drw_bitfield_length;
-	drm_drawable_info_t **info = dev->drw_info;
-	unsigned int info_length = dev->drw_info_length;
-	drm_draw_t draw;
+	struct drm_draw draw;
+	int new_id = 0;
+	int ret;
 
-	for (i = 0, j = 0; i < bitfield_length; i++) {
-		if (bitfield[i] == ~0)
-			continue;
-
-		for (; j < 8 * sizeof(*bitfield); j++)
-			if (!(bitfield[i] & (1 << j)))
-				goto done;
+again:
+	if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
+		DRM_ERROR("Out of memory expanding drawable idr\n");
+		return -ENOMEM;
 	}
-done:
-
-	if (i == bitfield_length) {
-		bitfield_length++;
-
-		bitfield = drm_alloc(bitfield_length * sizeof(*bitfield),
-				     DRM_MEM_BUFS);
-
-		if (!bitfield) {
-			DRM_ERROR("Failed to allocate new drawable bitfield\n");
-			return DRM_ERR(ENOMEM);
-		}
-
-		if (8 * sizeof(*bitfield) * bitfield_length > info_length) {
-			info_length += 8 * sizeof(*bitfield);
-
-			info = drm_alloc(info_length * sizeof(*info),
-					 DRM_MEM_BUFS);
-
-			if (!info) {
-				DRM_ERROR("Failed to allocate new drawable info"
-					  " array\n");
-
-				drm_free(bitfield,
-					 bitfield_length * sizeof(*bitfield),
-					 DRM_MEM_BUFS);
-				return DRM_ERR(ENOMEM);
-			}
-		}
-
-		bitfield[i] = 0;
-	}
-
-	draw.handle = i * 8 * sizeof(*bitfield) + j + 1;
-	DRM_DEBUG("%d\n", draw.handle);
 
 	spin_lock_irqsave(&dev->drw_lock, irqflags);
-
-	bitfield[i] |= 1 << j;
-	info[draw.handle - 1] = NULL;
-
-	if (bitfield != dev->drw_bitfield) {
-		memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length *
-		       sizeof(*bitfield));
-		drm_free(dev->drw_bitfield, sizeof(*bitfield) *
-			 dev->drw_bitfield_length, DRM_MEM_BUFS);
-		dev->drw_bitfield = bitfield;
-		dev->drw_bitfield_length = bitfield_length;
-	}
-
-	if (info != dev->drw_info) {
-		memcpy(info, dev->drw_info, dev->drw_info_length *
-		       sizeof(*info));
-		drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length,
-			 DRM_MEM_BUFS);
-		dev->drw_info = info;
-		dev->drw_info_length = info_length;
+	ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
+	if (ret == -EAGAIN) {
+		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+		goto again;
 	}
 
 	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
-	DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
+	draw.handle = new_id;
+
+	DRM_DEBUG("%d\n", draw.handle);
+
+	DRM_COPY_TO_USER_IOCTL((struct drm_draw __user *)data, draw, sizeof(draw));
 
 	return 0;
 }
@@ -131,141 +78,52 @@
 int drm_rmdraw(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_draw_t draw;
- 	int id, idx;
- 	unsigned int shift;
+	struct drm_draw draw;
 	unsigned long irqflags;
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned int bitfield_length = dev->drw_bitfield_length;
-	drm_drawable_info_t **info = dev->drw_info;
-	unsigned int info_length = dev->drw_info_length;
 
-	DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
+	DRM_COPY_FROM_USER_IOCTL(draw, (struct drm_draw __user *) data,
 				 sizeof(draw));
 
-	id = draw.handle - 1;
-	idx = id / (8 * sizeof(*bitfield));
-	shift = id % (8 * sizeof(*bitfield));
-
-	if (idx < 0 || idx >= bitfield_length ||
-	    !(bitfield[idx] & (1 << shift))) {
-		DRM_DEBUG("No such drawable %d\n", draw.handle);
-		return 0;
-	}
-
 	spin_lock_irqsave(&dev->drw_lock, irqflags);
 
-	bitfield[idx] &= ~(1 << shift);
+	drm_free(drm_get_drawable_info(dev, draw.handle),
+		 sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
+
+	idr_remove(&dev->drw_idr, draw.handle);
 
 	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
-	if (info[id]) {
-		drm_free(info[id]->rects, info[id]->num_rects *
-			 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
-		drm_free(info[id], sizeof(**info), DRM_MEM_BUFS);
-	}
-
-	/* Can we shrink the arrays? */
-	if (idx == bitfield_length - 1) {
-		while (idx >= 0 && !bitfield[idx])
-			--idx;
-
-		bitfield_length = idx + 1;
-
-		bitfield = NULL;
-
-		if (bitfield_length) {
-			if (bitfield_length != dev->drw_bitfield_length)
-				bitfield = drm_alloc(bitfield_length *
-						     sizeof(*bitfield),
-						     DRM_MEM_BUFS);
-
-			if (!bitfield) {
-				bitfield = dev->drw_bitfield;
-				bitfield_length = dev->drw_bitfield_length;
-			}
-		}
-	}
-
-	if (bitfield != dev->drw_bitfield) {
-		info_length = 8 * sizeof(*bitfield) * bitfield_length;
-
-		if (info_length) {
-			info = drm_alloc(info_length * sizeof(*info),
-					 DRM_MEM_BUFS);
-
-			if (!info) {
-				info = dev->drw_info;
-				info_length = dev->drw_info_length;
-			}
-		} else
-			info = NULL;
-
-		spin_lock_irqsave(&dev->drw_lock, irqflags);
-
-		if (bitfield)
-			memcpy(bitfield, dev->drw_bitfield, bitfield_length *
-			       sizeof(*bitfield));
-		drm_free(dev->drw_bitfield, sizeof(*bitfield) *
-			 dev->drw_bitfield_length, DRM_MEM_BUFS);
-		dev->drw_bitfield = bitfield;
-		dev->drw_bitfield_length = bitfield_length;
-
-		if (info != dev->drw_info) {
-			if (info)
-				memcpy(info, dev->drw_info, info_length *
-				       sizeof(*info));
-			drm_free(dev->drw_info, sizeof(*info) *
-				 dev->drw_info_length, DRM_MEM_BUFS);
-			dev->drw_info = info;
-			dev->drw_info_length = info_length;
-		}
-
-		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-	}
-
 	DRM_DEBUG("%d\n", draw.handle);
 	return 0;
 }
 
-int drm_update_drawable_info(DRM_IOCTL_ARGS) {
+int drm_update_drawable_info(DRM_IOCTL_ARGS)
+{
 	DRM_DEVICE;
-	drm_update_draw_t update;
-	unsigned int id, idx, shift;
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned long irqflags, bitfield_length = dev->drw_bitfield_length;
-	drm_drawable_info_t *info;
-	drm_clip_rect_t *rects;
+	struct drm_update_draw update;
+	unsigned long irqflags;
+	struct drm_clip_rect *rects;
+	struct drm_drawable_info *info;
 	int err;
 
-	DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
+	DRM_COPY_FROM_USER_IOCTL(update, (struct drm_update_draw __user *) data,
 				 sizeof(update));
 
-	id = update.handle - 1;
-	idx = id / (8 * sizeof(*bitfield));
-	shift = id % (8 * sizeof(*bitfield));
-
-	if (idx < 0 || idx >= bitfield_length ||
-	    !(bitfield[idx] & (1 << shift))) {
-		DRM_ERROR("No such drawable %d\n", update.handle);
-		return DRM_ERR(EINVAL);
-	}
-
-	info = dev->drw_info[id];
-
+	info = idr_find(&dev->drw_idr, update.handle);
 	if (!info) {
-		info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS);
-
-		if (!info) {
-			DRM_ERROR("Failed to allocate drawable info memory\n");
-			return DRM_ERR(ENOMEM);
+		info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
+		if (!info)
+			return -ENOMEM;
+		if (IS_ERR(idr_replace(&dev->drw_idr, info, update.handle))) {
+			DRM_ERROR("No such drawable %d\n", update.handle);
+			drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+			return -EINVAL;
 		}
 	}
 
 	switch (update.type) {
 	case DRM_DRAWABLE_CLIPRECTS:
 		if (update.num != info->num_rects) {
-			rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
+			rects = drm_alloc(update.num * sizeof(struct drm_clip_rect),
 					 DRM_MEM_BUFS);
 		} else
 			rects = info->rects;
@@ -277,7 +135,7 @@
 		}
 
 		if (update.num && DRM_COPY_FROM_USER(rects,
-						     (drm_clip_rect_t __user *)
+						     (struct drm_clip_rect __user *)
 						     (unsigned long)update.data,
 						     update.num *
 						     sizeof(*rects))) {
@@ -290,17 +148,16 @@
 
 		if (rects != info->rects) {
 			drm_free(info->rects, info->num_rects *
-				 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+				 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
 		}
 
 		info->rects = rects;
 		info->num_rects = update.num;
-		dev->drw_info[id] = info;
 
 		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
 		DRM_DEBUG("Updated %d cliprects for drawable %d\n",
-			  info->num_rects, id);
+			  info->num_rects, update.handle);
 		break;
 	default:
 		DRM_ERROR("Invalid update type %d\n", update.type);
@@ -310,11 +167,9 @@
 	return 0;
 
 error:
-	if (!dev->drw_info[id])
-		drm_free(info, sizeof(*info), DRM_MEM_BUFS);
-	else if (rects != dev->drw_info[id]->rects)
-		drm_free(rects, update.num *
-			 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+	if (rects != info->rects)
+		drm_free(rects, update.num * sizeof(struct drm_clip_rect),
+			 DRM_MEM_BUFS);
 
 	return err;
 }
@@ -322,20 +177,27 @@
 /**
  * Caller must hold the drawable spinlock!
  */
-drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned int idx, shift;
-
-	id--;
-	idx = id / (8 * sizeof(*bitfield));
-	shift = id % (8 * sizeof(*bitfield));
-
-	if (idx < 0 || idx >= dev->drw_bitfield_length ||
-	    !(bitfield[idx] & (1 << shift))) {
-		DRM_DEBUG("No such drawable %d\n", id);
-		return NULL;
-	}
-
-	return dev->drw_info[id];
+struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
+{
+	return idr_find(&dev->drw_idr, id);
 }
 EXPORT_SYMBOL(drm_get_drawable_info);
+
+static int drm_drawable_free(int idr, void *p, void *data)
+{
+	struct drm_drawable_info *info = p;
+
+	if (info) {
+		drm_free(info->rects, info->num_rects *
+			 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+		drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+	}
+
+	return 0;
+}
+
+void drm_drawable_free_all(struct drm_device *dev)
+{
+	idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
+	idr_remove_all(&dev->drw_idr);
+}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 8e77b7e..19994cd 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -129,11 +129,11 @@
  *
  * \sa drm_device
  */
-int drm_lastclose(drm_device_t * dev)
+int drm_lastclose(struct drm_device * dev)
 {
-	drm_magic_entry_t *pt, *next;
-	drm_map_list_t *r_list;
-	drm_vma_entry_t *vma, *vma_next;
+	struct drm_magic_entry *pt, *next;
+	struct drm_map_list *r_list, *list_t;
+	struct drm_vma_entry *vma, *vma_temp;
 	int i;
 
 	DRM_DEBUG("\n");
@@ -151,19 +151,10 @@
 	if (dev->irq_enabled)
 		drm_irq_uninstall(dev);
 
-	/* Free drawable information memory */
-	for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield);
-	     i++) {
-		drm_drawable_info_t *info = drm_get_drawable_info(dev, i);
-
-		if (info) {
-			drm_free(info->rects, info->num_rects *
-				 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
-			drm_free(info, sizeof(*info), DRM_MEM_BUFS);
-		}
-	}
-
 	mutex_lock(&dev->struct_mutex);
+
+	/* Free drawable information memory */
+	drm_drawable_free_all(dev);
 	del_timer(&dev->timer);
 
 	/* Clear pid list */
@@ -178,19 +169,17 @@
 
 	/* Clear AGP information */
 	if (drm_core_has_AGP(dev) && dev->agp) {
-		drm_agp_mem_t *entry;
-		drm_agp_mem_t *nexte;
+		struct drm_agp_mem *entry, *tempe;
 
 		/* Remove AGP resources, but leave dev->agp
 		   intact until drv_cleanup is called. */
-		for (entry = dev->agp->memory; entry; entry = nexte) {
-			nexte = entry->next;
+		list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
 			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;
+		INIT_LIST_HEAD(&dev->agp->memory);
 
 		if (dev->agp->acquired)
 			drm_agp_release(dev);
@@ -204,20 +193,14 @@
 	}
 
 	/* 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);
-		}
-		dev->vmalist = NULL;
+	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+		list_del(&vma->head);
+		drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
 	}
 
-	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);
-		}
+	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
+		drm_rmmap_locked(dev, r_list->map);
+		r_list = NULL;
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
@@ -298,7 +281,7 @@
  *
  * \sa drm_init
  */
-static void drm_cleanup(drm_device_t * dev)
+static void drm_cleanup(struct drm_device * dev)
 {
 	DRM_DEBUG("\n");
 
@@ -309,11 +292,7 @@
 
 	drm_lastclose(dev);
 
-	if (dev->maplist) {
-		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
-		dev->maplist = NULL;
-		drm_ht_remove(&dev->map_hash);
-	}
+	drm_ht_remove(&dev->map_hash);
 
 	drm_ctxbitmap_cleanup(dev);
 
@@ -342,8 +321,8 @@
 void drm_exit(struct drm_driver *driver)
 {
 	int i;
-	drm_device_t *dev = NULL;
-	drm_head_t *head;
+	struct drm_device *dev = NULL;
+	struct drm_head *head;
 
 	DRM_DEBUG("\n");
 
@@ -442,10 +421,10 @@
 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;
-	drm_version_t __user *argp = (void __user *)arg;
-	drm_version_t version;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_version __user *argp = (void __user *)arg;
+	struct drm_version version;
 	int len;
 
 	if (copy_from_user(&version, argp, sizeof(version)))
@@ -478,8 +457,8 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_ioctl_desc_t *ioctl;
 	drm_ioctl_t *func;
 	unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -529,3 +508,17 @@
 }
 
 EXPORT_SYMBOL(drm_ioctl);
+
+drm_local_map_t *drm_getsarea(struct drm_device *dev)
+{
+	struct drm_map_list *entry;
+
+	list_for_each_entry(entry, &dev->maplist, head) {
+		if (entry->map && entry->map->type == _DRM_SHM &&
+		    (entry->map->flags & _DRM_CONTAINS_LOCK)) {
+			return entry->map;
+		}
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(drm_getsarea);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 3b159ca..7bc51ba 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -39,9 +39,9 @@
 #include <linux/poll.h>
 
 static int drm_open_helper(struct inode *inode, struct file *filp,
-			   drm_device_t * dev);
+			   struct drm_device * dev);
 
-static int drm_setup(drm_device_t * dev)
+static int drm_setup(struct drm_device * dev)
 {
 	drm_local_map_t *map;
 	int i;
@@ -79,13 +79,6 @@
 	drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
 	INIT_LIST_HEAD(&dev->magicfree);
 
-	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 = NULL;
 	init_waitqueue_head(&dev->lock.lock_queue);
 	dev->queue_count = 0;
@@ -135,7 +128,7 @@
  */
 int drm_open(struct inode *inode, struct file *filp)
 {
-	drm_device_t *dev = NULL;
+	struct drm_device *dev = NULL;
 	int minor = iminor(inode);
 	int retcode = 0;
 
@@ -174,7 +167,7 @@
  */
 int drm_stub_open(struct inode *inode, struct file *filp)
 {
-	drm_device_t *dev = NULL;
+	struct drm_device *dev = NULL;
 	int minor = iminor(inode);
 	int err = -ENODEV;
 	const struct file_operations *old_fops;
@@ -230,10 +223,10 @@
  * 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)
+			   struct drm_device * dev)
 {
 	int minor = iminor(inode);
-	drm_file_t *priv;
+	struct drm_file *priv;
 	int ret;
 
 	if (filp->f_flags & O_EXCL)
@@ -258,6 +251,8 @@
 	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count = 0;
 
+	INIT_LIST_HEAD(&priv->lhead);
+
 	if (dev->driver->open) {
 		ret = dev->driver->open(dev, priv);
 		if (ret < 0)
@@ -265,19 +260,10 @@
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	if (!dev->file_last) {
-		priv->next = NULL;
-		priv->prev = NULL;
-		dev->file_first = priv;
-		dev->file_last = priv;
-		/* first opener automatically becomes master */
+	if (list_empty(&dev->filelist))
 		priv->master = 1;
-	} else {
-		priv->next = NULL;
-		priv->prev = dev->file_last;
-		dev->file_last->next = priv;
-		dev->file_last = priv;
-	}
+
+	list_add(&priv->lhead, &dev->filelist);
 	mutex_unlock(&dev->struct_mutex);
 
 #ifdef __alpha__
@@ -309,8 +295,8 @@
 /** 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	int retcode;
 
 	DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
@@ -336,8 +322,8 @@
  */
 int drm_release(struct inode *inode, struct file *filp)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
 	int retcode = 0;
 
 	lock_kernel();
@@ -414,10 +400,10 @@
 	drm_fasync(-1, filp, 0);
 
 	mutex_lock(&dev->ctxlist_mutex);
-	if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
-		drm_ctx_list_t *pos, *n;
+	if (!list_empty(&dev->ctxlist)) {
+		struct drm_ctx_list *pos, *n;
 
-		list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
 			if (pos->tag == priv &&
 			    pos->handle != DRM_KERNEL_CONTEXT) {
 				if (dev->driver->context_dtor)
@@ -436,22 +422,12 @@
 
 	mutex_lock(&dev->struct_mutex);
 	if (priv->remove_auth_on_close == 1) {
-		drm_file_t *temp = dev->file_first;
-		while (temp) {
+		struct drm_file *temp;
+
+		list_for_each_entry(temp, &dev->filelist, lhead)
 			temp->authenticated = 0;
-			temp = temp->next;
-		}
 	}
-	if (priv->prev) {
-		priv->prev->next = priv->next;
-	} else {
-		dev->file_first = priv->next;
-	}
-	if (priv->next) {
-		priv->next->prev = priv->prev;
-	} else {
-		dev->file_last = priv->prev;
-	}
+	list_del(&priv->lhead);
 	mutex_unlock(&dev->struct_mutex);
 
 	if (dev->driver->postclose)
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c
index 31acb62..3ad3190 100644
--- a/drivers/char/drm/drm_hashtab.c
+++ b/drivers/char/drm/drm_hashtab.c
@@ -36,7 +36,7 @@
 #include "drm_hashtab.h"
 #include <linux/hash.h>
 
-int drm_ht_create(drm_open_hash_t *ht, unsigned int order)
+int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
 {
 	unsigned int i;
 
@@ -63,9 +63,9 @@
 	return 0;
 }
 
-void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key)
+void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
 {
-	drm_hash_item_t *entry;
+	struct drm_hash_item *entry;
 	struct hlist_head *h_list;
 	struct hlist_node *list;
 	unsigned int hashed_key;
@@ -75,15 +75,15 @@
 	DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
 	h_list = &ht->table[hashed_key];
 	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, drm_hash_item_t, head);
+		entry = hlist_entry(list, struct drm_hash_item, head);
 		DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
 	}
 }
 
-static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht, 
+static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, 
 					  unsigned long key)
 {
-	drm_hash_item_t *entry;
+	struct drm_hash_item *entry;
 	struct hlist_head *h_list;
 	struct hlist_node *list;
 	unsigned int hashed_key;
@@ -91,7 +91,7 @@
 	hashed_key = hash_long(key, ht->order);
 	h_list = &ht->table[hashed_key];
 	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, drm_hash_item_t, head);
+		entry = hlist_entry(list, struct drm_hash_item, head);
 		if (entry->key == key)
 			return list;
 		if (entry->key > key)
@@ -101,9 +101,9 @@
 }
 
 
-int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
-	drm_hash_item_t *entry;
+	struct drm_hash_item *entry;
 	struct hlist_head *h_list;
 	struct hlist_node *list, *parent;
 	unsigned int hashed_key;
@@ -113,7 +113,7 @@
 	h_list = &ht->table[hashed_key];
 	parent = NULL;
 	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, drm_hash_item_t, head);
+		entry = hlist_entry(list, struct drm_hash_item, head);
 		if (entry->key == key)
 			return -EINVAL;
 		if (entry->key > key)
@@ -132,7 +132,7 @@
  * Just insert an item and return any "bits" bit key that hasn't been 
  * used before.
  */
-int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
 			      unsigned long seed, int bits, int shift,
 			      unsigned long add)
 {
@@ -156,8 +156,8 @@
 	return 0;
 }
 
-int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key,
-		     drm_hash_item_t **item)
+int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
+		     struct drm_hash_item **item)
 {
 	struct hlist_node *list;
 
@@ -165,11 +165,11 @@
 	if (!list)
 		return -EINVAL;
 
-	*item = hlist_entry(list, drm_hash_item_t, head);
+	*item = hlist_entry(list, struct drm_hash_item, head);
 	return 0;
 }
 
-int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key)
+int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 {
 	struct hlist_node *list;
 
@@ -182,14 +182,14 @@
 	return -EINVAL;
 }
 
-int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
 	hlist_del_init(&item->head);
 	ht->fill--;
 	return 0;
 }
 
-void drm_ht_remove(drm_open_hash_t *ht)
+void drm_ht_remove(struct drm_open_hash *ht)
 {
 	if (ht->table) {
 		if (ht->use_vmalloc)
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
index 613091c..0f13767 100644
--- a/drivers/char/drm/drm_hashtab.h
+++ b/drivers/char/drm/drm_hashtab.h
@@ -37,31 +37,31 @@
 
 #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
 
-typedef struct drm_hash_item{
+struct drm_hash_item {
 	struct hlist_node head;
 	unsigned long key;
-} drm_hash_item_t;
+};
 
-typedef struct drm_open_hash{
+struct drm_open_hash {
 	unsigned int size;
 	unsigned int order;
 	unsigned int fill;
 	struct hlist_head *table;
 	int use_vmalloc;
-} drm_open_hash_t;
+};
 
 
-extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order);
-extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
+extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
 				     unsigned long seed, int bits, int shift,
 				     unsigned long add);
-extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item);
+extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
 
-extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern void drm_ht_remove(drm_open_hash_t *ht);
+extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern void drm_ht_remove(struct drm_open_hash *ht);
 
 
 #endif
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index fafeb34..462f46f 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -82,7 +82,7 @@
 			      unsigned long arg)
 {
 	drm_version32_t v32;
-	drm_version_t __user *version;
+	struct drm_version __user *version;
 	int err;
 
 	if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
@@ -129,7 +129,7 @@
 				unsigned long arg)
 {
 	drm_unique32_t uq32;
-	drm_unique_t __user *u;
+	struct drm_unique __user *u;
 	int err;
 
 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
@@ -159,7 +159,7 @@
 				unsigned long arg)
 {
 	drm_unique32_t uq32;
-	drm_unique_t __user *u;
+	struct drm_unique __user *u;
 
 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
 		return -EFAULT;
@@ -179,8 +179,8 @@
 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 */
-	drm_map_flags_t flags;	/**< Flags */
+	enum drm_map_type type;	/**< Type of memory to map */
+	enum drm_map_flags flags;	/**< Flags */
 	u32 handle;		/**< User-space: "Handle" to pass to mmap() */
 	int mtrr;		/**< MTRR slot used */
 } drm_map32_t;
@@ -190,7 +190,7 @@
 {
 	drm_map32_t __user *argp = (void __user *)arg;
 	drm_map32_t m32;
-	drm_map_t __user *map;
+	struct drm_map __user *map;
 	int idx, err;
 	void *handle;
 
@@ -228,7 +228,7 @@
 {
 	drm_map32_t __user *argp = (void __user *)arg;
 	drm_map32_t m32;
-	drm_map_t __user *map;
+	struct drm_map __user *map;
 	int err;
 	void *handle;
 
@@ -270,7 +270,7 @@
 			    unsigned long arg)
 {
 	drm_map32_t __user *argp = (void __user *)arg;
-	drm_map_t __user *map;
+	struct drm_map __user *map;
 	u32 handle;
 
 	if (get_user(handle, &argp->handle))
@@ -300,7 +300,7 @@
 {
 	drm_client32_t c32;
 	drm_client32_t __user *argp = (void __user *)arg;
-	drm_client_t __user *client;
+	struct drm_client __user *client;
 	int idx, err;
 
 	if (get_user(idx, &argp->idx))
@@ -333,7 +333,7 @@
 	u32 count;
 	struct {
 		u32 value;
-		drm_stat_type_t type;
+		enum drm_stat_type type;
 	} data[15];
 } drm_stats32_t;
 
@@ -342,7 +342,7 @@
 {
 	drm_stats32_t s32;
 	drm_stats32_t __user *argp = (void __user *)arg;
-	drm_stats_t __user *stats;
+	struct drm_stats __user *stats;
 	int i, err;
 
 	stats = compat_alloc_user_space(sizeof(*stats));
@@ -379,7 +379,7 @@
 			      unsigned long arg)
 {
 	drm_buf_desc32_t __user *argp = (void __user *)arg;
-	drm_buf_desc_t __user *buf;
+	struct drm_buf_desc __user *buf;
 	int err;
 	unsigned long agp_start;
 
@@ -411,7 +411,7 @@
 {
 	drm_buf_desc32_t b32;
 	drm_buf_desc32_t __user *argp = (void __user *)arg;
-	drm_buf_desc_t __user *buf;
+	struct drm_buf_desc __user *buf;
 
 	if (copy_from_user(&b32, argp, sizeof(b32)))
 		return -EFAULT;
@@ -440,8 +440,8 @@
 	drm_buf_info32_t req32;
 	drm_buf_info32_t __user *argp = (void __user *)arg;
 	drm_buf_desc32_t __user *to;
-	drm_buf_info_t __user *request;
-	drm_buf_desc_t __user *list;
+	struct drm_buf_info __user *request;
+	struct drm_buf_desc __user *list;
 	size_t nbytes;
 	int i, err;
 	int count, actual;
@@ -457,11 +457,11 @@
 	    && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
 		return -EFAULT;
 
-	nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t);
+	nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
 	request = compat_alloc_user_space(nbytes);
 	if (!access_ok(VERIFY_WRITE, request, nbytes))
 		return -EFAULT;
-	list = (drm_buf_desc_t *) (request + 1);
+	list = (struct drm_buf_desc *) (request + 1);
 
 	if (__put_user(count, &request->count)
 	    || __put_user(list, &request->list))
@@ -477,7 +477,7 @@
 	if (count >= actual)
 		for (i = 0; i < actual; ++i)
 			if (__copy_in_user(&to[i], &list[i],
-					   offsetof(drm_buf_desc_t, flags)))
+					   offsetof(struct drm_buf_desc, flags)))
 				return -EFAULT;
 
 	if (__put_user(actual, &argp->count))
@@ -505,8 +505,8 @@
 	drm_buf_map32_t __user *argp = (void __user *)arg;
 	drm_buf_map32_t req32;
 	drm_buf_pub32_t __user *list32;
-	drm_buf_map_t __user *request;
-	drm_buf_pub_t __user *list;
+	struct drm_buf_map __user *request;
+	struct drm_buf_pub __user *list;
 	int i, err;
 	int count, actual;
 	size_t nbytes;
@@ -519,11 +519,11 @@
 
 	if (count < 0)
 		return -EINVAL;
-	nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t);
+	nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
 	request = compat_alloc_user_space(nbytes);
 	if (!access_ok(VERIFY_WRITE, request, nbytes))
 		return -EFAULT;
-	list = (drm_buf_pub_t *) (request + 1);
+	list = (struct drm_buf_pub *) (request + 1);
 
 	if (__put_user(count, &request->count)
 	    || __put_user(list, &request->list))
@@ -539,7 +539,7 @@
 	if (count >= actual)
 		for (i = 0; i < actual; ++i)
 			if (__copy_in_user(&list32[i], &list[i],
-					   offsetof(drm_buf_pub_t, address))
+					   offsetof(struct drm_buf_pub, address))
 			    || __get_user(addr, &list[i].address)
 			    || __put_user((unsigned long)addr,
 					  &list32[i].address))
@@ -562,7 +562,7 @@
 			       unsigned long arg)
 {
 	drm_buf_free32_t req32;
-	drm_buf_free_t __user *request;
+	struct drm_buf_free __user *request;
 	drm_buf_free32_t __user *argp = (void __user *)arg;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -589,7 +589,7 @@
 				  unsigned long arg)
 {
 	drm_ctx_priv_map32_t req32;
-	drm_ctx_priv_map_t __user *request;
+	struct drm_ctx_priv_map __user *request;
 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -610,7 +610,7 @@
 static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
 				  unsigned long arg)
 {
-	drm_ctx_priv_map_t __user *request;
+	struct drm_ctx_priv_map __user *request;
 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
 	int err;
 	unsigned int ctx_id;
@@ -648,7 +648,7 @@
 {
 	drm_ctx_res32_t __user *argp = (void __user *)arg;
 	drm_ctx_res32_t res32;
-	drm_ctx_res_t __user *res;
+	struct drm_ctx_res __user *res;
 	int err;
 
 	if (copy_from_user(&res32, argp, sizeof(res32)))
@@ -658,7 +658,7 @@
 	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((struct drm_ctx __user *) (unsigned long)res32.contexts,
 			  &res->contexts))
 		return -EFAULT;
 
@@ -679,7 +679,7 @@
 	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 */
+	enum drm_dma_flags flags;		  /**< Flags */
 	int request_count;	  /**< Number of buffers requested */
 	int request_size;	  /**< Desired size for buffers */
 	u32 request_indices;	  /**< Buffer information */
@@ -692,7 +692,7 @@
 {
 	drm_dma32_t d32;
 	drm_dma32_t __user *argp = (void __user *)arg;
-	drm_dma_t __user *d;
+	struct drm_dma __user *d;
 	int err;
 
 	if (copy_from_user(&d32, argp, sizeof(d32)))
@@ -740,7 +740,7 @@
 {
 	drm_agp_mode32_t __user *argp = (void __user *)arg;
 	drm_agp_mode32_t m32;
-	drm_agp_mode_t __user *mode;
+	struct drm_agp_mode __user *mode;
 
 	if (get_user(m32.mode, &argp->mode))
 		return -EFAULT;
@@ -772,7 +772,7 @@
 {
 	drm_agp_info32_t __user *argp = (void __user *)arg;
 	drm_agp_info32_t i32;
-	drm_agp_info_t __user *info;
+	struct drm_agp_info __user *info;
 	int err;
 
 	info = compat_alloc_user_space(sizeof(*info));
@@ -813,7 +813,7 @@
 {
 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
 	drm_agp_buffer32_t req32;
-	drm_agp_buffer_t __user *request;
+	struct drm_agp_buffer __user *request;
 	int err;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -845,7 +845,7 @@
 			       unsigned long arg)
 {
 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
-	drm_agp_buffer_t __user *request;
+	struct drm_agp_buffer __user *request;
 	u32 handle;
 
 	request = compat_alloc_user_space(sizeof(*request));
@@ -868,7 +868,7 @@
 {
 	drm_agp_binding32_t __user *argp = (void __user *)arg;
 	drm_agp_binding32_t req32;
-	drm_agp_binding_t __user *request;
+	struct drm_agp_binding __user *request;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
 		return -EFAULT;
@@ -887,7 +887,7 @@
 				 unsigned long arg)
 {
 	drm_agp_binding32_t __user *argp = (void __user *)arg;
-	drm_agp_binding_t __user *request;
+	struct drm_agp_binding __user *request;
 	u32 handle;
 
 	request = compat_alloc_user_space(sizeof(*request));
@@ -910,7 +910,7 @@
 			       unsigned long arg)
 {
 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
-	drm_scatter_gather_t __user *request;
+	struct drm_scatter_gather __user *request;
 	int err;
 	unsigned long x;
 
@@ -938,7 +938,7 @@
 			      unsigned long arg)
 {
 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
-	drm_scatter_gather_t __user *request;
+	struct drm_scatter_gather __user *request;
 	unsigned long x;
 
 	request = compat_alloc_user_space(sizeof(*request));
@@ -953,13 +953,13 @@
 }
 
 struct drm_wait_vblank_request32 {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	u32 signal;
 };
 
 struct drm_wait_vblank_reply32 {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	s32 tval_sec;
 	s32 tval_usec;
@@ -975,7 +975,7 @@
 {
 	drm_wait_vblank32_t __user *argp = (void __user *)arg;
 	drm_wait_vblank32_t req32;
-	drm_wait_vblank_t __user *request;
+	union drm_wait_vblank __user *request;
 	int err;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 5658955..b195e10 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -52,10 +52,10 @@
 int drm_getunique(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_unique_t __user *argp = (void __user *)arg;
-	drm_unique_t u;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_unique __user *argp = (void __user *)arg;
+	struct drm_unique u;
 
 	if (copy_from_user(&u, argp, sizeof(u)))
 		return -EFAULT;
@@ -86,15 +86,15 @@
 int drm_setunique(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_unique_t u;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_unique u;
 	int domain, bus, slot, func, ret;
 
 	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, (struct drm_unique __user *) arg, sizeof(u)))
 		return -EFAULT;
 
 	if (!u.unique_len || u.unique_len > 1024)
@@ -136,7 +136,7 @@
 	return 0;
 }
 
-static int drm_set_busid(drm_device_t * dev)
+static int drm_set_busid(struct drm_device * dev)
 {
 	int len;
 
@@ -184,11 +184,11 @@
 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_map_list_t *r_list = NULL;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map __user *argp = (void __user *)arg;
+	struct drm_map map;
+	struct drm_map_list *r_list = NULL;
 	struct list_head *list;
 	int idx;
 	int i;
@@ -204,9 +204,9 @@
 	}
 
 	i = 0;
-	list_for_each(list, &dev->maplist->head) {
+	list_for_each(list, &dev->maplist) {
 		if (i == idx) {
-			r_list = list_entry(list, drm_map_list_t, head);
+			r_list = list_entry(list, struct drm_map_list, head);
 			break;
 		}
 		i++;
@@ -245,11 +245,11 @@
 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_client_t __user *argp = (drm_client_t __user *)arg;
-	drm_client_t client;
-	drm_file_t *pt;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_client __user *argp = (struct drm_client __user *)arg;
+	struct drm_client client;
+	struct drm_file *pt;
 	int idx;
 	int i;
 
@@ -257,12 +257,18 @@
 		return -EFAULT;
 	idx = client.idx;
 	mutex_lock(&dev->struct_mutex);
-	for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
-
-	if (!pt) {
+	
+	if (list_empty(&dev->filelist)) {
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
+
+	i = 0;
+	list_for_each_entry(pt, &dev->filelist, lhead) {
+		if (i++ >= idx)
+			break;
+	}
+
 	client.auth = pt->authenticated;
 	client.pid = pt->pid;
 	client.uid = pt->uid;
@@ -288,9 +294,9 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_stats stats;
 	int i;
 
 	memset(&stats, 0, sizeof(stats));
@@ -310,7 +316,7 @@
 
 	mutex_unlock(&dev->struct_mutex);
 
-	if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
+	if (copy_to_user((struct drm_stats __user *) arg, &stats, sizeof(stats)))
 		return -EFAULT;
 	return 0;
 }
@@ -329,10 +335,10 @@
 int drm_setversion(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_set_version_t sv;
-	drm_set_version_t retv;
+	struct drm_set_version sv;
+	struct drm_set_version retv;
 	int if_version;
-	drm_set_version_t __user *argp = (void __user *)data;
+	struct drm_set_version __user *argp = (void __user *)data;
 	int ret;
 
 	if (copy_from_user(&sv, argp, sizeof(sv)))
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 2e75331..871d2fd 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -53,10 +53,10 @@
 int drm_irq_by_busid(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_irq_busid_t __user *argp = (void __user *)arg;
-	drm_irq_busid_t p;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_irq_busid __user *argp = (void __user *)arg;
+	struct drm_irq_busid p;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
@@ -87,7 +87,7 @@
  * \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(struct drm_device * dev)
 {
 	int ret;
 	unsigned long sh_flags = 0;
@@ -120,8 +120,8 @@
 
 		spin_lock_init(&dev->vbl_lock);
 
-		INIT_LIST_HEAD(&dev->vbl_sigs.head);
-		INIT_LIST_HEAD(&dev->vbl_sigs2.head);
+		INIT_LIST_HEAD(&dev->vbl_sigs);
+		INIT_LIST_HEAD(&dev->vbl_sigs2);
 
 		dev->vbl_pending = 0;
 	}
@@ -155,7 +155,7 @@
  *
  * 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(struct drm_device * dev)
 {
 	int irq_enabled;
 
@@ -197,13 +197,13 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_control 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, (struct drm_control __user *) arg, sizeof(ctl)))
 		return -EFAULT;
 
 	switch (ctl.func) {
@@ -244,10 +244,10 @@
  */
 int drm_wait_vblank(DRM_IOCTL_ARGS)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_wait_vblank_t __user *argp = (void __user *)data;
-	drm_wait_vblank_t vblwait;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	union drm_wait_vblank __user *argp = (void __user *)data;
+	union drm_wait_vblank vblwait;
 	struct timeval now;
 	int ret = 0;
 	unsigned int flags, seq;
@@ -292,9 +292,9 @@
 
 	if (flags & _DRM_VBLANK_SIGNAL) {
 		unsigned long irqflags;
-		drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+		struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
 				      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-		drm_vbl_sig_t *vbl_sig;
+		struct drm_vbl_sig *vbl_sig;
 
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
@@ -302,7 +302,7 @@
 		 * for the same vblank sequence number; nothing to be done in
 		 * that case
 		 */
-		list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {
+		list_for_each_entry(vbl_sig, vbl_sigs, head) {
 			if (vbl_sig->sequence == vblwait.request.sequence
 			    && vbl_sig->info.si_signo == vblwait.request.signal
 			    && vbl_sig->task == current) {
@@ -324,7 +324,7 @@
 
 		if (!
 		    (vbl_sig =
-		     drm_alloc(sizeof(drm_vbl_sig_t), DRM_MEM_DRIVER))) {
+		     drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
 			return -ENOMEM;
 		}
 
@@ -336,7 +336,7 @@
 
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
-		list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);
+		list_add_tail(&vbl_sig->head, vbl_sigs);
 
 		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
@@ -371,7 +371,7 @@
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-void drm_vbl_send_signals(drm_device_t * dev)
+void drm_vbl_send_signals(struct drm_device * dev)
 {
 	unsigned long flags;
 	int i;
@@ -379,20 +379,18 @@
 	spin_lock_irqsave(&dev->vbl_lock, flags);
 
 	for (i = 0; i < 2; i++) {
-		struct list_head *list, *tmp;
-		drm_vbl_sig_t *vbl_sig;
-		drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+		struct drm_vbl_sig *vbl_sig, *tmp;
+		struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
 		unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
 						   &dev->vbl_received);
 
-		list_for_each_safe(list, tmp, &vbl_sigs->head) {
-			vbl_sig = list_entry(list, drm_vbl_sig_t, head);
+		list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, 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);
 
-				list_del(list);
+				list_del(&vbl_sig->head);
 
 				drm_free(vbl_sig, sizeof(*vbl_sig),
 					 DRM_MEM_DRIVER);
@@ -418,7 +416,7 @@
  */
 static void drm_locked_tasklet_func(unsigned long data)
 {
-	drm_device_t *dev = (drm_device_t*)data;
+	struct drm_device *dev = (struct drm_device *)data;
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev->tasklet_lock, irqflags);
@@ -455,7 +453,7 @@
  * context, it must not make any assumptions about this. Also, the HW lock will
  * be held with the kernel context or any client context.
  */
-void drm_locked_tasklet(drm_device_t *dev, void (*func)(drm_device_t*))
+void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *))
 {
 	unsigned long irqflags;
 	static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index befd1af..c0534b5 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -51,15 +51,15 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	DECLARE_WAITQUEUE(entry, current);
-	drm_lock_t lock;
+	struct drm_lock lock;
 	int ret = 0;
 
 	++priv->lock_count;
 
-	if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+	if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock)))
 		return -EFAULT;
 
 	if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -152,12 +152,12 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_lock lock;
 	unsigned long irqflags;
 
-	if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+	if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock)))
 		return -EFAULT;
 
 	if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -202,7 +202,7 @@
  *
  * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
  */
-int drm_lock_take(drm_lock_data_t *lock_data,
+int drm_lock_take(struct drm_lock_data *lock_data,
 		  unsigned int context)
 {
 	unsigned int old, new, prev;
@@ -251,7 +251,7 @@
  * 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_lock_data_t *lock_data,
+static int drm_lock_transfer(struct drm_lock_data *lock_data,
 			     unsigned int context)
 {
 	unsigned int old, new, prev;
@@ -277,7 +277,7 @@
  * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
  * waiting on the lock queue.
  */
-int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context)
+int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
 {
 	unsigned int old, new, prev;
 	volatile unsigned int *lock = &lock_data->hw_lock->lock;
@@ -319,7 +319,7 @@
  */
 static int drm_notifier(void *priv)
 {
-	drm_sigdata_t *s = (drm_sigdata_t *) priv;
+	struct drm_sigdata *s = (struct drm_sigdata *) priv;
 	unsigned int old, new, prev;
 
 	/* Allow signal delivery if lock isn't held */
@@ -350,7 +350,7 @@
  * having to worry about starvation.
  */
 
-void drm_idlelock_take(drm_lock_data_t *lock_data)
+void drm_idlelock_take(struct drm_lock_data *lock_data)
 {
 	int ret = 0;
 
@@ -369,7 +369,7 @@
 }
 EXPORT_SYMBOL(drm_idlelock_take);
 
-void drm_idlelock_release(drm_lock_data_t *lock_data)
+void drm_idlelock_release(struct drm_lock_data *lock_data)
 {
 	unsigned int old, prev;
 	volatile unsigned int *lock = &lock_data->hw_lock->lock;
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 92a8670..9301990 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -80,7 +80,7 @@
 
 #if __OS_HAS_AGP
 static void *agp_remap(unsigned long offset, unsigned long size,
-		       drm_device_t * dev)
+		       struct drm_device * dev)
 {
 	unsigned long *phys_addr_map, i, num_pages =
 	    PAGE_ALIGN(size) / PAGE_SIZE;
@@ -94,7 +94,7 @@
 	offset -= dev->hose->mem_space->start;
 #endif
 
-	for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+	list_for_each_entry(agpmem, &dev->agp->memory, head)
 		if (agpmem->bound <= offset
 		    && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
 		    (offset + size))
@@ -123,7 +123,7 @@
 }
 
 /** 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(struct drm_device * dev, int pages, u32 type)
 {
 	return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
 }
@@ -148,7 +148,7 @@
 
 #else  /*  __OS_HAS_AGP  */
 static inline void *agp_remap(unsigned long offset, unsigned long size,
-			      drm_device_t * dev)
+			      struct drm_device * dev)
 {
 	return NULL;
 }
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
index 2ec1d9f..3e6bc14 100644
--- a/drivers/char/drm/drm_mm.c
+++ b/drivers/char/drm/drm_mm.c
@@ -44,26 +44,26 @@
 #include "drmP.h"
 #include <linux/slab.h>
 
-unsigned long drm_mm_tail_space(drm_mm_t *mm)
+unsigned long drm_mm_tail_space(struct drm_mm *mm)
 {
 	struct list_head *tail_node;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
 	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
 	if (!entry->free)
 		return 0;
 
 	return entry->size;
 }
 
-int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
 {
 	struct list_head *tail_node;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
 	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
 	if (!entry->free)
 		return -ENOMEM;
 
@@ -75,13 +75,13 @@
 }
 
 
-static int drm_mm_create_tail_node(drm_mm_t *mm,
+static int drm_mm_create_tail_node(struct drm_mm *mm,
 			    unsigned long start,
 			    unsigned long size)
 {
-	drm_mm_node_t *child;
+	struct drm_mm_node *child;
 
-	child = (drm_mm_node_t *)
+	child = (struct drm_mm_node *)
 		drm_alloc(sizeof(*child), DRM_MEM_MM);
 	if (!child)
 		return -ENOMEM;
@@ -98,13 +98,13 @@
 }
 
 
-int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
 {
 	struct list_head *tail_node;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
 	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
 	if (!entry->free) {
 		return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
 	}
@@ -112,12 +112,12 @@
 	return 0;
 }
 
-static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent,
+static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
 					    unsigned long size)
 {
-	drm_mm_node_t *child;
+	struct drm_mm_node *child;
 
-	child = (drm_mm_node_t *)
+	child = (struct drm_mm_node *)
 		drm_alloc(sizeof(*child), DRM_MEM_MM);
 	if (!child)
 		return NULL;
@@ -139,12 +139,12 @@
 
 
 
-drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
 				unsigned long size, unsigned alignment)
 {
 
-	drm_mm_node_t *align_splitoff = NULL;
-	drm_mm_node_t *child;
+	struct drm_mm_node *align_splitoff = NULL;
+	struct drm_mm_node *child;
 	unsigned tmp = 0;
 
 	if (alignment)
@@ -175,26 +175,26 @@
  * Otherwise add to the free stack.
  */
 
-void drm_mm_put_block(drm_mm_node_t * cur)
+void drm_mm_put_block(struct drm_mm_node * cur)
 {
 
-	drm_mm_t *mm = cur->mm;
+	struct drm_mm *mm = cur->mm;
 	struct list_head *cur_head = &cur->ml_entry;
 	struct list_head *root_head = &mm->ml_entry;
-	drm_mm_node_t *prev_node = NULL;
-	drm_mm_node_t *next_node;
+	struct drm_mm_node *prev_node = NULL;
+	struct drm_mm_node *next_node;
 
 	int merged = 0;
 
 	if (cur_head->prev != root_head) {
-		prev_node = list_entry(cur_head->prev, drm_mm_node_t, ml_entry);
+		prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
 		if (prev_node->free) {
 			prev_node->size += cur->size;
 			merged = 1;
 		}
 	}
 	if (cur_head->next != root_head) {
-		next_node = list_entry(cur_head->next, drm_mm_node_t, ml_entry);
+		next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
 		if (next_node->free) {
 			if (merged) {
 				prev_node->size += next_node->size;
@@ -218,14 +218,14 @@
 	}
 }
 
-drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
+struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
 				  unsigned long size,
 				  unsigned alignment, int best_match)
 {
 	struct list_head *list;
 	const struct list_head *free_stack = &mm->fl_entry;
-	drm_mm_node_t *entry;
-	drm_mm_node_t *best;
+	struct drm_mm_node *entry;
+	struct drm_mm_node *best;
 	unsigned long best_size;
 	unsigned wasted;
 
@@ -233,7 +233,7 @@
 	best_size = ~0UL;
 
 	list_for_each(list, free_stack) {
-		entry = list_entry(list, drm_mm_node_t, fl_entry);
+		entry = list_entry(list, struct drm_mm_node, fl_entry);
 		wasted = 0;
 
 		if (entry->size < size)
@@ -259,14 +259,14 @@
 	return best;
 }
 
-int drm_mm_clean(drm_mm_t * mm)
+int drm_mm_clean(struct drm_mm * mm)
 {
 	struct list_head *head = &mm->ml_entry;
 
 	return (head->next->next == head);
 }
 
-int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
+int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
 	INIT_LIST_HEAD(&mm->ml_entry);
 	INIT_LIST_HEAD(&mm->fl_entry);
@@ -275,12 +275,12 @@
 }
 
 
-void drm_mm_takedown(drm_mm_t * mm)
+void drm_mm_takedown(struct drm_mm * mm)
 {
 	struct list_head *bnode = mm->fl_entry.next;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
-	entry = list_entry(bnode, drm_mm_node_t, fl_entry);
+	entry = list_entry(bnode, struct drm_mm_node, fl_entry);
 
 	if (entry->ml_entry.next != &mm->ml_entry ||
 	    entry->fl_entry.next != &mm->fl_entry) {
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 0fe7b44..0b8d343 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -34,8 +34,8 @@
 /** Read/write memory barrier */
 #define DRM_MEMORYBARRIER()		mb()
 /** DRM device local declaration */
-#define DRM_DEVICE	drm_file_t	*priv	= filp->private_data; \
-			drm_device_t	*dev	= priv->head->dev
+#define DRM_DEVICE	struct drm_file	*priv	= filp->private_data; \
+			struct drm_device *dev	= priv->head->dev
 
 /** IRQ handler arguments and return type and values */
 #define DRM_IRQ_ARGS		int irq, void *arg
@@ -96,24 +96,6 @@
 
 #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.
- */
-#define DRM_GETSAREA()							 \
-do { 									 \
-	drm_map_list_t *entry;						 \
-	list_for_each_entry( entry, &dev->maplist->head, head ) {	 \
-		if ( entry->map &&					 \
-		     entry->map->type == _DRM_SHM &&			 \
-		     (entry->map->flags & _DRM_CONTAINS_LOCK) ) {	 \
-			dev_priv->sarea = entry->map;			 \
- 			break;						 \
- 		}							 \
- 	}								 \
-} while (0)
-
 #define DRM_HZ HZ
 
 #define DRM_WAIT_ON( ret, queue, timeout, condition )		\
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 86a0f1c..e292bb0 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -47,7 +47,7 @@
 /**
  * \brief Allocate a PCI consistent memory block, for DMA.
  */
-drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
 				dma_addr_t maxaddr)
 {
 	drm_dma_handle_t *dmah;
@@ -126,7 +126,7 @@
  *
  * 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(struct drm_device * dev, drm_dma_handle_t * dmah)
 {
 #if 1
 	unsigned long addr;
@@ -172,7 +172,7 @@
 /**
  * \brief Free a PCI consistent memory block
  */
-void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 {
 	__drm_pci_free(dev, dmah);
 	kfree(dmah);
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index b204498..12dfea8 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -87,7 +87,7 @@
  * "/proc/dri/%minor%/", and each entry in proc_list as
  * "/proc/dri/%minor%/%name%".
  */
-int drm_proc_init(drm_device_t * dev, int minor,
+int drm_proc_init(struct drm_device * dev, int minor,
 		  struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
 {
 	struct proc_dir_entry *ent;
@@ -163,7 +163,7 @@
 static int drm_name_info(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
 
 	if (offset > DRM_PROC_LIMIT) {
@@ -205,11 +205,10 @@
 static int drm__vm_info(char *buf, char **start, off_t offset, int request,
 			int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_map_t *map;
-	drm_map_list_t *r_list;
-	struct list_head *list;
+	struct drm_map *map;
+	struct drm_map_list *r_list;
 
 	/* Hardcoded from _DRM_FRAME_BUFFER,
 	   _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
@@ -229,9 +228,7 @@
 	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) {
-		r_list = list_entry(list, drm_map_list_t, head);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		map = r_list->map;
 		if (!map)
 			continue;
@@ -242,14 +239,15 @@
 		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;
@@ -263,7 +261,7 @@
 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
 		       int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -286,10 +284,10 @@
 static int drm__queues_info(char *buf, char **start, off_t offset,
 			    int request, int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
 	int i;
-	drm_queue_t *q;
+	struct drm_queue *q;
 
 	if (offset > DRM_PROC_LIMIT) {
 		*eof = 1;
@@ -336,7 +334,7 @@
 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
 			   int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -359,9 +357,9 @@
 static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
 			  int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma || offset > DRM_PROC_LIMIT) {
@@ -408,7 +406,7 @@
 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -431,9 +429,9 @@
 static int drm__clients_info(char *buf, char **start, off_t offset,
 			     int request, int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_file_t *priv;
+	struct drm_file *priv;
 
 	if (offset > DRM_PROC_LIMIT) {
 		*eof = 1;
@@ -444,7 +442,7 @@
 	*eof = 0;
 
 	DRM_PROC_PRINT("a dev	pid    uid	magic	  ioctls\n\n");
-	for (priv = dev->file_first; priv; priv = priv->next) {
+	list_for_each_entry(priv, &dev->filelist, lhead) {
 		DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
 			       priv->authenticated ? 'y' : 'n',
 			       priv->minor,
@@ -464,7 +462,7 @@
 static int drm_clients_info(char *buf, char **start, off_t offset,
 			    int request, int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -478,9 +476,9 @@
 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_vma_entry_t *pt;
+	struct drm_vma_entry *pt;
 	struct vm_area_struct *vma;
 #if defined(__i386__)
 	unsigned int pgprot;
@@ -497,7 +495,7 @@
 	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) {
+	list_for_each_entry(pt, &dev->vmalist, head) {
 		if (!(vma = pt->vma))
 			continue;
 		DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
@@ -537,7 +535,7 @@
 static int drm_vma_info(char *buf, char **start, off_t offset, int request,
 			int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
index e94297b..f546696 100644
--- a/drivers/char/drm/drm_sarea.h
+++ b/drivers/char/drm/drm_sarea.h
@@ -50,29 +50,35 @@
 #define SAREA_DRAWABLE_CLAIMED_ENTRY    0x80000000
 
 /** SAREA drawable */
-typedef struct drm_sarea_drawable {
+struct drm_sarea_drawable {
 	unsigned int stamp;
 	unsigned int flags;
-} drm_sarea_drawable_t;
+};
 
 /** SAREA frame */
-typedef struct drm_sarea_frame {
+struct drm_sarea_frame {
 	unsigned int x;
 	unsigned int y;
 	unsigned int width;
 	unsigned int height;
 	unsigned int fullscreen;
-} drm_sarea_frame_t;
+};
 
 /** SAREA */
-typedef struct drm_sarea {
+struct drm_sarea {
     /** first thing is always the DRM locking structure */
-	drm_hw_lock_t lock;
+	struct drm_hw_lock 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 */
+	struct drm_hw_lock drawable_lock;
+	struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES];	/**< drawables */
+	struct drm_sarea_frame frame;	/**< frame */
 	drm_context_t dummy_context;
-} drm_sarea_t;
+};
+
+#ifndef __KERNEL__
+typedef struct drm_sarea_drawable drm_sarea_drawable_t;
+typedef struct drm_sarea_frame drm_sarea_frame_t;
+typedef struct drm_sarea drm_sarea_t;
+#endif
 
 #endif				/* _DRM_SAREA_H_ */
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
index 06ef7dd..067d25d 100644
--- a/drivers/char/drm/drm_scatter.c
+++ b/drivers/char/drm/drm_scatter.c
@@ -36,7 +36,7 @@
 
 #define DEBUG_SCATTER 0
 
-void drm_sg_cleanup(drm_sg_mem_t * entry)
+void drm_sg_cleanup(struct drm_sg_mem * entry)
 {
 	struct page *page;
 	int i;
@@ -65,11 +65,11 @@
 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;
-	drm_scatter_gather_t __user *argp = (void __user *)arg;
-	drm_scatter_gather_t request;
-	drm_sg_mem_t *entry;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_scatter_gather __user *argp = (void __user *)arg;
+	struct drm_scatter_gather request;
+	struct drm_sg_mem *entry;
 	unsigned long pages, i, j;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -201,16 +201,16 @@
 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;
-	drm_scatter_gather_t request;
-	drm_sg_mem_t *entry;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_scatter_gather request;
+	struct drm_sg_mem *entry;
 
 	if (!drm_core_check_feature(dev, DRIVER_SG))
 		return -EINVAL;
 
 	if (copy_from_user(&request,
-			   (drm_scatter_gather_t __user *) arg,
+			   (struct drm_scatter_gather __user *) arg,
 			   sizeof(request)))
 		return -EFAULT;
 
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c
index e15db6d..8421a93 100644
--- a/drivers/char/drm/drm_sman.c
+++ b/drivers/char/drm/drm_sman.c
@@ -38,13 +38,13 @@
 
 #include "drm_sman.h"
 
-typedef struct drm_owner_item {
-	drm_hash_item_t owner_hash;
+struct drm_owner_item {
+	struct drm_hash_item owner_hash;
 	struct list_head sman_list;
 	struct list_head mem_blocks;
-} drm_owner_item_t;
+};
 
-void drm_sman_takedown(drm_sman_t * sman)
+void drm_sman_takedown(struct drm_sman * sman)
 {
 	drm_ht_remove(&sman->user_hash_tab);
 	drm_ht_remove(&sman->owner_hash_tab);
@@ -56,12 +56,12 @@
 EXPORT_SYMBOL(drm_sman_takedown);
 
 int
-drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
 	      unsigned int user_order, unsigned int owner_order)
 {
 	int ret = 0;
 
-	sman->mm = (drm_sman_mm_t *) drm_calloc(num_managers, sizeof(*sman->mm),
+	sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
 						DRM_MEM_MM);
 	if (!sman->mm) {
 		ret = -ENOMEM;
@@ -88,8 +88,8 @@
 static void *drm_sman_mm_allocate(void *private, unsigned long size,
 				  unsigned alignment)
 {
-	drm_mm_t *mm = (drm_mm_t *) private;
-	drm_mm_node_t *tmp;
+	struct drm_mm *mm = (struct drm_mm *) private;
+	struct drm_mm_node *tmp;
 
 	tmp = drm_mm_search_free(mm, size, alignment, 1);
 	if (!tmp) {
@@ -101,30 +101,30 @@
 
 static void drm_sman_mm_free(void *private, void *ref)
 {
-	drm_mm_node_t *node = (drm_mm_node_t *) ref;
+	struct drm_mm_node *node = (struct drm_mm_node *) ref;
 
 	drm_mm_put_block(node);
 }
 
 static void drm_sman_mm_destroy(void *private)
 {
-	drm_mm_t *mm = (drm_mm_t *) private;
+	struct drm_mm *mm = (struct drm_mm *) private;
 	drm_mm_takedown(mm);
 	drm_free(mm, sizeof(*mm), DRM_MEM_MM);
 }
 
 static unsigned long drm_sman_mm_offset(void *private, void *ref)
 {
-	drm_mm_node_t *node = (drm_mm_node_t *) ref;
+	struct drm_mm_node *node = (struct drm_mm_node *) ref;
 	return node->start;
 }
 
 int
-drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
 		   unsigned long start, unsigned long size)
 {
-	drm_sman_mm_t *sman_mm;
-	drm_mm_t *mm;
+	struct drm_sman_mm *sman_mm;
+	struct drm_mm *mm;
 	int ret;
 
 	BUG_ON(manager >= sman->num_managers);
@@ -153,8 +153,8 @@
 EXPORT_SYMBOL(drm_sman_set_range);
 
 int
-drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
-		     drm_sman_mm_t * allocator)
+drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
+		     struct drm_sman_mm * allocator)
 {
 	BUG_ON(manager >= sman->num_managers);
 	sman->mm[manager] = *allocator;
@@ -163,16 +163,16 @@
 }
 EXPORT_SYMBOL(drm_sman_set_manager);
 
-static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman,
+static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
 						 unsigned long owner)
 {
 	int ret;
-	drm_hash_item_t *owner_hash_item;
-	drm_owner_item_t *owner_item;
+	struct drm_hash_item *owner_hash_item;
+	struct drm_owner_item *owner_item;
 
 	ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
 	if (!ret) {
-		return drm_hash_entry(owner_hash_item, drm_owner_item_t,
+		return drm_hash_entry(owner_hash_item, struct drm_owner_item,
 				      owner_hash);
 	}
 
@@ -194,14 +194,14 @@
 	return NULL;
 }
 
-drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager,
+struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
 				    unsigned long size, unsigned alignment,
 				    unsigned long owner)
 {
 	void *tmp;
-	drm_sman_mm_t *sman_mm;
-	drm_owner_item_t *owner_item;
-	drm_memblock_item_t *memblock;
+	struct drm_sman_mm *sman_mm;
+	struct drm_owner_item *owner_item;
+	struct drm_memblock_item *memblock;
 
 	BUG_ON(manager >= sman->num_managers);
 
@@ -246,9 +246,9 @@
 
 EXPORT_SYMBOL(drm_sman_alloc);
 
-static void drm_sman_free(drm_memblock_item_t *item)
+static void drm_sman_free(struct drm_memblock_item *item)
 {
-	drm_sman_t *sman = item->sman;
+	struct drm_sman *sman = item->sman;
 
 	list_del(&item->owner_list);
 	drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
@@ -256,40 +256,41 @@
 	drm_free(item, sizeof(*item), DRM_MEM_MM);
 }
 
-int drm_sman_free_key(drm_sman_t *sman, unsigned int key)
+int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
 {
-	drm_hash_item_t *hash_item;
-	drm_memblock_item_t *memblock_item;
+	struct drm_hash_item *hash_item;
+	struct drm_memblock_item *memblock_item;
 
 	if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
 		return -EINVAL;
 
-	memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash);
+	memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
+				       user_hash);
 	drm_sman_free(memblock_item);
 	return 0;
 }
 
 EXPORT_SYMBOL(drm_sman_free_key);
 
-static void drm_sman_remove_owner(drm_sman_t *sman,
-				  drm_owner_item_t *owner_item)
+static void drm_sman_remove_owner(struct drm_sman *sman,
+				  struct drm_owner_item *owner_item)
 {
 	list_del(&owner_item->sman_list);
 	drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
 	drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
 }
 
-int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
+int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
 {
 
-	drm_hash_item_t *hash_item;
-	drm_owner_item_t *owner_item;
+	struct drm_hash_item *hash_item;
+	struct drm_owner_item *owner_item;
 
 	if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
 		return -1;
 	}
 
-	owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+	owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
 	if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
 		drm_sman_remove_owner(sman, owner_item);
 		return -1;
@@ -300,10 +301,10 @@
 
 EXPORT_SYMBOL(drm_sman_owner_clean);
 
-static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
-				      drm_owner_item_t *owner_item)
+static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
+				      struct drm_owner_item *owner_item)
 {
-	drm_memblock_item_t *entry, *next;
+	struct drm_memblock_item *entry, *next;
 
 	list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
 				 owner_list) {
@@ -312,28 +313,28 @@
 	drm_sman_remove_owner(sman, owner_item);
 }
 
-void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner)
+void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
 {
 
-	drm_hash_item_t *hash_item;
-	drm_owner_item_t *owner_item;
+	struct drm_hash_item *hash_item;
+	struct drm_owner_item *owner_item;
 
 	if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
 
 		return;
 	}
 
-	owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+	owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
 	drm_sman_do_owner_cleanup(sman, owner_item);
 }
 
 EXPORT_SYMBOL(drm_sman_owner_cleanup);
 
-void drm_sman_cleanup(drm_sman_t *sman)
+void drm_sman_cleanup(struct drm_sman *sman)
 {
-	drm_owner_item_t *entry, *next;
+	struct drm_owner_item *entry, *next;
 	unsigned int i;
-	drm_sman_mm_t *sman_mm;
+	struct drm_sman_mm *sman_mm;
 
 	list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
 		drm_sman_do_owner_cleanup(sman, entry);
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h
index ddc732a..39a39fe 100644
--- a/drivers/char/drm/drm_sman.h
+++ b/drivers/char/drm/drm_sman.h
@@ -50,7 +50,7 @@
  * for memory management.
  */
 
-typedef struct drm_sman_mm {
+struct drm_sman_mm {
 	/* private info. If allocated, needs to be destroyed by the destroy
 	   function */
 	void *private;
@@ -74,30 +74,30 @@
 	   "alloc" function */
 
 	unsigned long (*offset) (void *private, void *ref);
-} drm_sman_mm_t;
+};
 
-typedef struct drm_memblock_item {
+struct drm_memblock_item {
 	struct list_head owner_list;
-	drm_hash_item_t user_hash;
+	struct drm_hash_item user_hash;
 	void *mm_info;
-	drm_sman_mm_t *mm;
+	struct drm_sman_mm *mm;
 	struct drm_sman *sman;
-} drm_memblock_item_t;
+};
 
-typedef struct drm_sman {
-	drm_sman_mm_t *mm;
+struct drm_sman {
+	struct drm_sman_mm *mm;
 	int num_managers;
-	drm_open_hash_t owner_hash_tab;
-	drm_open_hash_t user_hash_tab;
+	struct drm_open_hash owner_hash_tab;
+	struct drm_open_hash user_hash_tab;
 	struct list_head owner_items;
-} drm_sman_t;
+};
 
 /*
  * Take down a memory manager. This function should only be called after a
  * successful init and after a call to drm_sman_cleanup.
  */
 
-extern void drm_sman_takedown(drm_sman_t * sman);
+extern void drm_sman_takedown(struct drm_sman * sman);
 
 /*
  * Allocate structures for a manager.
@@ -112,7 +112,7 @@
  *
  */
 
-extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
 			 unsigned int user_order, unsigned int owner_order);
 
 /*
@@ -120,7 +120,7 @@
  * manager unless a customized allogator is used.
  */
 
-extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
 			      unsigned long start, unsigned long size);
 
 /*
@@ -129,23 +129,23 @@
  * so it can be destroyed after this call.
  */
 
-extern int drm_sman_set_manager(drm_sman_t * sman, unsigned int mananger,
-				drm_sman_mm_t * allocator);
+extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
+				struct drm_sman_mm * allocator);
 
 /*
  * Allocate a memory block. Aligment is not implemented yet.
  */
 
-extern drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman,
-					   unsigned int manager,
-					   unsigned long size,
-					   unsigned alignment,
-					   unsigned long owner);
+extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
+						unsigned int manager,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long owner);
 /*
  * Free a memory block identified by its user hash key.
  */
 
-extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
+extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key);
 
 /*
  * returns 1 iff there are no stale memory blocks associated with this owner.
@@ -154,7 +154,7 @@
  * resources associated with owner.
  */
 
-extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
+extern int drm_sman_owner_clean(struct drm_sman * sman, unsigned long owner);
 
 /*
  * Frees all stale memory blocks associated with this owner. Note that this
@@ -164,13 +164,13 @@
  * is not going to be referenced anymore.
  */
 
-extern void drm_sman_owner_cleanup(drm_sman_t * sman, unsigned long owner);
+extern void drm_sman_owner_cleanup(struct drm_sman * sman, unsigned long owner);
 
 /*
  * Frees all stale memory blocks associated with the memory manager.
  * See idling above.
  */
 
-extern void drm_sman_cleanup(drm_sman_t * sman);
+extern void drm_sman_cleanup(struct drm_sman * sman);
 
 #endif
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 19408ad..ee83ff9 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -49,16 +49,21 @@
 module_param_named(cards_limit, drm_cards_limit, int, 0444);
 module_param_named(debug, drm_debug, int, 0600);
 
-drm_head_t **drm_heads;
+struct drm_head **drm_heads;
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
-static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
+static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
 			   const struct pci_device_id *ent,
 			   struct drm_driver *driver)
 {
 	int retcode;
 
+	INIT_LIST_HEAD(&dev->filelist);
+	INIT_LIST_HEAD(&dev->ctxlist);
+	INIT_LIST_HEAD(&dev->vmalist);
+	INIT_LIST_HEAD(&dev->maplist);
+
 	spin_lock_init(&dev->count_lock);
 	spin_lock_init(&dev->drw_lock);
 	spin_lock_init(&dev->tasklet_lock);
@@ -67,6 +72,8 @@
 	mutex_init(&dev->struct_mutex);
 	mutex_init(&dev->ctxlist_mutex);
 
+	idr_init(&dev->drw_idr);
+
 	dev->pdev = pdev;
 	dev->pci_device = pdev->device;
 	dev->pci_vendor = pdev->vendor;
@@ -76,12 +83,7 @@
 #endif
 	dev->irq = pdev->irq;
 
-	dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
-	if (dev->maplist == NULL)
-		return -ENOMEM;
-	INIT_LIST_HEAD(&dev->maplist->head);
 	if (drm_ht_create(&dev->map_hash, 12)) {
-		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
 		return -ENOMEM;
 	}
 
@@ -143,9 +145,9 @@
  * 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(struct drm_device * dev, struct drm_head * head)
 {
-	drm_head_t **heads = drm_heads;
+	struct drm_head **heads = drm_heads;
 	int ret;
 	int minor;
 
@@ -154,7 +156,7 @@
 	for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
 		if (!*heads) {
 
-			*head = (drm_head_t) {
+			*head = (struct drm_head) {
 			.dev = dev,.device =
 				    MKDEV(DRM_MAJOR, minor),.minor = minor,};
 
@@ -184,7 +186,7 @@
       err_g2:
 	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
       err_g1:
-	*head = (drm_head_t) {
+	*head = (struct drm_head) {
 	.dev = NULL};
 	return ret;
 }
@@ -203,7 +205,7 @@
 int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 		struct drm_driver *driver)
 {
-	drm_device_t *dev;
+	struct drm_device *dev;
 	int ret;
 
 	DRM_DEBUG("\n");
@@ -246,7 +248,7 @@
  * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
  * unregisters the character device.
  */
-int drm_put_dev(drm_device_t * dev)
+int drm_put_dev(struct drm_device * dev)
 {
 	DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
 
@@ -274,7 +276,7 @@
  * last minor released.
  *
  */
-int drm_put_head(drm_head_t * head)
+int drm_put_head(struct drm_head * head)
 {
 	int minor = head->minor;
 
@@ -283,7 +285,7 @@
 	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
 	drm_sysfs_device_remove(head->dev_class);
 
-	*head = (drm_head_t) {.dev = NULL};
+	*head = (struct drm_head) {.dev = NULL};
 
 	drm_heads[minor] = NULL;
 
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index cc8e2eb..cf4349b 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -80,7 +80,7 @@
 
 static ssize_t show_dri(struct class_device *class_device, char *buf)
 {
-	drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev;
+	struct drm_device * dev = ((struct drm_head *)class_get_devdata(class_device))->dev;
 	if (dev->driver->dri_library_name)
 		return dev->driver->dri_library_name(dev, buf);
 	return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
@@ -104,7 +104,7 @@
  * Note: the struct class passed to this function must have previously been
  * created with a call to drm_sysfs_create().
  */
-struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
+struct class_device *drm_sysfs_device_add(struct class *cs, struct drm_head *head)
 {
 	struct class_device *class_dev;
 	int i, j, err;
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index b5c5b9f..68e36e5 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -79,11 +79,11 @@
 static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
 						unsigned long address)
 {
-	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_hash_item_t *hash;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map *map = NULL;
+	struct drm_map_list *r_list;
+	struct drm_hash_item *hash;
 
 	/*
 	 * Find the right map
@@ -97,7 +97,7 @@
 	if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
 		goto vm_nopage_error;
 
-	r_list = drm_hash_entry(hash, drm_map_list_t, hash);
+	r_list = drm_hash_entry(hash, struct drm_map_list, hash);
 	map = r_list->map;
 
 	if (map && map->type == _DRM_AGP) {
@@ -116,7 +116,7 @@
 		/*
 		 * It's AGP memory - find the real physical page to map
 		 */
-		for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
+		list_for_each_entry(agpmem, &dev->agp->memory, head) {
 			if (agpmem->bound <= baddr &&
 			    agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
 				break;
@@ -163,7 +163,7 @@
 static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
 						    unsigned long address)
 {
-	drm_map_t *map = (drm_map_t *) vma->vm_private_data;
+	struct drm_map *map = (struct drm_map *) vma->vm_private_data;
 	unsigned long offset;
 	unsigned long i;
 	struct page *page;
@@ -194,12 +194,11 @@
  */
 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_vma_entry_t *pt, *prev, *next;
-	drm_map_t *map;
-	drm_map_list_t *r_list;
-	struct list_head *list;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_vma_entry *pt, *temp;
+	struct drm_map *map;
+	struct drm_map_list *r_list;
 	int found_maps = 0;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -209,30 +208,22 @@
 	map = vma->vm_private_data;
 
 	mutex_lock(&dev->struct_mutex);
-	for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
-		next = pt->next;
+	list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
 		if (pt->vma->vm_private_data == map)
 			found_maps++;
 		if (pt->vma == vma) {
-			if (prev) {
-				prev->next = pt->next;
-			} else {
-				dev->vmalist = pt->next;
-			}
+			list_del(&pt->head);
 			drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
-		} else {
-			prev = pt;
 		}
 	}
+
 	/* We were the only map that was found */
 	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.
 		 */
 		found_maps = 0;
-		list = &dev->maplist->head;
-		list_for_each(list, &dev->maplist->head) {
-			r_list = list_entry(list, drm_map_list_t, head);
+		list_for_each_entry(r_list, &dev->maplist, head) {
 			if (r_list->map == map)
 				found_maps++;
 		}
@@ -283,9 +274,9 @@
 static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
 						    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;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
 	unsigned long offset;
 	unsigned long page_nr;
 	struct page *page;
@@ -319,10 +310,10 @@
 static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
 						   unsigned long address)
 {
-	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;
+	struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_sg_mem *entry = dev->sg;
 	unsigned long offset;
 	unsigned long map_offset;
 	unsigned long page_offset;
@@ -414,9 +405,9 @@
  */
 static void drm_vm_open_locked(struct vm_area_struct *vma)
 {
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_vma_entry_t *vma_entry;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_vma_entry *vma_entry;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
 		  vma->vm_start, vma->vm_end - vma->vm_start);
@@ -425,16 +416,15 @@
 	vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
 	if (vma_entry) {
 		vma_entry->vma = vma;
-		vma_entry->next = dev->vmalist;
 		vma_entry->pid = current->pid;
-		dev->vmalist = vma_entry;
+		list_add(&vma_entry->head, &dev->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;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	mutex_lock(&dev->struct_mutex);
 	drm_vm_open_locked(vma);
@@ -451,22 +441,18 @@
  */
 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_vma_entry_t *pt, *prev;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_vma_entry *pt, *temp;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
 		  vma->vm_start, vma->vm_end - vma->vm_start);
 	atomic_dec(&dev->vma_count);
 
 	mutex_lock(&dev->struct_mutex);
-	for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+	list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
 		if (pt->vma == vma) {
-			if (prev) {
-				prev->next = pt->next;
-			} else {
-				dev->vmalist = pt->next;
-			}
+			list_del(&pt->head);
 			drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
 			break;
 		}
@@ -486,9 +472,9 @@
  */
 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_device_dma_t *dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
+	struct drm_device_dma *dma;
 	unsigned long length = vma->vm_end - vma->vm_start;
 
 	dev = priv->head->dev;
@@ -526,7 +512,7 @@
 	return 0;
 }
 
-unsigned long drm_core_get_map_ofs(drm_map_t * map)
+unsigned long drm_core_get_map_ofs(struct drm_map * map)
 {
 	return map->offset;
 }
@@ -559,11 +545,11 @@
  */
 static int drm_mmap_locked(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map *map = NULL;
 	unsigned long offset = 0;
-	drm_hash_item_t *hash;
+	struct drm_hash_item *hash;
 
 	DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
 		  vma->vm_start, vma->vm_end, vma->vm_pgoff);
@@ -588,7 +574,7 @@
 		return -EINVAL;
 	}
 
-	map = drm_hash_entry(hash, drm_map_list_t, hash)->map;
+	map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
 	if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
 		return -EPERM;
 
@@ -677,8 +663,8 @@
 
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 603d17f..cb44999 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -45,16 +45,16 @@
 #define I810_BUF_UNMAPPED 0
 #define I810_BUF_MAPPED   1
 
-static drm_buf_t *i810_freelist_get(drm_device_t * dev)
+static struct drm_buf *i810_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *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];
+		struct drm_buf *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,
@@ -70,7 +70,7 @@
  * 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(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	int used;
@@ -87,10 +87,10 @@
 
 static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
 	drm_i810_private_t *dev_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i810_buf_priv_t *buf_priv;
 
 	lock_kernel();
@@ -120,10 +120,10 @@
 	.fasync = drm_fasync,
 };
 
-static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
+static int i810_map_buffer(struct drm_buf * buf, struct file *filp)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	const struct file_operations *old_fops;
@@ -152,7 +152,7 @@
 	return retcode;
 }
 
-static int i810_unmap_buffer(drm_buf_t * buf)
+static int i810_unmap_buffer(struct drm_buf * buf)
 {
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
@@ -172,10 +172,10 @@
 	return retcode;
 }
 
-static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
+static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
 			       struct file *filp)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i810_buf_priv_t *buf_priv;
 	int retcode = 0;
 
@@ -202,9 +202,9 @@
 	return retcode;
 }
 
-static int i810_dma_cleanup(drm_device_t * dev)
+static int i810_dma_cleanup(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
@@ -233,7 +233,7 @@
 		dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
-			drm_buf_t *buf = dma->buflist[i];
+			struct drm_buf *buf = dma->buflist[i];
 			drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 			if (buf_priv->kernel_virtual && buf->total)
@@ -243,7 +243,7 @@
 	return 0;
 }
 
-static int i810_wait_ring(drm_device_t * dev, int n)
+static int i810_wait_ring(struct drm_device * dev, int n)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -276,7 +276,7 @@
 	return iters;
 }
 
-static void i810_kernel_lost_context(drm_device_t * dev)
+static void i810_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -288,9 +288,9 @@
 		ring->space += ring->Size;
 }
 
-static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
+static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int my_idx = 24;
 	u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
 	int i;
@@ -301,7 +301,7 @@
 	}
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		buf_priv->in_use = hw_status++;
@@ -323,16 +323,14 @@
 	return 0;
 }
 
-static int i810_dma_initialize(drm_device_t * dev,
+static int i810_dma_initialize(struct drm_device * dev,
 			       drm_i810_private_t * dev_priv,
 			       drm_i810_init_t * init)
 {
-	struct list_head *list;
-
+	struct drm_map_list *r_list;
 	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);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map &&
 		    r_list->map->type == _DRM_SHM &&
 		    r_list->map->flags & _DRM_CONTAINS_LOCK) {
@@ -478,8 +476,8 @@
 static int i810_dma_init(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv;
 	drm_i810_init_t init;
 	int retcode = 0;
@@ -536,7 +534,7 @@
  * Use 'volatile' & local var tmp to force the emitted values to be
  * identical to the verified ones.
  */
-static void i810EmitContextVerified(drm_device_t * dev,
+static void i810EmitContextVerified(struct drm_device * dev,
 				    volatile unsigned int *code)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -569,7 +567,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
+static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
@@ -602,7 +600,7 @@
 
 /* Need to do some additional checking when setting the dest buffer.
  */
-static void i810EmitDestVerified(drm_device_t * dev,
+static void i810EmitDestVerified(struct drm_device * dev,
 				 volatile unsigned int *code)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -637,7 +635,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i810EmitState(drm_device_t * dev)
+static void i810EmitState(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -668,14 +666,14 @@
 
 /* need to verify
  */
-static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
+static void i810_dma_dispatch_clear(struct drm_device * 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;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = 2;
 	int i;
@@ -743,12 +741,12 @@
 	}
 }
 
-static void i810_dma_dispatch_swap(drm_device_t * dev)
+static void i810_dma_dispatch_swap(struct drm_device * dev)
 {
 	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;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = 2;
 	int i;
@@ -789,13 +787,13 @@
 	}
 }
 
-static void i810_dma_dispatch_vertex(drm_device_t * dev,
-				     drm_buf_t * buf, int discard, int used)
+static void i810_dma_dispatch_vertex(struct drm_device * dev,
+				     struct drm_buf * buf, int discard, int used)
 {
 	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;
+	struct drm_clip_rect *box = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	unsigned long address = (unsigned long)buf->bus_address;
 	unsigned long start = address - dev->agp->base;
@@ -869,7 +867,7 @@
 	}
 }
 
-static void i810_dma_dispatch_flip(drm_device_t * dev)
+static void i810_dma_dispatch_flip(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	int pitch = dev_priv->pitch;
@@ -916,7 +914,7 @@
 
 }
 
-static void i810_dma_quiescent(drm_device_t * dev)
+static void i810_dma_quiescent(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -935,10 +933,10 @@
 	i810_wait_ring(dev, dev_priv->ring.Size - 8);
 }
 
-static int i810_flush_queue(drm_device_t * dev)
+static int i810_flush_queue(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i, ret = 0;
 	RING_LOCALS;
 
@@ -954,7 +952,7 @@
 	i810_wait_ring(dev, dev_priv->ring.Size - 8);
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
@@ -970,9 +968,9 @@
 }
 
 /* Must be called with the lock held */
-static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i810_reclaim_buffers(struct drm_device * dev, struct file *filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma)
@@ -985,7 +983,7 @@
 	i810_flush_queue(dev);
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		if (buf->filp == filp && buf_priv) {
@@ -1003,8 +1001,8 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
@@ -1015,9 +1013,9 @@
 static int i810_dma_vertex(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_device_dma_t *dma = dev->dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *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 *)
@@ -1051,8 +1049,8 @@
 static int i810_clear_bufs(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_clear_t clear;
 
 	if (copy_from_user
@@ -1074,8 +1072,8 @@
 static int i810_swap_bufs(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	DRM_DEBUG("i810_swap_bufs\n");
 
@@ -1088,8 +1086,8 @@
 static int i810_getage(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *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 *)
@@ -1102,8 +1100,8 @@
 static int i810_getbuf(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *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;
@@ -1123,7 +1121,7 @@
 	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((void __user *) arg, &d, sizeof(d)))
 		return -EFAULT;
 	sarea_priv->last_dispatch = (int)hw_status[5];
 
@@ -1144,7 +1142,7 @@
 	return 0;
 }
 
-static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
+static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
 				 unsigned int last_render)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1207,9 +1205,9 @@
 static int i810_dma_mc(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_device_dma_t *dma = dev->dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *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 *)
@@ -1238,8 +1236,8 @@
 static int i810_rstatus(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
 	return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
@@ -1248,8 +1246,8 @@
 static int i810_ov0_info(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 	drm_i810_overlay_t data;
 
@@ -1264,8 +1262,8 @@
 static int i810_fstatus(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1276,8 +1274,8 @@
 static int i810_ov0_flip(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1290,7 +1288,7 @@
 
 /* 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(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
@@ -1300,7 +1298,7 @@
 	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(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
@@ -1315,8 +1313,8 @@
 static int i810_flip_bufs(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1330,7 +1328,7 @@
 	return 0;
 }
 
-int i810_driver_load(drm_device_t *dev, unsigned long flags)
+int i810_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	/* i810 has 4 more counters */
 	dev->counters += 4;
@@ -1342,12 +1340,12 @@
 	return 0;
 }
 
-void i810_driver_lastclose(drm_device_t * dev)
+void i810_driver_lastclose(struct drm_device * dev)
 {
 	i810_dma_cleanup(dev);
 }
 
-void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i810_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1357,12 +1355,12 @@
 	}
 }
 
-void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void i810_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	i810_reclaim_buffers(dev, filp);
 }
 
-int i810_driver_dma_quiescent(drm_device_t * dev)
+int i810_driver_dma_quiescent(struct drm_device * dev)
 {
 	i810_dma_quiescent(dev);
 	return 0;
@@ -1399,7 +1397,7 @@
  * \returns
  * A value of 1 is always retured to indictate every i810 is AGP.
  */
-int i810_driver_device_is_agp(drm_device_t * dev)
+int i810_driver_device_is_agp(struct drm_device * dev)
 {
 	return 1;
 }
diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
index 2deb925..614977d 100644
--- a/drivers/char/drm/i810_drm.h
+++ b/drivers/char/drm/i810_drm.h
@@ -158,7 +158,7 @@
 	unsigned int dirty;
 
 	unsigned int nbox;
-	drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[I810_NR_SAREA_CLIPRECTS];
 
 	/* Maintain an LRU of contiguous regions of texture space.  If
 	 * you think you own a region of texture memory, and it has an
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index e6df49f..6488338 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -77,8 +77,8 @@
 } drm_i810_ring_buffer_t;
 
 typedef struct drm_i810_private {
-	drm_map_t *sarea_map;
-	drm_map_t *mmio_map;
+	struct drm_map *sarea_map;
+	struct drm_map *mmio_map;
 
 	drm_i810_sarea_t *sarea_priv;
 	drm_i810_ring_buffer_t ring;
@@ -88,7 +88,7 @@
 
 	dma_addr_t dma_status_page;
 
-	drm_buf_t *mmap_buffer;
+	struct drm_buf *mmap_buffer;
 
 	u32 front_di1, back_di1, zi1;
 
@@ -115,15 +115,15 @@
 } drm_i810_private_t;
 
 				/* i810_dma.c */
-extern int i810_driver_dma_quiescent(drm_device_t * dev);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern int i810_driver_dma_quiescent(struct drm_device * dev);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
 					       struct file *filp);
 extern int i810_driver_load(struct drm_device *, unsigned long flags);
-extern void i810_driver_lastclose(drm_device_t * dev);
-extern void i810_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern void i810_driver_lastclose(struct drm_device * dev);
+extern void i810_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
 					       struct file *filp);
-extern int i810_driver_device_is_agp(drm_device_t * dev);
+extern int i810_driver_device_is_agp(struct drm_device * dev);
 
 extern drm_ioctl_desc_t i810_ioctls[];
 extern int i810_max_ioctl;
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 3314a9f..dc20c1a 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -47,16 +47,16 @@
 #define I830_BUF_UNMAPPED 0
 #define I830_BUF_MAPPED   1
 
-static drm_buf_t *i830_freelist_get(drm_device_t * dev)
+static struct drm_buf *i830_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *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];
+		struct drm_buf *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,
@@ -72,7 +72,7 @@
  * 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(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	int used;
@@ -89,10 +89,10 @@
 
 static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
 	drm_i830_private_t *dev_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i830_buf_priv_t *buf_priv;
 
 	lock_kernel();
@@ -122,10 +122,10 @@
 	.fasync = drm_fasync,
 };
 
-static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
+static int i830_map_buffer(struct drm_buf * buf, struct file *filp)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	const struct file_operations *old_fops;
@@ -156,7 +156,7 @@
 	return retcode;
 }
 
-static int i830_unmap_buffer(drm_buf_t * buf)
+static int i830_unmap_buffer(struct drm_buf * buf)
 {
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
@@ -176,10 +176,10 @@
 	return retcode;
 }
 
-static int i830_dma_get_buffer(drm_device_t * dev, drm_i830_dma_t * d,
+static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
 			       struct file *filp)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i830_buf_priv_t *buf_priv;
 	int retcode = 0;
 
@@ -206,9 +206,9 @@
 	return retcode;
 }
 
-static int i830_dma_cleanup(drm_device_t * dev)
+static int i830_dma_cleanup(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
@@ -238,7 +238,7 @@
 		dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
-			drm_buf_t *buf = dma->buflist[i];
+			struct drm_buf *buf = dma->buflist[i];
 			drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 			if (buf_priv->kernel_virtual && buf->total)
 				drm_core_ioremapfree(&buf_priv->map, dev);
@@ -247,7 +247,7 @@
 	return 0;
 }
 
-int i830_wait_ring(drm_device_t * dev, int n, const char *caller)
+int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -281,7 +281,7 @@
 	return iters;
 }
 
-static void i830_kernel_lost_context(drm_device_t * dev)
+static void i830_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -296,9 +296,9 @@
 		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(struct drm_device * dev, drm_i830_private_t * dev_priv)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int my_idx = 36;
 	u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
 	int i;
@@ -309,7 +309,7 @@
 	}
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 
 		buf_priv->in_use = hw_status++;
@@ -330,16 +330,15 @@
 	return 0;
 }
 
-static int i830_dma_initialize(drm_device_t * dev,
+static int i830_dma_initialize(struct drm_device * dev,
 			       drm_i830_private_t * dev_priv,
 			       drm_i830_init_t * init)
 {
-	struct list_head *list;
+	struct drm_map_list *r_list;
 
 	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);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map &&
 		    r_list->map->type == _DRM_SHM &&
 		    r_list->map->flags & _DRM_CONTAINS_LOCK) {
@@ -455,8 +454,8 @@
 static int i830_dma_init(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv;
 	drm_i830_init_t init;
 	int retcode = 0;
@@ -490,7 +489,7 @@
 /* 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(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
@@ -535,7 +534,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitTexVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
@@ -569,7 +568,7 @@
 		printk("rejected packet %x\n", code[0]);
 }
 
-static void i830EmitTexBlendVerified(drm_device_t * dev,
+static void i830EmitTexBlendVerified(struct drm_device * dev,
 				     unsigned int *code, unsigned int num)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -594,7 +593,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitTexPalette(drm_device_t * dev,
+static void i830EmitTexPalette(struct drm_device * dev,
 			       unsigned int *palette, int number, int is_shared)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -621,7 +620,7 @@
 
 /* Need to do some additional checking when setting the dest buffer.
  */
-static void i830EmitDestVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	unsigned int tmp;
@@ -682,7 +681,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitStippleVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -693,7 +692,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitState(drm_device_t * dev)
+static void i830EmitState(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -796,7 +795,7 @@
  * Performance monitoring functions
  */
 
-static void i830_fill_box(drm_device_t * dev,
+static void i830_fill_box(struct drm_device * dev,
 			  int x, int y, int w, int h, int r, int g, int b)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -834,7 +833,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830_cp_performance_boxes(drm_device_t * dev)
+static void i830_cp_performance_boxes(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
@@ -879,7 +878,7 @@
 	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(struct drm_device * dev, int flags,
 				    unsigned int clear_color,
 				    unsigned int clear_zval,
 				    unsigned int clear_depthmask)
@@ -887,7 +886,7 @@
 	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;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = dev_priv->cpp;
 	int i;
@@ -974,12 +973,12 @@
 	}
 }
 
-static void i830_dma_dispatch_swap(drm_device_t * dev)
+static void i830_dma_dispatch_swap(struct drm_device * dev)
 {
 	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;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = dev_priv->cpp;
 	int i;
@@ -1044,7 +1043,7 @@
 	}
 }
 
-static void i830_dma_dispatch_flip(drm_device_t * dev)
+static void i830_dma_dispatch_flip(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -1087,13 +1086,13 @@
 	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(struct drm_device * dev,
+				     struct drm_buf * buf, int discard, int used)
 {
 	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;
+	struct drm_clip_rect *box = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	unsigned long address = (unsigned long)buf->bus_address;
 	unsigned long start = address - dev->agp->base;
@@ -1199,7 +1198,7 @@
 	}
 }
 
-static void i830_dma_quiescent(drm_device_t * dev)
+static void i830_dma_quiescent(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -1216,10 +1215,10 @@
 	i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
 }
 
-static int i830_flush_queue(drm_device_t * dev)
+static int i830_flush_queue(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i, ret = 0;
 	RING_LOCALS;
 
@@ -1233,7 +1232,7 @@
 	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];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 
 		int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
@@ -1249,9 +1248,9 @@
 }
 
 /* Must be called with the lock held */
-static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i830_reclaim_buffers(struct drm_device * dev, struct file *filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma)
@@ -1264,7 +1263,7 @@
 	i830_flush_queue(dev);
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 
 		if (buf->filp == filp && buf_priv) {
@@ -1282,8 +1281,8 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
@@ -1294,9 +1293,9 @@
 static int i830_dma_vertex(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_device_dma_t *dma = dev->dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *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 *)
@@ -1328,8 +1327,8 @@
 static int i830_clear_bufs(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_clear_t clear;
 
 	if (copy_from_user
@@ -1352,8 +1351,8 @@
 static int i830_swap_bufs(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	DRM_DEBUG("i830_swap_bufs\n");
 
@@ -1365,7 +1364,7 @@
 
 /* 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(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
@@ -1375,7 +1374,7 @@
 	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(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
@@ -1390,8 +1389,8 @@
 static int i830_flip_bufs(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1408,8 +1407,8 @@
 static int i830_getage(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *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 *)
@@ -1422,8 +1421,8 @@
 static int i830_getbuf(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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *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;
@@ -1444,7 +1443,7 @@
 	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((void __user *) arg, &d, sizeof(d)))
 		return -EFAULT;
 	sarea_priv->last_dispatch = (int)hw_status[5];
 
@@ -1467,8 +1466,8 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_getparam_t param;
 	int value;
@@ -1501,8 +1500,8 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_setparam_t param;
 
@@ -1526,7 +1525,7 @@
 	return 0;
 }
 
-int i830_driver_load(drm_device_t *dev, unsigned long flags)
+int i830_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	/* i830 has 4 more counters */
 	dev->counters += 4;
@@ -1538,12 +1537,12 @@
 	return 0;
 }
 
-void i830_driver_lastclose(drm_device_t * dev)
+void i830_driver_lastclose(struct drm_device * dev)
 {
 	i830_dma_cleanup(dev);
 }
 
-void i830_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i830_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1553,12 +1552,12 @@
 	}
 }
 
-void i830_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	i830_reclaim_buffers(dev, filp);
 }
 
-int i830_driver_dma_quiescent(drm_device_t * dev)
+int i830_driver_dma_quiescent(struct drm_device * dev)
 {
 	i830_dma_quiescent(dev);
 	return 0;
@@ -1594,7 +1593,7 @@
  * \returns
  * A value of 1 is always retured to indictate every i8xx is AGP.
  */
-int i830_driver_device_is_agp(drm_device_t * dev)
+int i830_driver_device_is_agp(struct drm_device * dev)
 {
 	return 1;
 }
diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
index 66dd750..968a6d9 100644
--- a/drivers/char/drm/i830_drm.h
+++ b/drivers/char/drm/i830_drm.h
@@ -191,7 +191,7 @@
 	unsigned int dirty;
 
 	unsigned int nbox;
-	drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[I830_NR_SAREA_CLIPRECTS];
 
 	/* Maintain an LRU of contiguous regions of texture space.  If
 	 * you think you own a region of texture memory, and it has an
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index e91f94a..ddda679 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -84,8 +84,8 @@
 } drm_i830_ring_buffer_t;
 
 typedef struct drm_i830_private {
-	drm_map_t *sarea_map;
-	drm_map_t *mmio_map;
+	struct drm_map *sarea_map;
+	struct drm_map *mmio_map;
 
 	drm_i830_sarea_t *sarea_priv;
 	drm_i830_ring_buffer_t ring;
@@ -95,7 +95,7 @@
 
 	dma_addr_t dma_status_page;
 
-	drm_buf_t *mmap_buffer;
+	struct drm_buf *mmap_buffer;
 
 	u32 front_di1, back_di1, zi1;
 
@@ -132,16 +132,16 @@
 			 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_irq_preinstall(struct drm_device * dev);
+extern void i830_driver_irq_postinstall(struct drm_device * dev);
+extern void i830_driver_irq_uninstall(struct drm_device * dev);
 extern int i830_driver_load(struct drm_device *, unsigned long flags);
-extern void i830_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void i830_driver_lastclose(drm_device_t * dev);
-extern void i830_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern void i830_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void i830_driver_lastclose(struct drm_device * dev);
+extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev,
 					       struct file *filp);
-extern int i830_driver_dma_quiescent(drm_device_t * dev);
-extern int i830_driver_device_is_agp(drm_device_t * dev);
+extern int i830_driver_dma_quiescent(struct drm_device * dev);
+extern int i830_driver_device_is_agp(struct drm_device * dev);
 
 #define I830_READ(reg)          DRM_READ32(dev_priv->mmio_map, reg)
 #define I830_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, reg, val)
@@ -180,7 +180,7 @@
 	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(struct drm_device * dev, int n, const char *caller);
 
 #define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index 5841f76..a1b5c63 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -35,7 +35,7 @@
 
 irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	u16 temp;
 
@@ -53,7 +53,7 @@
 	return IRQ_HANDLED;
 }
 
-static int i830_emit_irq(drm_device_t * dev)
+static int i830_emit_irq(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -70,7 +70,7 @@
 	return atomic_read(&dev_priv->irq_emitted);
 }
 
-static int i830_wait_irq(drm_device_t * dev, int irq_nr)
+static int i830_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	DECLARE_WAITQUEUE(entry, current);
@@ -117,8 +117,8 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_irq_emit_t emit;
 	int result;
@@ -149,8 +149,8 @@
 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;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_irq_wait_t irqwait;
 
@@ -168,7 +168,7 @@
 
 /* drm_dma.h hooks
 */
-void i830_driver_irq_preinstall(drm_device_t * dev)
+void i830_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 
@@ -180,14 +180,14 @@
 	init_waitqueue_head(&dev_priv->irq_queue);
 }
 
-void i830_driver_irq_postinstall(drm_device_t * dev)
+void i830_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 
 	I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
 }
 
-void i830_driver_irq_uninstall(drm_device_t * dev)
+void i830_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	if (!dev_priv)
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index ea52740a..3359cc2 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -47,7 +47,7 @@
  * the head pointer changes, so that EBUSY only happens if the ring
  * actually stalls for (eg) 3 seconds.
  */
-int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
+int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
@@ -73,7 +73,7 @@
 	return DRM_ERR(EBUSY);
 }
 
-void i915_kernel_lost_context(drm_device_t * dev)
+void i915_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
@@ -88,7 +88,7 @@
 		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
 }
 
-static int i915_dma_cleanup(drm_device_t * dev)
+static int i915_dma_cleanup(struct drm_device * dev)
 {
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
@@ -126,13 +126,13 @@
 	return 0;
 }
 
-static int i915_initialize(drm_device_t * dev,
+static int i915_initialize(struct drm_device * dev,
 			   drm_i915_private_t * dev_priv,
 			   drm_i915_init_t * init)
 {
 	memset(dev_priv, 0, sizeof(drm_i915_private_t));
 
-	DRM_GETSAREA();
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("can not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
@@ -211,7 +211,7 @@
 	return 0;
 }
 
-static int i915_dma_resume(drm_device_t * dev)
+static int i915_dma_resume(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -357,7 +357,7 @@
 	return ret;
 }
 
-static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
+static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -396,12 +396,12 @@
 	return 0;
 }
 
-static int i915_emit_box(drm_device_t * dev,
-			 drm_clip_rect_t __user * boxes,
+static int i915_emit_box(struct drm_device * dev,
+			 struct drm_clip_rect __user * boxes,
 			 int i, int DR1, int DR4)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	drm_clip_rect_t box;
+	struct drm_clip_rect box;
 	RING_LOCALS;
 
 	if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
@@ -439,7 +439,7 @@
  * emit. For now, do it in both places:
  */
 
-static void i915_emit_breadcrumb(drm_device_t *dev)
+static void i915_emit_breadcrumb(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -457,7 +457,7 @@
 	ADVANCE_LP_RING();
 }
 
-static int i915_dispatch_cmdbuffer(drm_device_t * dev,
+static int i915_dispatch_cmdbuffer(struct drm_device * dev,
 				   drm_i915_cmdbuffer_t * cmd)
 {
 	int nbox = cmd->num_cliprects;
@@ -489,11 +489,11 @@
 	return 0;
 }
 
-static int i915_dispatch_batchbuffer(drm_device_t * dev,
+static int i915_dispatch_batchbuffer(struct drm_device * dev,
 				     drm_i915_batchbuffer_t * batch)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	drm_clip_rect_t __user *boxes = batch->cliprects;
+	struct drm_clip_rect __user *boxes = batch->cliprects;
 	int nbox = batch->num_cliprects;
 	int i = 0, count;
 	RING_LOCALS;
@@ -535,7 +535,7 @@
 	return 0;
 }
 
-static int i915_dispatch_flip(drm_device_t * dev)
+static int i915_dispatch_flip(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -583,7 +583,7 @@
 	return 0;
 }
 
-static int i915_quiescent(drm_device_t * dev)
+static int i915_quiescent(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
@@ -625,7 +625,7 @@
 
 	if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
 						       batch.num_cliprects *
-						       sizeof(drm_clip_rect_t)))
+						       sizeof(struct drm_clip_rect)))
 		return DRM_ERR(EFAULT);
 
 	ret = i915_dispatch_batchbuffer(dev, &batch);
@@ -655,7 +655,7 @@
 	if (cmdbuf.num_cliprects &&
 	    DRM_VERIFYAREA_READ(cmdbuf.cliprects,
 				cmdbuf.num_cliprects *
-				sizeof(drm_clip_rect_t))) {
+				sizeof(struct drm_clip_rect))) {
 		DRM_ERROR("Fault accessing cliprects\n");
 		return DRM_ERR(EFAULT);
 	}
@@ -792,7 +792,7 @@
 	return 0;
 }
 
-int i915_driver_load(drm_device_t *dev, unsigned long flags)
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	/* i915 has 4 more counters */
 	dev->counters += 4;
@@ -804,7 +804,7 @@
 	return 0;
 }
 
-void i915_driver_lastclose(drm_device_t * dev)
+void i915_driver_lastclose(struct drm_device * dev)
 {
 	if (dev->dev_private) {
 		drm_i915_private_t *dev_priv = dev->dev_private;
@@ -813,7 +813,7 @@
 	i915_dma_cleanup(dev);
 }
 
-void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i915_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_i915_private_t *dev_priv = dev->dev_private;
@@ -854,7 +854,7 @@
  * \returns
  * A value of 1 is always retured to indictate every i9x5 is AGP.
  */
-int i915_driver_device_is_agp(drm_device_t * dev)
+int i915_driver_device_is_agp(struct drm_device * dev)
 {
 	return 1;
 }
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 7b7b68b..05c66cf 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -64,7 +64,7 @@
 } drm_i915_init_t;
 
 typedef struct _drm_i915_sarea {
-	drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
+	struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
 	int last_upload;	/* last time texture was uploaded */
 	int last_enqueue;	/* last time a buffer was enqueued */
 	int last_dispatch;	/* age of the most recently dispatched buffer */
@@ -170,7 +170,7 @@
 	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? */
-	drm_clip_rect_t __user *cliprects;	/* pointer to userspace cliprects */
+	struct drm_clip_rect __user *cliprects;	/* pointer to userspace cliprects */
 } drm_i915_batchbuffer_t;
 
 /* As above, but pass a pointer to userspace buffer which can be
@@ -182,7 +182,7 @@
 	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? */
-	drm_clip_rect_t __user *cliprects;	/* pointer to userspace cliprects */
+	struct drm_clip_rect __user *cliprects;	/* pointer to userspace cliprects */
 } drm_i915_cmdbuffer_t;
 
 /* Userspace can request & wait on irq's:
@@ -259,7 +259,7 @@
  */
 typedef struct drm_i915_vblank_swap {
 	drm_drawable_t drawable;
-	drm_vblank_seq_type_t seqtype;
+	enum drm_vblank_seq_type seqtype;
 	unsigned int sequence;
 } drm_i915_vblank_swap_t;
 
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 85e323a..fd91856 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -120,11 +120,11 @@
 extern int i915_max_ioctl;
 
 				/* i915_dma.c */
-extern void i915_kernel_lost_context(drm_device_t * dev);
+extern void i915_kernel_lost_context(struct drm_device * dev);
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
-extern void i915_driver_lastclose(drm_device_t * dev);
-extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern int i915_driver_device_is_agp(drm_device_t * dev);
+extern void i915_driver_lastclose(struct drm_device * dev);
+extern void i915_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
 
@@ -132,12 +132,12 @@
 extern int i915_irq_emit(DRM_IOCTL_ARGS);
 extern int i915_irq_wait(DRM_IOCTL_ARGS);
 
-extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
 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(struct drm_device * dev);
+extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern void i915_driver_irq_uninstall(struct drm_device * dev);
 extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
 extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
 extern int i915_vblank_swap(DRM_IOCTL_ARGS);
@@ -148,7 +148,7 @@
 extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
 extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
 extern void i915_mem_takedown(struct mem_block **heap);
-extern void i915_mem_release(drm_device_t * dev,
+extern void i915_mem_release(struct drm_device * dev,
 			     DRMFILE filp, struct mem_block *heap);
 
 #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
@@ -188,7 +188,7 @@
 	I915_WRITE(LP_RING + RING_TAIL, outring);			\
 } while(0)
 
-extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 #define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index b92062a..4b4b2ce 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -42,7 +42,7 @@
  *
  * This function will be called with the HW lock held.
  */
-static void i915_vblank_tasklet(drm_device_t *dev)
+static void i915_vblank_tasklet(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
@@ -50,7 +50,7 @@
 	int nhits, nrects, slice[2], upper[2], lower[2], i;
 	unsigned counter[2] = { atomic_read(&dev->vbl_received),
 				atomic_read(&dev->vbl_received2) };
-	drm_drawable_info_t *drw;
+	struct drm_drawable_info *drw;
 	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	u32 cpp = dev_priv->cpp;
 	u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
@@ -95,7 +95,7 @@
 		list_for_each(hit, &hits) {
 			drm_i915_vbl_swap_t *swap_cmp =
 				list_entry(hit, drm_i915_vbl_swap_t, head);
-			drm_drawable_info_t *drw_cmp =
+			struct drm_drawable_info *drw_cmp =
 				drm_get_drawable_info(dev, swap_cmp->drw_id);
 
 			if (drw_cmp &&
@@ -160,7 +160,7 @@
 		list_for_each(hit, &hits) {
 			drm_i915_vbl_swap_t *swap_hit =
 				list_entry(hit, drm_i915_vbl_swap_t, head);
-			drm_clip_rect_t *rect;
+			struct drm_clip_rect *rect;
 			int num_rects, pipe;
 			unsigned short top, bottom;
 
@@ -211,7 +211,7 @@
 
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u16 temp;
 
@@ -257,7 +257,7 @@
 	return IRQ_HANDLED;
 }
 
-static int i915_emit_irq(drm_device_t * dev)
+static int i915_emit_irq(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -283,7 +283,7 @@
 	return dev_priv->counter;
 }
 
-static int i915_wait_irq(drm_device_t * dev, int irq_nr)
+static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int ret = 0;
@@ -309,7 +309,7 @@
 	return ret;
 }
 
-static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
 				      atomic_t *counter)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -331,12 +331,12 @@
 }
 
 
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
 {
 	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
 }
 
-int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
 {
 	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
 }
@@ -389,7 +389,7 @@
 	return i915_wait_irq(dev, irqwait.irq_seq);
 }
 
-static void i915_enable_interrupt (drm_device_t *dev)
+static void i915_enable_interrupt (struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u16 flag;
@@ -569,7 +569,7 @@
 
 /* drm_dma.h hooks
 */
-void i915_driver_irq_preinstall(drm_device_t * dev)
+void i915_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -578,7 +578,7 @@
 	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 }
 
-void i915_driver_irq_postinstall(drm_device_t * dev)
+void i915_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -592,7 +592,7 @@
 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 }
 
-void i915_driver_irq_uninstall(drm_device_t * dev)
+void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u16 temp;
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index 52c6732..50b4bac 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -43,11 +43,11 @@
  * block to allocate, and the ring is drained prior to allocations --
  * in other words allocation is expensive.
  */
-static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
+static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_tex_region_t *list;
+	struct drm_tex_region *list;
 	unsigned shift, nr;
 	unsigned start;
 	unsigned end;
@@ -208,7 +208,7 @@
 
 /* Free all blocks associated with the releasing file.
  */
-void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
+void i915_mem_release(struct drm_device * dev, DRMFILE filp, struct mem_block *heap)
 {
 	struct mem_block *p;
 
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index c2a4bac..9c73a6e 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -46,7 +46,7 @@
 
 #define MINIMAL_CLEANUP 0
 #define FULL_CLEANUP 1
-static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup);
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
 
 /* ================================================================
  * Engine control
@@ -224,7 +224,7 @@
 #define MGA_BUFFER_FREE		0
 
 #if MGA_FREELIST_DEBUG
-static void mga_freelist_print(drm_device_t * dev)
+static void mga_freelist_print(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *entry;
@@ -245,10 +245,10 @@
 }
 #endif
 
-static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
+static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_freelist_t *entry;
 	int i;
@@ -291,7 +291,7 @@
 	return 0;
 }
 
-static void mga_freelist_cleanup(drm_device_t * dev)
+static void mga_freelist_cleanup(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *entry;
@@ -311,10 +311,10 @@
 #if 0
 /* FIXME: Still needed?
  */
-static void mga_freelist_reset(drm_device_t * dev)
+static void mga_freelist_reset(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	int i;
 
@@ -326,7 +326,7 @@
 }
 #endif
 
-static drm_buf_t *mga_freelist_get(drm_device_t * dev)
+static struct drm_buf *mga_freelist_get(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *next;
@@ -359,7 +359,7 @@
 	return NULL;
 }
 
-int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -393,7 +393,7 @@
  * DMA initialization, cleanup
  */
 
-int mga_driver_load(drm_device_t * dev, unsigned long flags)
+int mga_driver_load(struct drm_device * dev, unsigned long flags)
 {
 	drm_mga_private_t *dev_priv;
 
@@ -434,7 +434,7 @@
  *
  * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
  */
-static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
 				    drm_mga_dma_bootstrap_t * dma_bs)
 {
 	drm_mga_private_t *const dev_priv =
@@ -445,11 +445,11 @@
 	const unsigned secondary_size = dma_bs->secondary_bin_count
 	    * 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;
-	drm_agp_buffer_t agp_req;
-	drm_agp_binding_t bind_req;
+	struct drm_buf_desc req;
+	struct drm_agp_mode mode;
+	struct drm_agp_info info;
+	struct drm_agp_buffer agp_req;
+	struct drm_agp_binding bind_req;
 
 	/* Acquire AGP. */
 	err = drm_agp_acquire(dev);
@@ -548,10 +548,10 @@
 	}
 
 	{
-		drm_map_list_t *_entry;
+		struct drm_map_list *_entry;
 		unsigned long agp_token = 0;
 		
-		list_for_each_entry(_entry, &dev->maplist->head, head) {
+		list_for_each_entry(_entry, &dev->maplist, head) {
 			if (_entry->map == dev->agp_buffer_map)
 				agp_token = _entry->user_token;
 		}
@@ -588,7 +588,7 @@
 	return 0;
 }
 #else
-static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
 				    drm_mga_dma_bootstrap_t * dma_bs)
 {
 	return -EINVAL;
@@ -609,7 +609,7 @@
  *
  * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
  */
-static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
 				    drm_mga_dma_bootstrap_t * dma_bs)
 {
 	drm_mga_private_t *const dev_priv =
@@ -618,7 +618,7 @@
 	unsigned int primary_size;
 	unsigned int bin_count;
 	int err;
-	drm_buf_desc_t req;
+	struct drm_buf_desc req;
 
 	if (dev->dma == NULL) {
 		DRM_ERROR("dev->dma is NULL\n");
@@ -699,7 +699,7 @@
 	return 0;
 }
 
-static int mga_do_dma_bootstrap(drm_device_t * dev,
+static int mga_do_dma_bootstrap(struct drm_device * dev,
 				drm_mga_dma_bootstrap_t * dma_bs)
 {
 	const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
@@ -793,7 +793,7 @@
 	return err;
 }
 
-static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
+static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
 {
 	drm_mga_private_t *dev_priv;
 	int ret;
@@ -823,8 +823,7 @@
 	dev_priv->texture_offset = init->texture_offset[0];
 	dev_priv->texture_size = init->texture_size[0];
 
-	DRM_GETSAREA();
-
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("failed to find sarea!\n");
 		return DRM_ERR(EINVAL);
@@ -934,7 +933,7 @@
 	return 0;
 }
 
-static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
 {
 	int err = 0;
 	DRM_DEBUG("\n");
@@ -963,8 +962,8 @@
 		if (dev_priv->used_new_dma_init) {
 #if __OS_HAS_AGP
 			if (dev_priv->agp_handle != 0) {
-				drm_agp_binding_t unbind_req;
-				drm_agp_buffer_t free_req;
+				struct drm_agp_binding unbind_req;
+				struct drm_agp_buffer free_req;
 
 				unbind_req.handle = dev_priv->agp_handle;
 				drm_agp_unbind(dev, &unbind_req);
@@ -1041,11 +1040,11 @@
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-	drm_lock_t lock;
+	struct drm_lock lock;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
+	DRM_COPY_FROM_USER_IOCTL(lock, (struct drm_lock __user *) data,
 				 sizeof(lock));
 
 	DRM_DEBUG("%s%s%s\n",
@@ -1087,9 +1086,9 @@
  * 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, struct drm_device * dev, struct drm_dma * d)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
@@ -1114,10 +1113,10 @@
 int mga_dma_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	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;
+	struct drm_dma __user *argp = (void __user *)data;
+	struct drm_dma d;
 	int ret = 0;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1156,7 +1155,7 @@
 /**
  * Called just before the module is unloaded.
  */
-int mga_driver_unload(drm_device_t * dev)
+int mga_driver_unload(struct drm_device * dev)
 {
 	drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
 	dev->dev_private = NULL;
@@ -1167,12 +1166,12 @@
 /**
  * Called when the last opener of the device is closed.
  */
-void mga_driver_lastclose(drm_device_t * dev)
+void mga_driver_lastclose(struct drm_device * dev)
 {
 	mga_do_cleanup_dma(dev, FULL_CLEANUP);
 }
 
-int mga_driver_dma_quiescent(drm_device_t * dev)
+int mga_driver_dma_quiescent(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	return mga_do_wait_for_idle(dev_priv);
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
index 44d1293..944b50a 100644
--- a/drivers/char/drm/mga_drm.h
+++ b/drivers/char/drm/mga_drm.h
@@ -181,7 +181,7 @@
 
 	/* The current cliprects, or a subset thereof.
 	 */
-	drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS];
 	unsigned int nbox;
 
 	/* Information about the most recently used 3d drawable.  The
@@ -202,7 +202,7 @@
 	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];
+	struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS];
 
 	/* Counters for aging textures and for client-side throttling.
 	 */
@@ -216,7 +216,7 @@
 
 	/* 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];
+	struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
 	unsigned int texAge[MGA_NR_TEX_HEAPS];
 
 	/* Mechanism to validate card state.
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index be49dbb..5572939 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -36,7 +36,7 @@
 
 #include "drm_pciids.h"
 
-static int mga_driver_device_is_agp(drm_device_t * dev);
+static int mga_driver_device_is_agp(struct drm_device * dev);
 
 static struct pci_device_id pciidlist[] = {
 	mga_PCI_IDS
@@ -118,7 +118,7 @@
  * \returns
  * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
  */
-static int mga_driver_device_is_agp(drm_device_t * dev)
+static int mga_driver_device_is_agp(struct drm_device * dev)
 {
 	const struct pci_dev *const pdev = dev->pdev;
 
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 6b0c531..49253af 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -65,7 +65,7 @@
 	struct drm_mga_freelist *next;
 	struct drm_mga_freelist *prev;
 	drm_mga_age_t age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 } drm_mga_freelist_t;
 
 typedef struct {
@@ -157,10 +157,10 @@
 extern int mga_dma_flush(DRM_IOCTL_ARGS);
 extern int mga_dma_reset(DRM_IOCTL_ARGS);
 extern int mga_dma_buffers(DRM_IOCTL_ARGS);
-extern int mga_driver_load(drm_device_t *dev, unsigned long flags);
-extern int mga_driver_unload(drm_device_t * dev);
-extern void mga_driver_lastclose(drm_device_t * dev);
-extern int mga_driver_dma_quiescent(drm_device_t * dev);
+extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
+extern int mga_driver_unload(struct drm_device * dev);
+extern void mga_driver_lastclose(struct drm_device * dev);
+extern int mga_driver_dma_quiescent(struct drm_device * dev);
 
 extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
 
@@ -168,7 +168,7 @@
 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(struct drm_device * dev, struct drm_buf * buf);
 
 				/* mga_warp.c */
 extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
@@ -176,12 +176,12 @@
 extern int mga_warp_init(drm_mga_private_t * dev_priv);
 
 				/* mga_irq.c */
-extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
-extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mga_driver_irq_preinstall(drm_device_t * dev);
-extern void mga_driver_irq_postinstall(drm_device_t * dev);
-extern void mga_driver_irq_uninstall(drm_device_t * dev);
+extern void mga_driver_irq_preinstall(struct drm_device * dev);
+extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern void mga_driver_irq_uninstall(struct drm_device * dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 			     unsigned long arg);
 
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index eb96440..9302cb8 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -37,7 +37,7 @@
 
 irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	int status;
 	int handled = 0;
@@ -78,7 +78,7 @@
 	return IRQ_NONE;
 }
 
-int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
@@ -96,7 +96,7 @@
 	return ret;
 }
 
-int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	unsigned int cur_fence;
@@ -115,7 +115,7 @@
 	return ret;
 }
 
-void mga_driver_irq_preinstall(drm_device_t * dev)
+void mga_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
@@ -125,7 +125,7 @@
 	MGA_WRITE(MGA_ICLEAR, ~0);
 }
 
-void mga_driver_irq_postinstall(drm_device_t * dev)
+void mga_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
@@ -135,7 +135,7 @@
 	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
 }
 
-void mga_driver_irq_uninstall(drm_device_t * dev)
+void mga_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	if (!dev_priv)
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index 2837e66..d448b0a 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -42,7 +42,7 @@
  */
 
 static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
-			       drm_clip_rect_t * box)
+			       struct drm_clip_rect * box)
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -480,12 +480,12 @@
  *
  */
 
-static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
+static void mga_dma_dispatch_clear(struct drm_device * 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;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	int i;
 	DMA_LOCALS;
@@ -500,7 +500,7 @@
 	ADVANCE_DMA();
 
 	for (i = 0; i < nbox; i++) {
-		drm_clip_rect_t *box = &pbox[i];
+		struct drm_clip_rect *box = &pbox[i];
 		u32 height = box->y2 - box->y1;
 
 		DRM_DEBUG("   from=%d,%d to=%d,%d\n",
@@ -568,12 +568,12 @@
 	FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_swap(drm_device_t * dev)
+static void mga_dma_dispatch_swap(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	int i;
 	DMA_LOCALS;
@@ -598,7 +598,7 @@
 		  MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
 
 	for (i = 0; i < nbox; i++) {
-		drm_clip_rect_t *box = &pbox[i];
+		struct drm_clip_rect *box = &pbox[i];
 		u32 height = box->y2 - box->y1;
 		u32 start = box->y1 * dev_priv->front_pitch;
 
@@ -622,7 +622,7 @@
 	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(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -669,7 +669,7 @@
 	FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
+static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
 				     unsigned int start, unsigned int end)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -718,7 +718,7 @@
 /* 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,
+static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
 				   unsigned int dstorg, unsigned int length)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -766,12 +766,12 @@
 	FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
+static void mga_dma_dispatch_blit(struct drm_device * 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;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	u32 scandir = 0, i;
 	DMA_LOCALS;
@@ -880,8 +880,8 @@
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_vertex_t vertex;
 
@@ -920,8 +920,8 @@
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_indices_t indices;
 
@@ -959,9 +959,9 @@
 static int mga_dma_iload(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_iload_t iload;
 	DRM_DEBUG("\n");
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 1014602..b163ed0 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -81,7 +81,7 @@
 	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(struct drm_device * dev, int addr)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 
@@ -271,7 +271,7 @@
 
 /* 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(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
@@ -308,7 +308,7 @@
 	return 0;
 }
 
-static void r128_cce_init_ring_buffer(drm_device_t * dev,
+static void r128_cce_init_ring_buffer(struct drm_device * dev,
 				      drm_r128_private_t * dev_priv)
 {
 	u32 ring_start;
@@ -347,7 +347,7 @@
 	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(struct drm_device * dev, drm_r128_init_t * init)
 {
 	drm_r128_private_t *dev_priv;
 
@@ -456,8 +456,7 @@
 	dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
 					 (dev_priv->span_offset >> 5));
 
-	DRM_GETSAREA();
-
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
@@ -585,7 +584,7 @@
 	return 0;
 }
 
-int r128_do_cleanup_cce(drm_device_t * dev)
+int r128_do_cleanup_cce(struct drm_device * dev)
 {
 
 	/* Make sure interrupts are disabled here because the uninstall ioctl
@@ -770,11 +769,11 @@
 #define R128_BUFFER_FREE	0
 
 #if 0
-static int r128_freelist_init(drm_device_t * dev)
+static int r128_freelist_init(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_freelist_t *entry;
 	int i;
@@ -816,12 +815,12 @@
 }
 #endif
 
-static drm_buf_t *r128_freelist_get(drm_device_t * dev)
+static struct drm_buf *r128_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_buf_priv_t *buf_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i, t;
 
 	/* FIXME: Optimize -- use freelist code */
@@ -854,13 +853,13 @@
 	return NULL;
 }
 
-void r128_freelist_reset(drm_device_t * dev)
+void r128_freelist_reset(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_r128_buf_priv_t *buf_priv = buf->dev_private;
 		buf_priv->age = 0;
 	}
@@ -887,10 +886,10 @@
 	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, struct drm_device * dev, struct drm_dma * d)
 {
 	int i;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
 		buf = r128_freelist_get(dev);
@@ -914,10 +913,10 @@
 int r128_cce_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int ret = 0;
-	drm_dma_t __user *argp = (void __user *)data;
-	drm_dma_t d;
+	struct drm_dma __user *argp = (void __user *)data;
+	struct drm_dma d;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 6e8af31..e94a39c 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -153,7 +153,7 @@
 
 	/* The current cliprects, or a subset thereof.
 	 */
-	drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS];
 	unsigned int nbox;
 
 	/* Counters for client-side throttling of rendering clients.
@@ -161,7 +161,7 @@
 	unsigned int last_frame;
 	unsigned int last_dispatch;
 
-	drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
+	struct drm_tex_region 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) */
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 9086835..72249fb 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -57,7 +57,7 @@
 
 typedef struct drm_r128_freelist {
 	unsigned int age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	struct drm_r128_freelist *next;
 	struct drm_r128_freelist *prev;
 } drm_r128_freelist_t;
@@ -118,7 +118,7 @@
 	drm_local_map_t *cce_ring;
 	drm_local_map_t *ring_rptr;
 	drm_local_map_t *agp_textures;
-	drm_ati_pcigart_info gart_info;
+	struct drm_ati_pcigart_info gart_info;
 } drm_r128_private_t;
 
 typedef struct drm_r128_buf_priv {
@@ -142,21 +142,21 @@
 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 void r128_freelist_reset(struct drm_device * 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_do_cleanup_cce(struct drm_device * dev);
 
-extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int r128_driver_vblank_wait(struct drm_device * 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_lastclose(drm_device_t * dev);
-extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void r128_driver_irq_preinstall(struct drm_device * dev);
+extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern void r128_driver_irq_uninstall(struct drm_device * dev);
+extern void r128_driver_lastclose(struct drm_device * dev);
+extern void r128_driver_preclose(struct drm_device * dev, DRMFILE filp);
 
 extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index 87f8ca2..c76fdca 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -37,7 +37,7 @@
 
 irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 	int status;
 
@@ -54,7 +54,7 @@
 	return IRQ_NONE;
 }
 
-int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
@@ -72,7 +72,7 @@
 	return ret;
 }
 
-void r128_driver_irq_preinstall(drm_device_t * dev)
+void r128_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 
@@ -82,7 +82,7 @@
 	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
 }
 
-void r128_driver_irq_postinstall(drm_device_t * dev)
+void r128_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 
@@ -90,7 +90,7 @@
 	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
 }
 
-void r128_driver_irq_uninstall(drm_device_t * dev)
+void r128_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 	if (!dev_priv)
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 17b11e7..7b334fb 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -38,7 +38,7 @@
  */
 
 static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
-				 drm_clip_rect_t * boxes, int count)
+				 struct drm_clip_rect * boxes, int count)
 {
 	u32 aux_sc_cntl = 0x00000000;
 	RING_LOCALS;
@@ -352,13 +352,13 @@
 		 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
 }
 
-static void r128_cce_dispatch_clear(drm_device_t * dev,
+static void r128_cce_dispatch_clear(struct drm_device * 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;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	unsigned int flags = clear->flags;
 	int i;
 	RING_LOCALS;
@@ -458,12 +458,12 @@
 	}
 }
 
-static void r128_cce_dispatch_swap(drm_device_t * dev)
+static void r128_cce_dispatch_swap(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -524,7 +524,7 @@
 	ADVANCE_RING();
 }
 
-static void r128_cce_dispatch_flip(drm_device_t * dev)
+static void r128_cce_dispatch_flip(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -567,7 +567,7 @@
 	ADVANCE_RING();
 }
 
-static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -637,8 +637,8 @@
 	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(struct drm_device * dev,
+				       struct drm_buf * buf, int start, int end)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -692,8 +692,8 @@
 	dev_priv->sarea_priv->last_dispatch++;
 }
 
-static void r128_cce_dispatch_indices(drm_device_t * dev,
-				      drm_buf_t * buf,
+static void r128_cce_dispatch_indices(struct drm_device * dev,
+				      struct drm_buf * buf,
 				      int start, int end, int count)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -777,11 +777,11 @@
 }
 
 static int r128_cce_dispatch_blit(DRMFILE filp,
-				  drm_device_t * dev, drm_r128_blit_t * blit)
+				  struct drm_device * dev, drm_r128_blit_t * blit)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	u32 *data;
 	int dword_shift, dwords;
@@ -887,7 +887,7 @@
  * have hardware stencil support.
  */
 
-static int r128_cce_dispatch_write_span(drm_device_t * dev,
+static int r128_cce_dispatch_write_span(struct drm_device * dev,
 					drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -983,7 +983,7 @@
 	return 0;
 }
 
-static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
 					  drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1105,7 +1105,7 @@
 	return 0;
 }
 
-static int r128_cce_dispatch_read_span(drm_device_t * dev,
+static int r128_cce_dispatch_read_span(struct drm_device * dev,
 				       drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1148,7 +1148,7 @@
 	return 0;
 }
 
-static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
 					 drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1220,7 +1220,7 @@
  * Polygon stipple
  */
 
-static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -1269,7 +1269,7 @@
 	return 0;
 }
 
-static int r128_do_init_pageflip(drm_device_t * dev)
+static int r128_do_init_pageflip(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG("\n");
@@ -1288,7 +1288,7 @@
 	return 0;
 }
 
-static int r128_do_cleanup_pageflip(drm_device_t * dev)
+static int r128_do_cleanup_pageflip(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG("\n");
@@ -1354,8 +1354,8 @@
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_vertex_t vertex;
 
@@ -1413,8 +1413,8 @@
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_indices_t elts;
 	int count;
@@ -1483,7 +1483,7 @@
 static int r128_cce_blit(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_blit_t blit;
 	int ret;
@@ -1571,8 +1571,8 @@
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_indirect_t indirect;
 #if 0
@@ -1675,7 +1675,7 @@
 	return 0;
 }
 
-void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void r128_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1685,7 +1685,7 @@
 	}
 }
 
-void r128_driver_lastclose(drm_device_t * dev)
+void r128_driver_lastclose(struct drm_device * dev)
 {
 	r128_do_cleanup_cce(dev);
 }
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index 032a022..4e5aca6 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -55,7 +55,7 @@
 static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
 			       drm_radeon_kcmd_buffer_t *cmdbuf, int n)
 {
-	drm_clip_rect_t box;
+	struct drm_clip_rect box;
 	int nr;
 	int i;
 	RING_LOCALS;
@@ -148,15 +148,16 @@
 
 	/* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
 	ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
-	ADD_RANGE(0x2080, 1);
+	ADD_RANGE(R300_VAP_CNTL, 1);
 	ADD_RANGE(R300_SE_VTE_CNTL, 2);
 	ADD_RANGE(0x2134, 2);
-	ADD_RANGE(0x2140, 1);
+	ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
 	ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
 	ADD_RANGE(0x21DC, 1);
-	ADD_RANGE(0x221C, 1);
-	ADD_RANGE(0x2220, 4);
-	ADD_RANGE(0x2288, 1);
+	ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
+	ADD_RANGE(R300_VAP_CLIP_X_0, 4);
+	ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
+	ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
 	ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
 	ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
 	ADD_RANGE(R300_GB_ENABLE, 1);
@@ -168,13 +169,13 @@
 	ADD_RANGE(R300_RE_POINTSIZE, 1);
 	ADD_RANGE(0x4230, 3);
 	ADD_RANGE(R300_RE_LINE_CNT, 1);
-	ADD_RANGE(0x4238, 1);
+	ADD_RANGE(R300_RE_UNK4238, 1);
 	ADD_RANGE(0x4260, 3);
-	ADD_RANGE(0x4274, 4);
-	ADD_RANGE(0x4288, 5);
-	ADD_RANGE(0x42A0, 1);
+	ADD_RANGE(R300_RE_SHADE, 4);
+	ADD_RANGE(R300_RE_POLYGON_MODE, 5);
+	ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
 	ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
-	ADD_RANGE(0x42B4, 1);
+	ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
 	ADD_RANGE(R300_RE_CULL_CNTL, 1);
 	ADD_RANGE(0x42C0, 2);
 	ADD_RANGE(R300_RS_CNTL_0, 2);
@@ -190,22 +191,22 @@
 	ADD_RANGE(R300_PFS_INSTR1_0, 64);
 	ADD_RANGE(R300_PFS_INSTR2_0, 64);
 	ADD_RANGE(R300_PFS_INSTR3_0, 64);
-	ADD_RANGE(0x4BC0, 1);
-	ADD_RANGE(0x4BC8, 3);
+	ADD_RANGE(R300_RE_FOG_STATE, 1);
+	ADD_RANGE(R300_FOG_COLOR_R, 3);
 	ADD_RANGE(R300_PP_ALPHA_TEST, 2);
 	ADD_RANGE(0x4BD8, 1);
 	ADD_RANGE(R300_PFS_PARAM_0_X, 64);
 	ADD_RANGE(0x4E00, 1);
 	ADD_RANGE(R300_RB3D_CBLEND, 2);
 	ADD_RANGE(R300_RB3D_COLORMASK, 1);
-	ADD_RANGE(0x4E10, 3);
+	ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
 	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(R300_RB3D_ZSTENCIL_FORMAT, 4);
 	ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);	/* check offset */
 	ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
 	ADD_RANGE(0x4F28, 1);
@@ -224,7 +225,7 @@
 	ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
 
 	/* Sporadic registers used as primitives are emitted */
-	ADD_RANGE(0x4f18, 1);
+	ADD_RANGE(R300_RB3D_ZCACHE_CTLSTAT, 1);
 	ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
 	ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
 	ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
@@ -692,9 +693,9 @@
 
 	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(R300_RB3D_DSTCACHE_UNKNOWN_0A);
+	OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
+	OUT_RING(R300_RB3D_ZCACHE_UNKNOWN_03);
 	OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
 	OUT_RING(0x0);
 	ADVANCE_RING();
@@ -705,7 +706,7 @@
  * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
  * be careful about how this function is called.
  */
-static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -766,8 +767,8 @@
 	}
 	
 	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0));
-	OUT_RING(dev_priv->scratch_ages[header.scratch.reg]);
+	OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
+	OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
 	ADVANCE_RING();
 	
 	return 0;
@@ -778,14 +779,14 @@
  * commands on the DMA ring buffer.
  * Called by the ioctl handler function radeon_cp_cmdbuf.
  */
-int r300_do_cp_cmdbuf(drm_device_t *dev,
+int r300_do_cp_cmdbuf(struct drm_device *dev,
 		      DRMFILE filp,
-		      drm_file_t *filp_priv,
+		      struct drm_file *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;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf = NULL;
 	int emit_dispatch_age = 0;
 	int ret = 0;
 
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index ecda760..3ae57ec 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -47,12 +47,12 @@
 #	define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT	28
 
 /*
-This file contains registers and constants for the R300. They have been
-found mostly by examining command buffers captured using glxtest, as well
-as by extrapolating some known registers and constants from the R200.
-
-I am fairly certain that they are correct unless stated otherwise in comments.
-*/
+ * This file contains registers and constants for the R300. They have been
+ * found mostly by examining command buffers captured using glxtest, as well
+ * as by extrapolating some known registers and constants from the R200.
+ * I am fairly certain that they are correct unless stated otherwise
+ * in comments.
+ */
 
 #define R300_SE_VPORT_XSCALE                0x1D98
 #define R300_SE_VPORT_XOFFSET               0x1D9C
@@ -61,49 +61,60 @@
 #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 */
+
+/*
+ * Vertex Array Processing (VAP) Control
+ * Stolen from r200 code from Christoph Brill (It's a guess!)
+ */
+#define R300_VAP_CNTL	0x2080
+
+/* This register is written directly and also starts data section
+ * in many 3d CP_PACKET3's
+ */
 #define R300_VAP_VF_CNTL	0x2084
+#	define	R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT              0
+#	define  R300_VAP_VF_CNTL__PRIM_NONE                     (0<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_POINTS                   (1<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_LINES                    (2<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_LINE_STRIP               (3<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLES                (4<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN             (5<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP           (6<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_LINE_LOOP                (12<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_QUADS                    (13<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_QUAD_STRIP               (14<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_POLYGON                  (15<<0)
 
-#	define	R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT                       0
-#	define  R300_VAP_VF_CNTL__PRIM_NONE				 (0<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_POINTS				 (1<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_LINES				 (2<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_LINE_STRIP			 (3<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLES			 (4<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN			 (5<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP			 (6<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_LINE_LOOP			 (12<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_QUADS			 	 (13<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_QUAD_STRIP			 (14<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_POLYGON			 	 (15<<0)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK__SHIFT              4
+	/* State based - direct writes to registers trigger vertex
+           generation */
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED         (0<<4)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_INDICES             (1<<4)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST         (2<<4)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED     (3<<4)
 
-#	define	R300_VAP_VF_CNTL__PRIM_WALK__SHIFT                       4
-	/* State based - direct writes to registers trigger vertex generation */
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED                      (0<<4)
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_INDICES                          (1<<4)
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST                      (2<<4)
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED                  (3<<4)
+	/* I don't think I saw these three used.. */
+#	define	R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT            6
+#	define	R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT     9
+#	define	R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT        10
 
-		/* I don't think I saw these three used.. */
-#	define	R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT                     6
-#	define	R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT              9
-#	define	R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT                 10
-
-		/* 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 */
-#	define	R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT                    16
+	/* 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 */
+#	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
+	/* each of the following is 3 bits wide, specifies number
+	   of components */
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
@@ -112,7 +123,7 @@
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
-/* END */
+/* END: Wild guesses */
 
 #define R300_SE_VTE_CNTL                  0x20b0
 #	define     R300_VPORT_X_SCALE_ENA                0x00000001
@@ -128,43 +139,54 @@
 #	define     R300_VTX_ST_DENORMALIZED              0x00001000
 
 /* BEGIN: Vertex data assembly - lots of uncertainties */
-/* gap */
-/* Where do we get our vertex data?
-//
-// Vertex data either comes either from immediate mode registers or from
-// vertex arrays.
-// There appears to be no mixed mode (though we can force the pitch of
-// vertex arrays to 0, effectively reusing the same element over and over
-// again).
-//
-// Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
-// if these registers influence vertex array processing.
-//
-// Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
-//
-// In both cases, vertex attributes are then passed through INPUT_ROUTE.
 
-// Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
-// into the vertex processor's input registers.
-// The first word routes the first input, the second word the second, etc.
-// The corresponding input is routed into the register with the given index.
-// The list is ended by a word with INPUT_ROUTE_END set.
-//
-// Always set COMPONENTS_4 in immediate mode. */
+/* gap */
+
+#define R300_VAP_CNTL_STATUS              0x2140
+#	define R300_VC_NO_SWAP                  (0 << 0)
+#	define R300_VC_16BIT_SWAP               (1 << 0)
+#	define R300_VC_32BIT_SWAP               (2 << 0)
+#	define R300_VAP_TCL_BYPASS		(1 << 8)
+
+/* gap */
+
+/* Where do we get our vertex data?
+ *
+ * Vertex data either comes either from immediate mode registers or from
+ * vertex arrays.
+ * There appears to be no mixed mode (though we can force the pitch of
+ * vertex arrays to 0, effectively reusing the same element over and over
+ * again).
+ *
+ * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
+ * if these registers influence vertex array processing.
+ *
+ * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
+ *
+ * In both cases, vertex attributes are then passed through INPUT_ROUTE.
+ *
+ * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
+ * into the vertex processor's input registers.
+ * The first word routes the first input, the second word the second, etc.
+ * The corresponding input is routed into the register with the given index.
+ * The list is ended by a word with INPUT_ROUTE_END set.
+ *
+ * Always set COMPONENTS_4 in immediate mode.
+ */
 
 #define R300_VAP_INPUT_ROUTE_0_0            0x2150
 #       define R300_INPUT_ROUTE_COMPONENTS_1     (0 << 0)
 #       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
@@ -174,10 +196,12 @@
 #define R300_VAP_INPUT_ROUTE_0_7            0x216C
 
 /* gap */
+
 /* Notes:
-//  - always set up to produce at least two attributes:
-//    if vertex program uses only position, fglrx will set normal, too
-//  - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal */
+ *  - always set up to produce at least two attributes:
+ *    if vertex program uses only position, fglrx will set normal, too
+ *  - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal.
+ */
 #define R300_VAP_INPUT_CNTL_0               0x2180
 #       define R300_INPUT_CNTL_0_COLOR           0x00000001
 #define R300_VAP_INPUT_CNTL_1               0x2184
@@ -186,20 +210,22 @@
 #       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
-// are set to a swizzling bit pattern, other words are 0.
-//
-// In immediate mode, the pattern is always set to xyzw. In vertex array
-// mode, the swizzling pattern is e.g. used to set zw components in texture
-// coordinates with only tweo components. */
+ * are set to a swizzling bit pattern, other words are 0.
+ *
+ * In immediate mode, the pattern is always set to xyzw. In vertex array
+ * mode, the swizzling pattern is e.g. used to set zw components in texture
+ * coordinates with only tweo components.
+ */
 #define R300_VAP_INPUT_ROUTE_1_0            0x21E0
 #       define R300_INPUT_ROUTE_SELECT_X    0
 #       define R300_INPUT_ROUTE_SELECT_Y    1
@@ -208,11 +234,11 @@
 #       define R300_INPUT_ROUTE_SELECT_ZERO 4
 #       define R300_INPUT_ROUTE_SELECT_ONE  5
 #       define R300_INPUT_ROUTE_SELECT_MASK 7
-#       define R300_INPUT_ROUTE_X_SHIFT          0
-#       define R300_INPUT_ROUTE_Y_SHIFT          3
-#       define R300_INPUT_ROUTE_Z_SHIFT          6
-#       define R300_INPUT_ROUTE_W_SHIFT          9
-#       define R300_INPUT_ROUTE_ENABLE           (15 << 12)
+#       define R300_INPUT_ROUTE_X_SHIFT     0
+#       define R300_INPUT_ROUTE_Y_SHIFT     3
+#       define R300_INPUT_ROUTE_Z_SHIFT     6
+#       define R300_INPUT_ROUTE_W_SHIFT     9
+#       define R300_INPUT_ROUTE_ENABLE      (15 << 12)
 #define R300_VAP_INPUT_ROUTE_1_1            0x21E4
 #define R300_VAP_INPUT_ROUTE_1_2            0x21E8
 #define R300_VAP_INPUT_ROUTE_1_3            0x21EC
@@ -221,79 +247,107 @@
 #define R300_VAP_INPUT_ROUTE_1_6            0x21F8
 #define R300_VAP_INPUT_ROUTE_1_7            0x21FC
 
-/* END */
+/* END: Vertex data assembly */
 
 /* gap */
-/* BEGIN: Upload vertex program and data
-// The programmable vertex shader unit has a memory bank of unknown size
-// that can be written to in 16 byte units by writing the address into
-// UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
-//
-// Pointers into the memory bank are always in multiples of 16 bytes.
-//
-// The memory bank is divided into areas with fixed meaning.
-//
-// Starting at address UPLOAD_PROGRAM: Vertex program instructions.
-// Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
-// whereas the difference between known addresses suggests size 512.
-//
-// Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
-// Native reported limits and the VPI layout suggest size 256, whereas
-// difference between known addresses suggests size 512.
-//
-// At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
-// floating point pointsize. The exact purpose of this state is uncertain,
-// as there is also the R300_RE_POINTSIZE register.
-//
-// Multiple vertex programs and parameter sets can be loaded at once,
-// which could explain the size discrepancy. */
+
+/* BEGIN: Upload vertex program and data */
+
+/*
+ * The programmable vertex shader unit has a memory bank of unknown size
+ * that can be written to in 16 byte units by writing the address into
+ * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
+ *
+ * Pointers into the memory bank are always in multiples of 16 bytes.
+ *
+ * The memory bank is divided into areas with fixed meaning.
+ *
+ * Starting at address UPLOAD_PROGRAM: Vertex program instructions.
+ * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
+ * whereas the difference between known addresses suggests size 512.
+ *
+ * Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
+ * Native reported limits and the VPI layout suggest size 256, whereas
+ * difference between known addresses suggests size 512.
+ *
+ * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
+ * floating point pointsize. The exact purpose of this state is uncertain,
+ * as there is also the R300_RE_POINTSIZE register.
+ *
+ * Multiple vertex programs and parameter sets can be loaded at once,
+ * which could explain the size discrepancy.
+ */
 #define R300_VAP_PVS_UPLOAD_ADDRESS         0x2200
 #       define R300_PVS_UPLOAD_PROGRAM           0x00000000
 #       define R300_PVS_UPLOAD_PARAMETERS        0x00000200
 #       define R300_PVS_UPLOAD_POINTSIZE         0x00000406
-/* gap */
-#define R300_VAP_PVS_UPLOAD_DATA            0x2208
-/* END */
 
 /* gap */
+
+#define R300_VAP_PVS_UPLOAD_DATA            0x2208
+
+/* END: Upload vertex program and data */
+
+/* gap */
+
 /* I do not know the purpose of this register. However, I do know that
-// it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
-// for normal rendering. */
+ * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
+ * for normal rendering.
+ */
 #define R300_VAP_UNKNOWN_221C               0x221C
 #       define R300_221C_NORMAL                  0x00000000
 #       define R300_221C_CLEAR                   0x0001C000
 
+/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
+ * plane is per-pixel and the second plane is per-vertex.
+ *
+ * This was determined by experimentation alone but I believe it is correct.
+ *
+ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
+ */
+#define R300_VAP_CLIP_X_0                   0x2220
+#define R300_VAP_CLIP_X_1                   0x2224
+#define R300_VAP_CLIP_Y_0                   0x2228
+#define R300_VAP_CLIP_Y_1                   0x2230
+
 /* gap */
+
 /* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
-// 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 */
+ * 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 */
 
 /* 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
-// memory bank. PROGRAM_END points to the last instruction of the active
-// program
-//
-// The meaning of the two UNKNOWN fields is obviously not known. However,
-// 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.
-// 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.
-*/
+ * memory bank. PROGRAM_END points to the last instruction of the active
+ * program
+ *
+ * The meaning of the two UNKNOWN fields is obviously not known. However,
+ * 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
+ * R300_PVS_CNTL_1_POS_END_SHIFT 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.
+ */
 #define R300_VAP_PVS_CNTL_1                 0x22D0
 #       define R300_PVS_CNTL_1_PROGRAM_START_SHIFT   0
 #       define R300_PVS_CNTL_1_POS_END_SHIFT         10
 #       define R300_PVS_CNTL_1_PROGRAM_END_SHIFT     20
-/* Addresses are relative to the vertex program parameters area. */
+/* Addresses are relative the the vertex program parameters area. */
 #define R300_VAP_PVS_CNTL_2                 0x22D4
 #       define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
 #       define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT  16
@@ -302,23 +356,26 @@
 #       define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0
 
 /* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
-// immediate vertices */
+ * immediate vertices
+ */
 #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? */
+/* write 0 to indicate end of packet? */
+#define R300_VAP_VTX_END_OF_PKT             0x24AC
 
 /* gap */
 
 /* These are values from r300_reg/r300_reg.h - they are known to be correct
-   and are here so we can use one register file instead of several
-   - Vladimir */
+ * and are here so we can use one register file instead of several
+ * - Vladimir
+ */
 #define R300_GB_VAP_RASTER_VTX_FMT_0	0x4000
 #	define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT	(1<<0)
 #	define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT	(1<<1)
@@ -341,14 +398,16 @@
 #	define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT	21
 
 /* UNK30 seems to enables point to quad transformation on textures
-   (or something closely related to that).
-   This bit is rather fatal at the time being due to lackings at pixel shader side */
+ * (or something closely related to that).
+ * This bit is rather fatal at the time being due to lackings at pixel
+ * shader side
+ */
 #define R300_GB_ENABLE	0x4008
 #	define R300_GB_POINT_STUFF_ENABLE	(1<<0)
 #	define R300_GB_LINE_STUFF_ENABLE	(1<<1)
 #	define R300_GB_TRIANGLE_STUFF_ENABLE	(1<<2)
 #	define R300_GB_STENCIL_AUTO_ENABLE	(1<<4)
-#	define R300_GB_UNK30			(1<<30)
+#	define R300_GB_UNK31			(1<<31)
 	/* each of the following is 2 bits wide */
 #define R300_GB_TEX_REPLICATE	0
 #define R300_GB_TEX_ST		1
@@ -383,11 +442,13 @@
 #	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
 #	define R300_GB_TILE_PIPE_COUNT_R300	(3<<1)
 #	define R300_GB_TILE_PIPE_COUNT_R420	(7<<1)
+#	define R300_GB_TILE_PIPE_COUNT_RV410	(3<<1)
 #	define R300_GB_TILE_SIZE_8		0
 #	define R300_GB_TILE_SIZE_16		(1<<4)
 #	define R300_GB_TILE_SIZE_32		(2<<4)
@@ -442,17 +503,18 @@
 #	define R300_GB_W_SELECT_1		(1<<4)
 
 #define R300_GB_AA_CONFIG		0x4020
+#	define R300_AA_DISABLE			0x00
 #	define R300_AA_ENABLE			0x01
 #	define R300_AA_SUBSAMPLES_2		0
 #	define R300_AA_SUBSAMPLES_3		(1<<1)
 #	define R300_AA_SUBSAMPLES_4		(2<<1)
 #	define R300_AA_SUBSAMPLES_6		(3<<1)
 
-/* END */
-
 /* gap */
+
 /* Zero to flush caches. */
 #define R300_TX_CNTL                        0x4100
+#define R300_TX_FLUSH                       0x0
 
 /* The upper enable bits are guessed, based on fglrx reported limits. */
 #define R300_TX_ENABLE                      0x4104
@@ -474,24 +536,25 @@
 #       define R300_TX_ENABLE_15                 (1 << 15)
 
 /* The pointsize is given in multiples of 6. The pointsize can be
-// enormous: Clear() renders a single point that fills the entire
-// framebuffer. */
+ * enormous: Clear() renders a single point that fills the entire
+ * 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.
-   In default mode lines are classified as vertical lines.
-   HO: horizontal
-   VE: vertical or horizontal
-   HO & VE: no classification
-*/
+ * In default mode lines are classified as vertical lines.
+ * HO: horizontal
+ * VE: vertical or horizontal
+ * HO & VE: no classification
+ */
 #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)
@@ -499,6 +562,9 @@
 /* Some sort of scale or clamp value for texcoordless textures. */
 #define R300_RE_UNK4238                       0x4238
 
+/* Something shade related */
+#define R300_RE_SHADE                         0x4274
+
 #define R300_RE_SHADE_MODEL                   0x4278
 #	define R300_RE_SHADE_MODEL_SMOOTH     0x3aaaa
 #	define R300_RE_SHADE_MODEL_FLAT       0x39595
@@ -513,24 +579,31 @@
 #	define R300_PM_BACK_LINE              (1 << 7)
 #	define R300_PM_BACK_FILL              (1 << 8)
 
+/* Fog parameters */
+#define R300_RE_FOG_SCALE                     0x4294
+#define R300_RE_FOG_START                     0x4298
+
 /* Not sure why there are duplicate of factor and constant values.
-   My best guess so far is that there are seperate zbiases for test and write.
-   Ordering might be wrong.
-   Some of the tests indicate that fgl has a fallback implementation of zbias
-   via pixel shaders. */
+ * 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.
+ */
+#define R300_RE_ZBIAS_CNTL                    0x42A0 /* GUESS */
 #define R300_RE_ZBIAS_T_FACTOR                0x42A4
 #define R300_RE_ZBIAS_T_CONSTANT              0x42A8
 #define R300_RE_ZBIAS_W_FACTOR                0x42AC
 #define R300_RE_ZBIAS_W_CONSTANT              0x42B0
 
 /* This register needs to be set to (1<<1) for RV350 to correctly
-   perform depth test (see --vb-triangles in r300_demo)
-   Don't know about other chips. - Vladimir
-   This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
-   My guess is that there are two bits for each zbias primitive (FILL, LINE, POINT).
-   One to enable depth test and one for depth write.
-   Yet this doesnt explain why depth writes work ...
-    */
+ * perform depth test (see --vb-triangles in r300_demo)
+ * Don't know about other chips. - Vladimir
+ * This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
+ * My guess is that there are two bits for each zbias primitive
+ * (FILL, LINE, POINT).
+ *  One to enable depth test and one for depth write.
+ * Yet this doesnt explain why depth writes work ...
+ */
 #define R300_RE_OCCLUSION_CNTL		    0x42B4
 #	define R300_OCCLUSION_ON		(1<<1)
 
@@ -540,30 +613,38 @@
 #       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
-// on the vertex program, *not* the fragment program) */
+
+/* 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
+ * on the vertex program, *not* the fragment program)
+ */
 #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 */
+	/* number of color interpolators used */
+#	define R300_RS_CNTL_CI_CNT_SHIFT         7
 #       define R300_RS_CNTL_0_UNKNOWN_18         (1 << 18)
-/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */
+	/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n
+	   register. */
 #define R300_RS_CNTL_1                      0x4304
 
 /* gap */
+
 /* Only used for texture coordinates.
-// Use the source field to route texture coordinate input from the vertex program
-// to the desired interpolator. Note that the source field is relative to the
-// outputs the vertex program *actually* writes. If a vertex program only writes
-// texcoord[1], this will be source index 0.
-// Set INTERP_USED on all interpolators that produce data used by the
-// fragment program. INTERP_USED looks like a swizzling mask, but
-// I haven't seen it used that way.
-//
-// Note: The _UNKNOWN constants are always set in their respective register.
-// I don't know if this is necessary. */
+ * Use the source field to route texture coordinate input from the
+ * vertex program to the desired interpolator. Note that the source
+ * field is relative to the outputs the vertex program *actually*
+ * writes. If a vertex program only writes texcoord[1], this will
+ * be source index 0.
+ * Set INTERP_USED on all interpolators that produce data used by
+ * the fragment program. INTERP_USED looks like a swizzling mask,
+ * but I haven't seen it used that way.
+ *
+ * Note: The _UNKNOWN constants are always set in their respective
+ * register. I don't know if this is necessary.
+ */
 #define R300_RS_INTERP_0                    0x4310
 #define R300_RS_INTERP_1                    0x4314
 #       define R300_RS_INTERP_1_UNKNOWN          0x40
@@ -580,54 +661,63 @@
 #       define R300_RS_INTERP_USED               0x00D10000
 
 /* These DWORDs control how vertex data is routed into fragment program
-// registers, after interpolators. */
+ * registers, after interpolators.
+ */
 #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. */
+ * the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
+ * color register index.
+ *
+ * Apperently you may set the R300_RS_ROUTE_0_COLOR bit, but not provide any
+ * R300_RS_ROUTE_0_COLOR_DEST value; this setup is used for clearing the state.
+ * See r300_ioctl.c:r300EmitClearState. I'm not sure if this setup is strictly
+ * correct or not. - Oliver.
+ */
 #       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
 #		define R300_RS_ROUTE_1_COLOR1_DEST_MASK  (31 << 17)
 #		define R300_RS_ROUTE_1_UNKNOWN11         (1 << 11)
-/* END */
+/* END: Rasterization / Interpolators - many guesses */
 
-/* BEGIN: Scissors and cliprects
-// There are four clipping rectangles. Their corner coordinates are inclusive.
-// Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
-// on whether the pixel is inside cliprects 0-3, respectively. For example,
-// if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
-// the number 3 (binary 0011).
-// Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
-// the pixel is rasterized.
-//
-// In addition to this, there is a scissors rectangle. Only pixels inside the
-// scissors rectangle are drawn. (coordinates are inclusive)
-//
-// For some reason, the top-left corner of the framebuffer is at (1440, 1440)
-// for the purpose of clipping and scissors. */
+/* BEGIN: Scissors and cliprects */
+
+/* There are four clipping rectangles. Their corner coordinates are inclusive.
+ * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
+ * on whether the pixel is inside cliprects 0-3, respectively. For example,
+ * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
+ * the number 3 (binary 0011).
+ * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
+ * the pixel is rasterized.
+ *
+ * In addition to this, there is a scissors rectangle. Only pixels inside the
+ * scissors rectangle are drawn. (coordinates are inclusive)
+ *
+ * For some reason, the top-left corner of the framebuffer is at (1440, 1440)
+ * for the purpose of clipping and scissors.
+ */
 #define R300_RE_CLIPRECT_TL_0               0x43B0
 #define R300_RE_CLIPRECT_BR_0               0x43B4
 #define R300_RE_CLIPRECT_TL_1               0x43B8
@@ -661,6 +751,7 @@
 #       define R300_CLIP_3210                    (1 << 15)
 
 /* gap */
+
 #define R300_RE_SCISSORS_TL                 0x43E0
 #define R300_RE_SCISSORS_BR                 0x43E4
 #       define R300_SCISSORS_OFFSET              1440
@@ -668,12 +759,15 @@
 #       define R300_SCISSORS_X_MASK              (0x1FFF << 0)
 #       define R300_SCISSORS_Y_SHIFT             13
 #       define R300_SCISSORS_Y_MASK              (0x1FFF << 13)
-/* END */
+/* END: Scissors and cliprects */
 
-/* BEGIN: Texture specification
-// The texture specification dwords are grouped by meaning and not by texture unit.
-// This means that e.g. the offset for texture image unit N is found in register
-// TX_OFFSET_0 + (4*N) */
+/* BEGIN: Texture specification */
+
+/*
+ * The texture specification dwords are grouped by meaning and not by texture
+ * unit. This means that e.g. the offset for texture image unit N is found in
+ * register TX_OFFSET_0 + (4*N)
+ */
 #define R300_TX_FILTER_0                    0x4400
 #       define R300_TX_REPEAT                    0
 #       define R300_TX_MIRRORED                  1
@@ -697,13 +791,14 @@
 #	define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR         (10 <<  11)
 
 /* NOTE: NEAREST doesnt seem to exist.
-   Im not seting MAG_FILTER_MASK and (3 << 11) on for all
-   anisotropy modes because that would void selected mag filter */
-#	define R300_TX_MIN_FILTER_ANISO_NEAREST             ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#	define R300_TX_MIN_FILTER_ANISO_LINEAR              ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST ((1 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR  ((2 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#       define R300_TX_MIN_FILTER_MASK           ( (15 << 11) | (3 << 13) )
+ * Im not seting MAG_FILTER_MASK and (3 << 11) on for all
+ * anisotropy modes because that would void selected mag filter
+ */
+#	define R300_TX_MIN_FILTER_ANISO_NEAREST             (0 << 13)
+#	define R300_TX_MIN_FILTER_ANISO_LINEAR              (0 << 13)
+#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (1 << 13)
+#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR  (2 << 13)
+#       define R300_TX_MIN_FILTER_MASK   ( (15 << 11) | (3 << 13) )
 #	define R300_TX_MAX_ANISO_1_TO_1  (0 << 21)
 #	define R300_TX_MAX_ANISO_2_TO_1  (2 << 21)
 #	define R300_TX_MAX_ANISO_4_TO_1  (4 << 21)
@@ -734,10 +829,10 @@
 #       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_MASK                 (15 << 26)
-#       define R300_TX_SIZE_PROJECTED                     (1<<30)
-#       define R300_TX_SIZE_TXPITCH_EN                     (1<<31)
+#       define R300_TX_MAX_MIP_LEVEL_SHIFT       26
+#       define R300_TX_MAX_MIP_LEVEL_MASK        (0xf << 26)
+#       define R300_TX_SIZE_PROJECTED            (1<<30)
+#       define R300_TX_SIZE_TXPITCH_EN           (1<<31)
 #define R300_TX_FORMAT_0                    0x44C0
 	/* The interpretation of the format word by Wladimir van der Laan */
 	/* The X, Y, Z and W refer to the layout of the components.
@@ -761,11 +856,11 @@
 #	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 */
-						  /* 0x16 - some 16 bit green format.. ?? */
+#	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_CUBIC_MAP		   (1 << 26)
 
@@ -793,23 +888,26 @@
 #	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 */
+	/* 2.0*Z, everything above 1.0 is set to 0.0 */
+#	define R300_TX_FORMAT_CUT_Z	6
+	/* 2.0*W, everything above 1.0 is set to 0.0 */
+#	define R300_TX_FORMAT_CUT_W	7
 
 #	define R300_TX_FORMAT_B_SHIFT	18
 #	define R300_TX_FORMAT_G_SHIFT	15
 #	define R300_TX_FORMAT_R_SHIFT	12
 #	define R300_TX_FORMAT_A_SHIFT	9
 	/* Convenience macro to take care of layout and swizzling */
-#	define R300_EASY_TX_FORMAT(B, G, R, A, FMT)	(\
-	  ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \
-	| ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \
-	| ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \
-	| ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \
-	| (R300_TX_FORMAT_##FMT) \
-	  )
-	/* These can be ORed with result of R300_EASY_TX_FORMAT() */
-	/* We don't really know what they do. Take values from a constant color ? */
+#	define R300_EASY_TX_FORMAT(B, G, R, A, FMT)	(		\
+		((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT)		\
+		| ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT)	\
+		| ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT)	\
+		| ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT)	\
+		| (R300_TX_FORMAT_##FMT)				\
+		)
+	/* These can be ORed with result of R300_EASY_TX_FORMAT()
+	   We don't really know what they do. Take values from a
+           constant color ? */
 #	define R300_TX_FORMAT_CONST_X		(1<<5)
 #	define R300_TX_FORMAT_CONST_Y		(2<<5)
 #	define R300_TX_FORMAT_CONST_Z		(4<<5)
@@ -819,7 +917,7 @@
 
 #define R300_TX_PITCH_0			    0x4500 /* obvious missing in gap */
 #define R300_TX_OFFSET_0                    0x4540
-/* BEGIN: Guess from R200 */
+	/* BEGIN: Guess from R200 */
 #       define R300_TXO_ENDIAN_NO_SWAP           (0 << 0)
 #       define R300_TXO_ENDIAN_BYTE_SWAP         (1 << 0)
 #       define R300_TXO_ENDIAN_WORD_SWAP         (2 << 0)
@@ -828,53 +926,61 @@
 #       define R300_TXO_MICRO_TILE               (1 << 3)
 #       define R300_TXO_OFFSET_MASK              0xffffffe0
 #       define R300_TXO_OFFSET_SHIFT             5
-/* END */
-#define R300_TX_CHROMA_KEY_0                      0x4580 /* 32 bit chroma key */
-#define R300_TX_BORDER_COLOR_0              0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
+	/* END: Guess from R200 */
 
-/* END */
+/* 32 bit chroma key */
+#define R300_TX_CHROMA_KEY_0                      0x4580
+/* ff00ff00 == { 0, 1.0, 0, 1.0 } */
+#define R300_TX_BORDER_COLOR_0              0x45C0
 
-/* BEGIN: Fragment program instruction set
-// Fragment programs are written directly into register space.
-// There are separate instruction streams for texture instructions and ALU
-// instructions.
-// In order to synchronize these streams, the program is divided into up
-// to 4 nodes. Each node begins with a number of TEX operations, followed
-// by a number of ALU operations.
-// The first node can have zero TEX ops, all subsequent nodes must have at least
-// one TEX ops.
-// All nodes must have at least one ALU op.
-//
-// The index of the last node is stored in PFS_CNTL_0: A value of 0 means
-// 1 node, a value of 3 means 4 nodes.
-// The total amount of instructions is defined in PFS_CNTL_2. The offsets are
-// offsets into the respective instruction streams, while *_END points to the
-// last instruction relative to this offset. */
+/* END: Texture specification */
+
+/* BEGIN: Fragment program instruction set */
+
+/* Fragment programs are written directly into register space.
+ * There are separate instruction streams for texture instructions and ALU
+ * instructions.
+ * In order to synchronize these streams, the program is divided into up
+ * to 4 nodes. Each node begins with a number of TEX operations, followed
+ * by a number of ALU operations.
+ * The first node can have zero TEX ops, all subsequent nodes must have at
+ * least
+ * one TEX ops.
+ * All nodes must have at least one ALU op.
+ *
+ * The index of the last node is stored in PFS_CNTL_0: A value of 0 means
+ * 1 node, a value of 3 means 4 nodes.
+ * The total amount of instructions is defined in PFS_CNTL_2. The offsets are
+ * offsets into the respective instruction streams, while *_END points to the
+ * last instruction relative to this offset.
+ */
 #define R300_PFS_CNTL_0                     0x4600
 #       define R300_PFS_CNTL_LAST_NODES_SHIFT    0
 #       define R300_PFS_CNTL_LAST_NODES_MASK     (3 << 0)
 #       define R300_PFS_CNTL_FIRST_NODE_HAS_TEX  (1 << 3)
 #define R300_PFS_CNTL_1                     0x4604
 /* There is an unshifted value here which has so far always been equal to the
-// index of the highest used temporary register. */
+ * index of the highest used temporary register.
+ */
 #define R300_PFS_CNTL_2                     0x4608
 #       define R300_PFS_CNTL_ALU_OFFSET_SHIFT    0
 #       define R300_PFS_CNTL_ALU_OFFSET_MASK     (63 << 0)
 #       define R300_PFS_CNTL_ALU_END_SHIFT       6
-#       define R300_PFS_CNTL_ALU_END_MASK        (63 << 0)
+#       define R300_PFS_CNTL_ALU_END_MASK        (63 << 6)
 #       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
-// PFS_NODE_3.
-// Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
-// first node is stored in NODE_2, the second node is stored in NODE_3.
-//
-// Offsets are relative to the master offset from PFS_CNTL_2.
-// LAST_NODE is set for the last node, and only for the last node. */
+ * PFS_NODE_3.
+ * Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
+ * first node is stored in NODE_2, the second node is stored in NODE_3.
+ *
+ * Offsets are relative to the master offset from PFS_CNTL_2.
+ */
 #define R300_PFS_NODE_0                     0x4610
 #define R300_PFS_NODE_1                     0x4614
 #define R300_PFS_NODE_2                     0x4618
@@ -887,91 +993,98 @@
 #       define R300_PFS_NODE_TEX_OFFSET_MASK     (31 << 12)
 #       define R300_PFS_NODE_TEX_END_SHIFT       17
 #       define R300_PFS_NODE_TEX_END_MASK        (31 << 17)
-/*#       define R300_PFS_NODE_LAST_NODE           (1 << 22) */
 #		define R300_PFS_NODE_OUTPUT_COLOR        (1 << 22)
 #		define R300_PFS_NODE_OUTPUT_DEPTH        (1 << 23)
 
 /* TEX
-// As far as I can tell, texture instructions cannot write into output
-// registers directly. A subsequent ALU instruction is always necessary,
-// even if it's just MAD o0, r0, 1, 0 */
+ * As far as I can tell, texture instructions cannot write into output
+ * registers directly. A subsequent ALU instruction is always necessary,
+ * even if it's just MAD o0, r0, 1, 0
+ */
 #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_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_SRC_SHIFT              0
+#	define R300_FPITX_SRC_MASK               (31 << 0)
+	/* GUESS */
+#	define R300_FPITX_SRC_CONST              (1 << 5)
+#	define R300_FPITX_DST_SHIFT              6
+#	define R300_FPITX_DST_MASK               (31 << 6)
+#	define R300_FPITX_IMAGE_SHIFT            11
+	/* GUESS based on layout and native limits */
+#       define R300_FPITX_IMAGE_MASK             (15 << 11)
 /* Unsure if these are opcodes, or some kind of bitfield, but this is how
  * they were set when I checked
  */
-#		define R300_FPITX_OPCODE_SHIFT			15
-#			define R300_FPITX_OP_TEX			1
-#			define R300_FPITX_OP_KIL			2
-#			define R300_FPITX_OP_TXP			3
-#			define R300_FPITX_OP_TXB			4
+#	define R300_FPITX_OPCODE_SHIFT		15
+#		define R300_FPITX_OP_TEX	1
+#		define R300_FPITX_OP_KIL	2
+#		define R300_FPITX_OP_TXP	3
+#		define R300_FPITX_OP_TXB	4
+#	define R300_FPITX_OPCODE_MASK           (7 << 15)
 
 /* ALU
-// The ALU instructions register blocks are enumerated according to the order
-// in which fglrx. I assume there is space for 64 instructions, since
-// each block has space for a maximum of 64 DWORDs, and this matches reported
-// native limits.
-//
-// The basic functional block seems to be one MAD for each color and alpha,
-// and an adder that adds all components after the MUL.
-//  - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
-//  - DP4: Use OUTC_DP4, OUTA_DP4
-//  - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
-//  - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
-//  - CMP: If ARG2 < 0, return ARG1, else return ARG0
-//  - FLR: use FRC+MAD
-//  - XPD: use MAD+MAD
-//  - SGE, SLT: use MAD+CMP
-//  - RSQ: use ABS modifier for argument
-//  - Use OUTC_REPL_ALPHA to write results of an alpha-only operation (e.g. RCP)
-//    into color register
-//  - apparently, there's no quick DST operation
-//  - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
-//  - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
-//  - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
-//
-// Operand selection
-// First stage selects three sources from the available registers and
-// constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
-// fglrx sorts the three source fields: Registers before constants,
-// lower indices before higher indices; I do not know whether this is necessary.
-// fglrx fills unused sources with "read constant 0"
-// According to specs, you cannot select more than two different constants.
-//
-// Second stage selects the operands from the sources. This is defined in
-// INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
-// zero and one.
-// Swizzling and negation happens in this stage, as well.
-//
-// Important: Color and alpha seem to be mostly separate, i.e. their sources
-// selection appears to be fully independent (the register storage is probably
-// physically split into a color and an alpha section).
-// However (because of the apparent physical split), there is some interaction
-// WRT swizzling. If, for example, you want to load an R component into an
-// Alpha operand, this R component is taken from a *color* source, not from
-// an alpha source. The corresponding register doesn't even have to appear in
-// the alpha sources list. (I hope this alll makes sense to you)
-//
-// Destination selection
-// The destination register index is in FPI1 (color) and FPI3 (alpha) together
-// with enable bits.
-// There are separate enable bits for writing into temporary registers
-// (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* /DSTA_OUTPUT).
-// You can write to both at once, or not write at all (the same index
-// must be used for both).
-//
-// Note: There is a special form for LRP
-//  - Argument order is the same as in ARB_fragment_program.
-//  - Operation is MAD
-//  - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
-//  - Set FPI0/FPI2_SPECIAL_LRP
-// Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD */
+ * The ALU instructions register blocks are enumerated according to the order
+ * in which fglrx. I assume there is space for 64 instructions, since
+ * each block has space for a maximum of 64 DWORDs, and this matches reported
+ * native limits.
+ *
+ * The basic functional block seems to be one MAD for each color and alpha,
+ * and an adder that adds all components after the MUL.
+ *  - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
+ *  - DP4: Use OUTC_DP4, OUTA_DP4
+ *  - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
+ *  - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+ *  - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1
+ *  - CMP: If ARG2 < 0, return ARG1, else return ARG0
+ *  - FLR: use FRC+MAD
+ *  - XPD: use MAD+MAD
+ *  - SGE, SLT: use MAD+CMP
+ *  - RSQ: use ABS modifier for argument
+ *  - Use OUTC_REPL_ALPHA to write results of an alpha-only operation
+ *    (e.g. RCP) into color register
+ *  - apparently, there's no quick DST operation
+ *  - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
+ *  - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
+ *  - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
+ *
+ * Operand selection
+ * First stage selects three sources from the available registers and
+ * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
+ * fglrx sorts the three source fields: Registers before constants,
+ * lower indices before higher indices; I do not know whether this is
+ * necessary.
+ *
+ * fglrx fills unused sources with "read constant 0"
+ * According to specs, you cannot select more than two different constants.
+ *
+ * Second stage selects the operands from the sources. This is defined in
+ * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
+ * zero and one.
+ * Swizzling and negation happens in this stage, as well.
+ *
+ * Important: Color and alpha seem to be mostly separate, i.e. their sources
+ * selection appears to be fully independent (the register storage is probably
+ * physically split into a color and an alpha section).
+ * However (because of the apparent physical split), there is some interaction
+ * WRT swizzling. If, for example, you want to load an R component into an
+ * Alpha operand, this R component is taken from a *color* source, not from
+ * an alpha source. The corresponding register doesn't even have to appear in
+ * the alpha sources list. (I hope this all makes sense to you)
+ *
+ * Destination selection
+ * The destination register index is in FPI1 (color) and FPI3 (alpha)
+ * together with enable bits.
+ * There are separate enable bits for writing into temporary registers
+ * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_*
+ * /DSTA_OUTPUT). You can write to both at once, or not write at all (the
+ * same index must be used for both).
+ *
+ * Note: There is a special form for LRP
+ *  - Argument order is the same as in ARB_fragment_program.
+ *  - Operation is MAD
+ *  - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
+ *  - Set FPI0/FPI2_SPECIAL_LRP
+ * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD
+ */
 #define R300_PFS_INSTR1_0                   0x46C0
 #       define R300_FPI1_SRC0C_SHIFT             0
 #       define R300_FPI1_SRC0C_MASK              (31 << 0)
@@ -982,6 +1095,7 @@
 #       define R300_FPI1_SRC2C_SHIFT             12
 #       define R300_FPI1_SRC2C_MASK              (31 << 12)
 #       define R300_FPI1_SRC2C_CONST             (1 << 17)
+#       define R300_FPI1_SRC_MASK                0x0003ffff
 #       define R300_FPI1_DSTC_SHIFT              18
 #       define R300_FPI1_DSTC_MASK               (31 << 18)
 #		define R300_FPI1_DSTC_REG_MASK_SHIFT     23
@@ -1003,6 +1117,7 @@
 #       define R300_FPI3_SRC2A_SHIFT             12
 #       define R300_FPI3_SRC2A_MASK              (31 << 12)
 #       define R300_FPI3_SRC2A_CONST             (1 << 17)
+#       define R300_FPI3_SRC_MASK                0x0003ffff
 #       define R300_FPI3_DSTA_SHIFT              18
 #       define R300_FPI3_DSTA_MASK               (31 << 18)
 #       define R300_FPI3_DSTA_REG                (1 << 23)
@@ -1028,7 +1143,8 @@
 #       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 */
+	/* GUESS */
+#       define R300_FPI0_ARGC_HALF               22
 #       define R300_FPI0_ARGC_SRC0C_YZX          23
 #       define R300_FPI0_ARGC_SRC1C_YZX          24
 #       define R300_FPI0_ARGC_SRC2C_YZX          25
@@ -1057,6 +1173,7 @@
 #       define R300_FPI0_OUTC_DP4                (2 << 23)
 #       define R300_FPI0_OUTC_MIN                (4 << 23)
 #       define R300_FPI0_OUTC_MAX                (5 << 23)
+#       define R300_FPI0_OUTC_CMPH               (7 << 23)
 #       define R300_FPI0_OUTC_CMP                (8 << 23)
 #       define R300_FPI0_OUTC_FRC                (9 << 23)
 #       define R300_FPI0_OUTC_REPL_ALPHA         (10 << 23)
@@ -1079,20 +1196,23 @@
 #       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 */
-
+	/* GUESS */
+#       define R300_FPI2_ARGA_HALF               18
 #       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 */
+	/* GUESS */
+#	define R300_FPI2_ARG0A_ABS		 (1 << 6)
 #       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 */
+	/* GUESS */
+#	define R300_FPI2_ARG1A_ABS		 (1 << 13)
 #       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 */
+	/* GUESS */
+#	define R300_FPI2_ARG2A_ABS		 (1 << 20)
 #       define R300_FPI2_SPECIAL_LRP             (1 << 21)
 #       define R300_FPI2_OUTA_MAD                (0 << 23)
 #       define R300_FPI2_OUTA_DP4                (1 << 23)
@@ -1106,9 +1226,19 @@
 #       define R300_FPI2_OUTA_RSQ                (11 << 23)
 #       define R300_FPI2_OUTA_SAT                (1 << 30)
 #       define R300_FPI2_UNKNOWN_31              (1 << 31)
-/* END */
+/* END: Fragment program instruction set */
 
-/* gap */
+/* Fog state and color */
+#define R300_RE_FOG_STATE                   0x4BC0
+#       define R300_FOG_ENABLE                   (1 << 0)
+#	define R300_FOG_MODE_LINEAR              (0 << 1)
+#	define R300_FOG_MODE_EXP                 (1 << 1)
+#	define R300_FOG_MODE_EXP2                (2 << 1)
+#	define R300_FOG_MODE_MASK                (3 << 1)
+#define R300_FOG_COLOR_R                    0x4BC8
+#define R300_FOG_COLOR_G                    0x4BCC
+#define R300_FOG_COLOR_B                    0x4BD0
+
 #define R300_PP_ALPHA_TEST                  0x4BD4
 #       define R300_REF_ALPHA_MASK               0x000000ff
 #       define R300_ALPHA_TEST_FAIL              (0 << 8)
@@ -1123,6 +1253,7 @@
 #       define R300_ALPHA_TEST_ENABLE            (1 << 11)
 
 /* gap */
+
 /* Fragment program parameters in 7.16 floating point */
 #define R300_PFS_PARAM_0_X                  0x4C00
 #define R300_PFS_PARAM_0_Y                  0x4C04
@@ -1135,45 +1266,48 @@
 #define R300_PFS_PARAM_31_W                 0x4DFC
 
 /* Notes:
-// - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in the application
-// - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND are set to the same
-//   function (both registers are always set up completely in any case)
-// - Most blend flags are simply copied from R200 and not tested yet */
+ * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in
+ *   the application
+ * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND
+ *    are set to the same
+ *   function (both registers are always set up completely in any case)
+ * - Most blend flags are simply copied from R200 and not tested yet
+ */
 #define R300_RB3D_CBLEND                    0x4E04
 #define R300_RB3D_ABLEND                    0x4E08
- /* the following only appear in CBLEND */
+/* the following only appear in CBLEND */
 #       define R300_BLEND_ENABLE                     (1 << 0)
 #       define R300_BLEND_UNKNOWN                    (3 << 1)
 #       define R300_BLEND_NO_SEPARATE                (1 << 3)
- /* the following are shared between CBLEND and ABLEND */
+/* the following are shared between CBLEND and ABLEND */
 #       define R300_FCN_MASK                         (3  << 12)
 #       define R300_COMB_FCN_ADD_CLAMP               (0  << 12)
 #       define R300_COMB_FCN_ADD_NOCLAMP             (1  << 12)
 #       define R300_COMB_FCN_SUB_CLAMP               (2  << 12)
 #       define R300_COMB_FCN_SUB_NOCLAMP             (3  << 12)
-#       define R300_SRC_BLEND_GL_ZERO                (32 << 16)
-#       define R300_SRC_BLEND_GL_ONE                 (33 << 16)
-#       define R300_SRC_BLEND_GL_SRC_COLOR           (34 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
-#       define R300_SRC_BLEND_GL_DST_COLOR           (36 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
-#       define R300_SRC_BLEND_GL_SRC_ALPHA           (38 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
-#       define R300_SRC_BLEND_GL_DST_ALPHA           (40 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
-#       define R300_SRC_BLEND_GL_SRC_ALPHA_SATURATE  (42 << 16)
-#       define R300_SRC_BLEND_MASK                   (63 << 16)
-#       define R300_DST_BLEND_GL_ZERO                (32 << 24)
-#       define R300_DST_BLEND_GL_ONE                 (33 << 24)
-#       define R300_DST_BLEND_GL_SRC_COLOR           (34 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
-#       define R300_DST_BLEND_GL_DST_COLOR           (36 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
-#       define R300_DST_BLEND_GL_SRC_ALPHA           (38 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
-#       define R300_DST_BLEND_GL_DST_ALPHA           (40 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
-#       define R300_DST_BLEND_MASK                   (63 << 24)
+#       define R300_COMB_FCN_MIN                     (4  << 12)
+#       define R300_COMB_FCN_MAX                     (5  << 12)
+#       define R300_COMB_FCN_RSUB_CLAMP              (6  << 12)
+#       define R300_COMB_FCN_RSUB_NOCLAMP            (7  << 12)
+#       define R300_BLEND_GL_ZERO                    (32)
+#       define R300_BLEND_GL_ONE                     (33)
+#       define R300_BLEND_GL_SRC_COLOR               (34)
+#       define R300_BLEND_GL_ONE_MINUS_SRC_COLOR     (35)
+#       define R300_BLEND_GL_DST_COLOR               (36)
+#       define R300_BLEND_GL_ONE_MINUS_DST_COLOR     (37)
+#       define R300_BLEND_GL_SRC_ALPHA               (38)
+#       define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA     (39)
+#       define R300_BLEND_GL_DST_ALPHA               (40)
+#       define R300_BLEND_GL_ONE_MINUS_DST_ALPHA     (41)
+#       define R300_BLEND_GL_SRC_ALPHA_SATURATE      (42)
+#       define R300_BLEND_GL_CONST_COLOR             (43)
+#       define R300_BLEND_GL_ONE_MINUS_CONST_COLOR   (44)
+#       define R300_BLEND_GL_CONST_ALPHA             (45)
+#       define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA   (46)
+#       define R300_BLEND_MASK                       (63)
+#       define R300_SRC_BLEND_SHIFT                  (16)
+#       define R300_DST_BLEND_SHIFT                  (24)
+#define R300_RB3D_BLEND_COLOR               0x4E10
 #define R300_RB3D_COLORMASK                 0x4E0C
 #       define R300_COLORMASK0_B                 (1<<0)
 #       define R300_COLORMASK0_G                 (1<<1)
@@ -1181,41 +1315,49 @@
 #       define R300_COLORMASK0_A                 (1<<3)
 
 /* 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? */
+ * 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.
-// Set to 0A before 3D operations, set to 02 afterwards. */
+ * Set to 0A before 3D operations, set to 02 afterwards.
+ */
 #define R300_RB3D_DSTCACHE_CTLSTAT          0x4E4C
-#       define R300_RB3D_DSTCACHE_02             0x00000002
-#       define R300_RB3D_DSTCACHE_0A             0x0000000A
+#       define R300_RB3D_DSTCACHE_UNKNOWN_02             0x00000002
+#       define R300_RB3D_DSTCACHE_UNKNOWN_0A             0x0000000A
 
 /* gap */
-/* 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 */
+/* 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
+#       define R300_RB3D_Z_DISABLED_2            0x00000014
 #       define R300_RB3D_Z_TEST                  0x00000012
 #       define R300_RB3D_Z_TEST_AND_WRITE        0x00000016
 #       define R300_RB3D_Z_WRITE_ONLY        	 0x00000006
@@ -1226,7 +1368,7 @@
 #	define R300_RB3D_STENCIL_ENABLE		 0x00000001
 
 #define R300_RB3D_ZSTENCIL_CNTL_1                   0x4F04
-		/* functions */
+	/* functions */
 #	define R300_ZS_NEVER			0
 #	define R300_ZS_LESS			1
 #	define R300_ZS_LEQUAL			2
@@ -1236,7 +1378,7 @@
 #	define R300_ZS_NOTEQUAL			6
 #	define R300_ZS_ALWAYS			7
 #       define R300_ZS_MASK                     7
-		/* operations */
+	/* operations */
 #	define R300_ZS_KEEP			0
 #	define R300_ZS_ZERO			1
 #	define R300_ZS_REPLACE			2
@@ -1245,9 +1387,8 @@
 #	define R300_ZS_INVERT			5
 #	define R300_ZS_INCR_WRAP		6
 #	define R300_ZS_DECR_WRAP		7
-
-       /* front and back refer to operations done for front
-          and back faces, i.e. separate stencil function support */
+	/* front and back refer to operations done for front
+	   and back faces, i.e. separate stencil function support */
 #	define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT		0
 #	define R300_RB3D_ZS1_FRONT_FUNC_SHIFT		3
 #	define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT	6
@@ -1269,45 +1410,64 @@
 #define R300_RB3D_ZSTENCIL_FORMAT                   0x4F10
 #	define R300_DEPTH_FORMAT_16BIT_INT_Z     (0 << 0)
 #	define R300_DEPTH_FORMAT_24BIT_INT_Z     (2 << 0)
+	/* 16 bit format or some aditional bit ? */
+#	define R300_DEPTH_FORMAT_UNK32          (32 << 0)
+
+#define R300_RB3D_EARLY_Z                           0x4F14
+#	define R300_EARLY_Z_DISABLE              (0 << 0)
+#	define R300_EARLY_Z_ENABLE               (1 << 0)
 
 /* gap */
+
+#define R300_RB3D_ZCACHE_CTLSTAT            0x4F18 /* GUESS */
+#       define R300_RB3D_ZCACHE_UNKNOWN_01  0x1
+#       define R300_RB3D_ZCACHE_UNKNOWN_03  0x3
+
+/* 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:
-//  DWORD 0: output and opcode
-//  DWORD 1: first argument
-//  DWORD 2: second argument
-//  DWORD 3: third argument
-//
-// Notes:
-//  - ABS r, a is implemented as MAX r, a, -a
-//  - MOV is implemented as ADD to zero
-//  - XPD is implemented as MUL + MAD
-//  - FLR is implemented as FRC + ADD
-//  - apparently, fglrx tries to schedule instructions so that there is at least
-//    one instruction between the write to a temporary and the first read
-//    from said temporary; however, violations of this scheduling are allowed
-//  - register indices seem to be unrelated with OpenGL aliasing to conventional state
-//  - only one attribute and one parameter can be loaded at a time; however, the
-//    same attribute/parameter can be used for more than one argument
-//  - the second software argument for POW is the third hardware argument (no idea why)
-//  - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
-//
-// There is some magic surrounding LIT:
-//  The single argument is replicated across all three inputs, but swizzled:
-//   First argument: xyzy
-//   Second argument: xyzx
-//   Third argument: xyzw
-//  Whenever the result is used later in the fragment program, fglrx forces x and w
-//  to be 1.0 in the input selection; I don't know whether this is strictly necessary */
+/* BEGIN: Vertex program instruction set */
+
+/* Every instruction is four dwords long:
+ *  DWORD 0: output and opcode
+ *  DWORD 1: first argument
+ *  DWORD 2: second argument
+ *  DWORD 3: third argument
+ *
+ * Notes:
+ *  - ABS r, a is implemented as MAX r, a, -a
+ *  - MOV is implemented as ADD to zero
+ *  - XPD is implemented as MUL + MAD
+ *  - FLR is implemented as FRC + ADD
+ *  - apparently, fglrx tries to schedule instructions so that there is at
+ *    least one instruction between the write to a temporary and the first
+ *    read from said temporary; however, violations of this scheduling are
+ *    allowed
+ *  - register indices seem to be unrelated with OpenGL aliasing to
+ *    conventional state
+ *  - only one attribute and one parameter can be loaded at a time; however,
+ *    the same attribute/parameter can be used for more than one argument
+ *  - the second software argument for POW is the third hardware argument
+ *    (no idea why)
+ *  - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
+ *
+ * There is some magic surrounding LIT:
+ *   The single argument is replicated across all three inputs, but swizzled:
+ *     First argument: xyzy
+ *     Second argument: xyzx
+ *     Third argument: xyzw
+ *   Whenever the result is used later in the fragment program, fglrx forces
+ *   x and w to be 1.0 in the input selection; I don't know whether this is
+ *   strictly necessary
+ */
 #define R300_VPI_OUT_OP_DOT                     (1 << 0)
 #define R300_VPI_OUT_OP_MUL                     (2 << 0)
 #define R300_VPI_OUT_OP_ADD                     (3 << 0)
@@ -1318,26 +1478,33 @@
 #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) */
+	/* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+#define R300_VPI_OUT_OP_UNK12                   (12 << 0)
+#define R300_VPI_OUT_OP_ARL                     (13 << 0)
 #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) */
+	/* Used in fog computations, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK67                   (67 << 0)
 #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) */
+	/* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK73                   (73 << 0)
 #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) */
+	/* all temps, vector(scalar, vector, vector) */
+#define R300_VPI_OUT_OP_UNK129                  (129 << 0)
 
 #define R300_VPI_OUT_REG_CLASS_TEMPORARY        (0 << 8)
+#define R300_VPI_OUT_REG_CLASS_ADDR             (1 << 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 */
+	/* GUESS based on fglrx native limits */
+#define R300_VPI_OUT_REG_INDEX_MASK             (31 << 13)
 
 #define R300_VPI_OUT_WRITE_X                    (1 << 20)
 #define R300_VPI_OUT_WRITE_Y                    (1 << 21)
@@ -1348,14 +1515,16 @@
 #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)
 
 #define R300_VPI_IN_REG_INDEX_SHIFT             5
-#define R300_VPI_IN_REG_INDEX_MASK              (255 << 5)	/* GUESS based on fglrx native limits */
+	/* GUESS based on fglrx native limits */
+#define R300_VPI_IN_REG_INDEX_MASK              (255 << 5)
 
 /* The R300 can select components from the input register arbitrarily.
-// Use the following constants, shifted by the component shift you
-// want to select */
+ * Use the following constants, shifted by the component shift you
+ * want to select
+ */
 #define R300_VPI_IN_SELECT_X    0
 #define R300_VPI_IN_SELECT_Y    1
 #define R300_VPI_IN_SELECT_Z    2
@@ -1373,11 +1542,11 @@
 #define R300_VPI_IN_NEG_Y                       (1 << 26)
 #define R300_VPI_IN_NEG_Z                       (1 << 27)
 #define R300_VPI_IN_NEG_W                       (1 << 28)
-/* END */
+/* END: Vertex program instruction set */
 
-//BEGIN: Packet 3 commands
+/* BEGIN: Packet 3 commands */
 
-// A primitive emission dword.
+/* A primitive emission dword. */
 #define R300_PRIM_TYPE_NONE                     (0 << 0)
 #define R300_PRIM_TYPE_POINT                    (1 << 0)
 #define R300_PRIM_TYPE_LINE                     (2 << 0)
@@ -1389,7 +1558,8 @@
 #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)
+	/* GUESS (based on r200) */
+#define R300_PRIM_TYPE_POINT_SPRITES            (11 << 0)
 #define R300_PRIM_TYPE_LINE_LOOP                (12 << 0)
 #define R300_PRIM_TYPE_QUADS                    (13 << 0)
 #define R300_PRIM_TYPE_QUAD_STRIP               (14 << 0)
@@ -1399,37 +1569,58 @@
 #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
+	/* GUESS (based on r200) */
+#define R300_PRIM_COLOR_ORDER_BGRA              (0 << 6)
+#define R300_PRIM_COLOR_ORDER_RGBA              (1 << 6)
 #define R300_PRIM_NUM_VERTICES_SHIFT            16
+#define R300_PRIM_NUM_VERTICES_MASK             0xffff
 
-// Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
-// Two parameter dwords:
-// 0. The first parameter appears to be always 0
-// 1. The second parameter is a standard primitive emission dword.
+/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+ * Two parameter dwords:
+ * 0. The first parameter appears to be always 0
+ * 1. The second parameter is a standard primitive emission dword.
+ */
 #define R300_PACKET3_3D_DRAW_VBUF           0x00002800
 
-// Specify the full set of vertex arrays as (address, stride).
-// The first parameter is the number of vertex arrays specified.
-// The rest of the command is a variable length list of blocks, where
-// each block is three dwords long and specifies two arrays.
-// The first dword of a block is split into two words, the lower significant
-// word refers to the first array, the more significant word to the second
-// array in the block.
-// The low byte of each word contains the size of an array entry in dwords,
-// the high byte contains the stride of the array.
-// The second dword of a block contains the pointer to the first array,
-// the third dword of a block contains the pointer to the second array.
-// Note that if the total number of arrays is odd, the third dword of
-// the last block is omitted.
+/* Specify the full set of vertex arrays as (address, stride).
+ * The first parameter is the number of vertex arrays specified.
+ * The rest of the command is a variable length list of blocks, where
+ * each block is three dwords long and specifies two arrays.
+ * The first dword of a block is split into two words, the lower significant
+ * word refers to the first array, the more significant word to the second
+ * array in the block.
+ * The low byte of each word contains the size of an array entry in dwords,
+ * the high byte contains the stride of the array.
+ * The second dword of a block contains the pointer to the first array,
+ * the third dword of a block contains the pointer to the second array.
+ * Note that if the total number of arrays is odd, the third dword of
+ * the last block is omitted.
+ */
 #define R300_PACKET3_3D_LOAD_VBPNTR         0x00002F00
 
 #define R300_PACKET3_INDX_BUFFER            0x00003300
 #    define R300_EB_UNK1_SHIFT                      24
 #    define R300_EB_UNK1                    (0x80<<24)
 #    define R300_EB_UNK2                        0x0810
+#define R300_PACKET3_3D_DRAW_VBUF_2         0x00003400
 #define R300_PACKET3_3D_DRAW_INDX_2         0x00003600
 
-//END
+/* END: Packet 3 commands */
 
-#endif				/* _R300_REG_H */
+
+/* Color formats for 2d packets
+ */
+#define R300_CP_COLOR_FORMAT_CI8	2
+#define R300_CP_COLOR_FORMAT_ARGB1555	3
+#define R300_CP_COLOR_FORMAT_RGB565	4
+#define R300_CP_COLOR_FORMAT_ARGB8888	6
+#define R300_CP_COLOR_FORMAT_RGB332	7
+#define R300_CP_COLOR_FORMAT_RGB8	9
+#define R300_CP_COLOR_FORMAT_ARGB4444	15
+
+/*
+ * CP type-3 packets
+ */
+#define R300_CP_CMD_BITBLT_MULTI	0xC0009B00
+
+#endif /* _R300_REG_H */
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 68338389..af5790f 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -36,7 +36,7 @@
 
 #define RADEON_FIFO_DEBUG	0
 
-static int radeon_do_cleanup_cp(drm_device_t * dev);
+static int radeon_do_cleanup_cp(struct drm_device * dev);
 
 /* CP microcode (from ATI) */
 static const u32 R200_cp_microcode[][2] = {
@@ -816,7 +816,7 @@
 	{0000000000, 0000000000},
 };
 
-static int RADEON_READ_PLL(drm_device_t * dev, int addr)
+static int RADEON_READ_PLL(struct drm_device * dev, int addr)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1066,7 +1066,7 @@
 
 /* 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(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
@@ -1122,7 +1122,7 @@
 	return 0;
 }
 
-static void radeon_cp_init_ring_buffer(drm_device_t * dev,
+static void radeon_cp_init_ring_buffer(struct drm_device * dev,
 				       drm_radeon_private_t * dev_priv)
 {
 	u32 ring_start, cur_read_ptr;
@@ -1174,7 +1174,7 @@
 	} else
 #endif
 	{
-		drm_sg_mem_t *entry = dev->sg;
+		struct drm_sg_mem *entry = dev->sg;
 		unsigned long tmp_ofs, page_ofs;
 
 		tmp_ofs = dev_priv->ring_rptr->offset -
@@ -1384,7 +1384,7 @@
 	}
 }
 
-static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1420,6 +1420,10 @@
 		return DRM_ERR(EINVAL);
 	}
 
+	/* Enable vblank on CRTC1 for older X servers
+	 */
+	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
+
 	switch(init->func) {
 	case RADEON_INIT_R200_CP:
 		dev_priv->microcode_version = UCODE_R200;
@@ -1501,13 +1505,13 @@
 					 RADEON_ROUND_MODE_TRUNC |
 					 RADEON_ROUND_PREC_8TH_PIX);
 
-	DRM_GETSAREA();
 
 	dev_priv->ring_offset = init->ring_offset;
 	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;
 
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		radeon_do_cleanup_cp(dev);
@@ -1731,7 +1735,7 @@
 	return 0;
 }
 
-static int radeon_do_cleanup_cp(drm_device_t * dev)
+static int radeon_do_cleanup_cp(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG("\n");
@@ -1787,7 +1791,7 @@
  *
  * Charl P. Botha <http://cpbotha.net>
  */
-static int radeon_do_resume_cp(drm_device_t * dev)
+static int radeon_do_resume_cp(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1914,7 +1918,7 @@
 	return 0;
 }
 
-void radeon_do_release(drm_device_t * dev)
+void radeon_do_release(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	int i, ret;
@@ -2042,12 +2046,12 @@
  * they can't get the lock.
  */
 
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i, t;
 	int start;
 
@@ -2082,12 +2086,12 @@
 }
 
 #if 0
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i, t;
 	int start;
 	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
@@ -2116,15 +2120,15 @@
 }
 #endif
 
-void radeon_freelist_reset(drm_device_t * dev)
+void radeon_freelist_reset(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *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++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
 		buf_priv->age = 0;
 	}
@@ -2166,11 +2170,11 @@
 	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, struct drm_device * dev,
+				 struct drm_dma * d)
 {
 	int i;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
 		buf = radeon_freelist_get(dev);
@@ -2194,10 +2198,10 @@
 int radeon_cp_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int ret = 0;
-	drm_dma_t __user *argp = (void __user *)data;
-	drm_dma_t d;
+	struct drm_dma __user *argp = (void __user *)data;
+	struct drm_dma d;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 66c4b6f..5a8e23f 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -417,7 +417,7 @@
 
 	/* The current cliprects, or a subset thereof.
 	 */
-	drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS];
 	unsigned int nbox;
 
 	/* Counters for client-side throttling of rendering clients.
@@ -426,7 +426,7 @@
 	unsigned int last_dispatch;
 	unsigned int last_clear;
 
-	drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
+	struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
 						       1];
 	unsigned int tex_age[RADEON_NR_TEX_HEAPS];
 	int ctx_owner;
@@ -604,7 +604,7 @@
 	int bufsz;
 	char __user *buf;
 	int nbox;
-	drm_clip_rect_t __user *boxes;
+	struct drm_clip_rect __user *boxes;
 } drm_radeon_cmd_buffer_t;
 
 typedef struct drm_radeon_tex_image {
@@ -655,6 +655,7 @@
 #define RADEON_PARAM_GART_TEX_HANDLE       10
 #define RADEON_PARAM_SCRATCH_OFFSET        11
 #define RADEON_PARAM_CARD_TYPE             12
+#define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */
 
 typedef struct drm_radeon_getparam {
 	int param;
@@ -708,7 +709,7 @@
 #define RADEON_SETPARAM_PCIGART_LOCATION 3	/* PCI Gart Location */
 #define RADEON_SETPARAM_NEW_MEMMAP 4		/* Use new memory map */
 #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5    /* PCI GART Table Size */
-
+#define RADEON_SETPARAM_VBLANK_CRTC 6           /* VBLANK CRTC */
 /* 1.14: Clients can allocate/free a surface
  */
 typedef struct drm_radeon_surface_alloc {
@@ -721,4 +722,7 @@
 	unsigned int address;
 } drm_radeon_surface_free_t;
 
+#define	DRM_RADEON_VBLANK_CRTC1 	1
+#define	DRM_RADEON_VBLANK_CRTC2 	2
+
 #endif
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 2eb652e..349ac3d 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -60,7 +60,7 @@
 	.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_IRQ_VBL | DRIVER_IRQ_VBL2,
 	.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
 	.load = radeon_driver_load,
 	.firstopen = radeon_driver_firstopen,
@@ -70,6 +70,7 @@
 	.lastclose = radeon_driver_lastclose,
 	.unload = radeon_driver_unload,
 	.vblank_wait = radeon_driver_vblank_wait,
+	.vblank_wait2 = radeon_driver_vblank_wait2,
 	.dri_library_name = dri_library_name,
 	.irq_preinstall = radeon_driver_irq_preinstall,
 	.irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 54f49ef..3b3d935 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -97,9 +97,10 @@
  *       new packet type)
  * 1.26- Add support for variable size PCI(E) gart aperture
  * 1.27- Add support for IGP GART
+ * 1.28- Add support for VBL on CRTC2
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		27
+#define DRIVER_MINOR		28
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -154,7 +155,7 @@
 
 typedef struct drm_radeon_freelist {
 	unsigned int age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	struct drm_radeon_freelist *next;
 	struct drm_radeon_freelist *prev;
 } drm_radeon_freelist_t;
@@ -277,13 +278,16 @@
 	/* SW interrupt */
 	wait_queue_head_t swi_queue;
 	atomic_t swi_emitted;
+	int vblank_crtc;
+	uint32_t irq_enable_reg;
+	int irq_enabled;
 
 	struct radeon_surface surfaces[RADEON_MAX_SURFACES];
 	struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
 
 	unsigned long pcigart_offset;
 	unsigned int pcigart_offset_set;
-	drm_ati_pcigart_info gart_info;
+	struct drm_ati_pcigart_info gart_info;
 
 	u32 scratch_ages[5];
 
@@ -299,7 +303,7 @@
 	int bufsz;
 	char *buf;
 	int nbox;
-	drm_clip_rect_t __user *boxes;
+	struct drm_clip_rect __user *boxes;
 } drm_radeon_kcmd_buffer_t;
 
 extern int radeon_no_wb;
@@ -332,8 +336,8 @@
 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(struct drm_device * dev);
+extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
 
 extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
 
@@ -353,29 +357,33 @@
 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,
+extern void radeon_do_release(struct drm_device * dev);
+extern int radeon_driver_vblank_wait(struct drm_device * dev,
 				     unsigned int *sequence);
+extern int radeon_driver_vblank_wait2(struct drm_device * 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_irq_preinstall(struct drm_device * dev);
+extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern void radeon_driver_irq_uninstall(struct drm_device * dev);
+extern int radeon_vblank_crtc_get(struct drm_device *dev);
+extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
 
 extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
 extern int radeon_driver_unload(struct drm_device *dev);
 extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp);
-extern void radeon_driver_lastclose(drm_device_t * dev);
-extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv);
+extern void radeon_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp);
+extern void radeon_driver_lastclose(struct drm_device * dev);
+extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv);
 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,
+extern int r300_do_cp_cmdbuf(struct drm_device * dev, DRMFILE filp,
+			     struct drm_file * filp_priv,
 			     drm_radeon_kcmd_buffer_t * cmdbuf);
 
 /* Flags for stats.boxes
@@ -496,12 +504,15 @@
 
 #define RADEON_GEN_INT_CNTL		0x0040
 #	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
+#	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
 #	define RADEON_GUI_IDLE_INT_ENABLE	(1 << 19)
 #	define RADEON_SW_INT_ENABLE		(1 << 25)
 
 #define RADEON_GEN_INT_STATUS		0x0044
 #	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
 #	define RADEON_CRTC_VBLANK_STAT_ACK   	(1 << 0)
+#	define RADEON_CRTC2_VBLANK_STAT		(1 << 9)
+#	define RADEON_CRTC2_VBLANK_STAT_ACK   	(1 << 9)
 #	define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
 #	define RADEON_SW_INT_TEST		(1 << 25)
 #	define RADEON_SW_INT_TEST_ACK   	(1 << 25)
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 3ff0baa..ad8a0ac 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -64,7 +64,7 @@
 
 irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	u32 stat;
@@ -73,18 +73,35 @@
 	 * outside the DRM
 	 */
 	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-						  RADEON_CRTC_VBLANK_STAT));
+						  RADEON_CRTC_VBLANK_STAT |
+						  RADEON_CRTC2_VBLANK_STAT));
 	if (!stat)
 		return IRQ_NONE;
 
+	stat &= dev_priv->irq_enable_reg;
+
 	/* SW interrupt */
 	if (stat & RADEON_SW_INT_TEST) {
 		DRM_WAKEUP(&dev_priv->swi_queue);
 	}
 
 	/* VBLANK interrupt */
-	if (stat & RADEON_CRTC_VBLANK_STAT) {
-		atomic_inc(&dev->vbl_received);
+	if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
+		int vblank_crtc = dev_priv->vblank_crtc;
+
+		if ((vblank_crtc &
+		     (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
+		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+			if (stat & RADEON_CRTC_VBLANK_STAT)
+				atomic_inc(&dev->vbl_received);
+			if (stat & RADEON_CRTC2_VBLANK_STAT)
+				atomic_inc(&dev->vbl_received2);
+		} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
+			   (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
+			   ((stat & RADEON_CRTC2_VBLANK_STAT) &&
+			    (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
+			atomic_inc(&dev->vbl_received);
+
 		DRM_WAKEUP(&dev->vbl_queue);
 		drm_vbl_send_signals(dev);
 	}
@@ -92,7 +109,7 @@
 	return IRQ_HANDLED;
 }
 
-static int radeon_emit_irq(drm_device_t * dev)
+static int radeon_emit_irq(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	unsigned int ret;
@@ -110,7 +127,7 @@
 	return ret;
 }
 
-static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
+static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
@@ -127,19 +144,30 @@
 	return ret;
 }
 
-int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int radeon_driver_vblank_do_wait(struct drm_device * dev, unsigned int *sequence,
+				 int crtc)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	unsigned int cur_vblank;
 	int ret = 0;
-
+	int ack = 0;
+	atomic_t *counter;
 	if (!dev_priv) {
 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
 		return DRM_ERR(EINVAL);
 	}
 
-	radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
+	if (crtc == DRM_RADEON_VBLANK_CRTC1) {
+		counter = &dev->vbl_received;
+		ack |= RADEON_CRTC_VBLANK_STAT;
+	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
+		counter = &dev->vbl_received2;
+		ack |= RADEON_CRTC2_VBLANK_STAT;
+	} else
+		return DRM_ERR(EINVAL);
+
+	radeon_acknowledge_irqs(dev_priv, ack);
 
 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
@@ -148,7 +176,7 @@
 	 * using vertical blanks...
 	 */
 	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received))
+		    (((cur_vblank = atomic_read(counter))
 		      - *sequence) <= (1 << 23)));
 
 	*sequence = cur_vblank;
@@ -156,6 +184,16 @@
 	return ret;
 }
 
+int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+{
+	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+}
+
+int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+{
+	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+}
+
 /* Needs the lock as it touches the ring.
  */
 int radeon_irq_emit(DRM_IOCTL_ARGS)
@@ -204,9 +242,24 @@
 	return radeon_wait_irq(dev, irqwait.irq_seq);
 }
 
+static void radeon_enable_interrupt(struct drm_device *dev)
+{
+	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+
+	dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
+	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
+		dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
+
+	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
+		dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
+
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+	dev_priv->irq_enabled = 1;
+}
+
 /* drm_dma.h hooks
 */
-void radeon_driver_irq_preinstall(drm_device_t * dev)
+void radeon_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
@@ -216,10 +269,11 @@
 
 	/* Clear bits if they're already high */
 	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-					   RADEON_CRTC_VBLANK_STAT));
+					   RADEON_CRTC_VBLANK_STAT |
+					   RADEON_CRTC2_VBLANK_STAT));
 }
 
-void radeon_driver_irq_postinstall(drm_device_t * dev)
+void radeon_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
@@ -227,18 +281,48 @@
 	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_enable_interrupt(dev);
 }
 
-void radeon_driver_irq_uninstall(drm_device_t * dev)
+void radeon_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	if (!dev_priv)
 		return;
 
+	dev_priv->irq_enabled = 0;
+
 	/* Disable *all* interrupts */
 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 }
+
+
+int radeon_vblank_crtc_get(struct drm_device *dev)
+{
+	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+	u32 flag;
+	u32 value;
+
+	flag = RADEON_READ(RADEON_GEN_INT_CNTL);
+	value = 0;
+
+	if (flag & RADEON_CRTC_VBLANK_MASK)
+		value |= DRM_RADEON_VBLANK_CRTC1;
+
+	if (flag & RADEON_CRTC2_VBLANK_MASK)
+		value |= DRM_RADEON_VBLANK_CRTC2;
+	return value;
+}
+
+int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
+{
+	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+	if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+		DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
+		return DRM_ERR(EINVAL);
+	}
+	dev_priv->vblank_crtc = (unsigned int)value;
+	radeon_enable_interrupt(dev);
+	return 0;
+}
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 98c5f1d..3ddf86f 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -39,7 +39,7 @@
 
 static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
 						    dev_priv,
-						    drm_file_t * filp_priv,
+						    struct drm_file * filp_priv,
 						    u32 *offset)
 {
 	u64 off = *offset;
@@ -90,7 +90,7 @@
 
 static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 						     dev_priv,
-						     drm_file_t * filp_priv,
+						     struct drm_file * filp_priv,
 						     int id, u32 *data)
 {
 	switch (id) {
@@ -264,7 +264,7 @@
 
 static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
 						     dev_priv,
-						     drm_file_t *filp_priv,
+						     struct drm_file *filp_priv,
 						     drm_radeon_kcmd_buffer_t *
 						     cmdbuf,
 						     unsigned int *cmdsz)
@@ -421,7 +421,7 @@
  */
 
 static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-					     drm_clip_rect_t * box)
+					     struct drm_clip_rect * box)
 {
 	RING_LOCALS;
 
@@ -439,7 +439,7 @@
 /* Emit 1.1 state
  */
 static int radeon_emit_state(drm_radeon_private_t * dev_priv,
-			     drm_file_t * filp_priv,
+			     struct drm_file * filp_priv,
 			     drm_radeon_context_regs_t * ctx,
 			     drm_radeon_texture_regs_t * tex,
 			     unsigned int dirty)
@@ -608,7 +608,7 @@
 /* Emit 1.2 state
  */
 static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
-			      drm_file_t * filp_priv,
+			      struct drm_file * filp_priv,
 			      drm_radeon_state_t * state)
 {
 	RING_LOCALS;
@@ -844,7 +844,7 @@
  * CP command dispatch functions
  */
 
-static void radeon_cp_dispatch_clear(drm_device_t * dev,
+static void radeon_cp_dispatch_clear(struct drm_device * dev,
 				     drm_radeon_clear_t * clear,
 				     drm_radeon_clear_rect_t * depth_boxes)
 {
@@ -852,7 +852,7 @@
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	unsigned int flags = clear->flags;
 	u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
 	int i;
@@ -1335,12 +1335,12 @@
 	ADVANCE_RING();
 }
 
-static void radeon_cp_dispatch_swap(drm_device_t * dev)
+static void radeon_cp_dispatch_swap(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG("\n");
@@ -1412,10 +1412,10 @@
 	ADVANCE_RING();
 }
 
-static void radeon_cp_dispatch_flip(drm_device_t * dev)
+static void radeon_cp_dispatch_flip(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
+	struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
 	int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
 	    ? dev_priv->front_offset : dev_priv->back_offset;
 	RING_LOCALS;
@@ -1491,8 +1491,8 @@
 	unsigned int vc_format;
 } drm_radeon_tcl_prim_t;
 
-static void radeon_cp_dispatch_vertex(drm_device_t * dev,
-				      drm_buf_t * buf,
+static void radeon_cp_dispatch_vertex(struct drm_device * dev,
+				      struct drm_buf * buf,
 				      drm_radeon_tcl_prim_t * prim)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1537,7 +1537,7 @@
 	} while (i < nbox);
 }
 
-static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -1554,8 +1554,8 @@
 	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(struct drm_device * dev,
+					struct drm_buf * buf, int start, int end)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -1588,8 +1588,8 @@
 	}
 }
 
-static void radeon_cp_dispatch_indices(drm_device_t * dev,
-				       drm_buf_t * elt_buf,
+static void radeon_cp_dispatch_indices(struct drm_device * dev,
+				       struct drm_buf * elt_buf,
 				       drm_radeon_tcl_prim_t * prim)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1647,13 +1647,13 @@
 #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
 
 static int radeon_cp_dispatch_texture(DRMFILE filp,
-				      drm_device_t * dev,
+				      struct drm_device * 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;
-	drm_buf_t *buf;
+	struct drm_file *filp_priv;
+	struct drm_buf *buf;
 	u32 format;
 	u32 *buffer;
 	const u8 __user *data;
@@ -1881,7 +1881,7 @@
 	return 0;
 }
 
-static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -2134,7 +2134,7 @@
 
 /* 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(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -2206,10 +2206,10 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_vertex_t vertex;
 	drm_radeon_tcl_prim_t prim;
 
@@ -2289,10 +2289,10 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_indices_t elts;
 	drm_radeon_tcl_prim_t prim;
 	int count;
@@ -2438,8 +2438,8 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_indirect_t indirect;
 	RING_LOCALS;
 
@@ -2507,10 +2507,10 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_vertex2_t vertex;
 	int i;
 	unsigned char laststate;
@@ -2603,7 +2603,7 @@
 }
 
 static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
-			       drm_file_t * filp_priv,
+			       struct drm_file * filp_priv,
 			       drm_radeon_cmd_header_t header,
 			       drm_radeon_kcmd_buffer_t *cmdbuf)
 {
@@ -2728,8 +2728,8 @@
 	return 0;
 }
 
-static int radeon_emit_packet3(drm_device_t * dev,
-			       drm_file_t * filp_priv,
+static int radeon_emit_packet3(struct drm_device * dev,
+			       struct drm_file * filp_priv,
 			       drm_radeon_kcmd_buffer_t *cmdbuf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2754,16 +2754,16 @@
 	return 0;
 }
 
-static int radeon_emit_packet3_cliprect(drm_device_t *dev,
-					drm_file_t *filp_priv,
+static int radeon_emit_packet3_cliprect(struct drm_device *dev,
+					struct drm_file *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;
+	struct drm_clip_rect box;
 	unsigned int cmdsz;
 	int ret;
-	drm_clip_rect_t __user *boxes = cmdbuf->boxes;
+	struct drm_clip_rect __user *boxes = cmdbuf->boxes;
 	int i = 0;
 	RING_LOCALS;
 
@@ -2816,7 +2816,7 @@
 	return 0;
 }
 
-static int radeon_emit_wait(drm_device_t * dev, int flags)
+static int radeon_emit_wait(struct drm_device * dev, int flags)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -2849,9 +2849,9 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf = NULL;
+	struct drm_file *filp_priv;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf = NULL;
 	int idx;
 	drm_radeon_kcmd_buffer_t cmdbuf;
 	drm_radeon_cmd_header_t header;
@@ -3085,6 +3085,9 @@
 		else
 			value = RADEON_CARD_PCI;
 		break;
+	case RADEON_PARAM_VBLANK_CRTC:
+		value = radeon_vblank_crtc_get(dev);
+		break;
 	default:
 		DRM_DEBUG("Invalid parameter %d\n", param.param);
 		return DRM_ERR(EINVAL);
@@ -3102,7 +3105,7 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_setparam_t sp;
 	struct drm_radeon_driver_file_fields *radeon_priv;
 
@@ -3141,6 +3144,9 @@
 		if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
 			dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
 		break;
+	case RADEON_SETPARAM_VBLANK_CRTC:
+		return radeon_vblank_crtc_set(dev, sp.value);
+		break;
 	default:
 		DRM_DEBUG("Invalid parameter %d\n", sp.param);
 		return DRM_ERR(EINVAL);
@@ -3156,7 +3162,7 @@
  *
  * DRM infrastructure takes care of reclaiming dma buffers.
  */
-void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void radeon_driver_preclose(struct drm_device *dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3167,7 +3173,7 @@
 	}
 }
 
-void radeon_driver_lastclose(drm_device_t * dev)
+void radeon_driver_lastclose(struct drm_device *dev)
 {
 	if (dev->dev_private) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3180,7 +3186,7 @@
 	radeon_do_release(dev);
 }
 
-int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
+int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	struct drm_radeon_driver_file_fields *radeon_priv;
@@ -3202,7 +3208,7 @@
 	return 0;
 }
 
-void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
+void radeon_driver_postclose(struct drm_device *dev, struct drm_file *filp_priv)
 {
 	struct drm_radeon_driver_file_fields *radeon_priv =
 	    filp_priv->driver_priv;
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index b94fab5..18c7235 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -32,7 +32,7 @@
 #define SAVAGE_EVENT_USEC_TIMEOUT	5000000	/* 5s */
 #define SAVAGE_FREELIST_DEBUG		0
 
-static int savage_do_cleanup_bci(drm_device_t *dev);
+static int savage_do_cleanup_bci(struct drm_device *dev);
 
 static int
 savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
@@ -203,11 +203,11 @@
 /*
  * Freelist management
  */
-static int savage_freelist_init(drm_device_t * dev)
+static int savage_freelist_init(struct drm_device * dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_savage_buf_priv_t *entry;
 	int i;
 	DRM_DEBUG("count=%d\n", dma->buf_count);
@@ -236,7 +236,7 @@
 	return 0;
 }
 
-static drm_buf_t *savage_freelist_get(drm_device_t * dev)
+static struct drm_buf *savage_freelist_get(struct drm_device * dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
@@ -269,7 +269,7 @@
 	return NULL;
 }
 
-void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
@@ -535,7 +535,7 @@
 	dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
 }
 
-int savage_driver_load(drm_device_t *dev, unsigned long chipset)
+int savage_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	drm_savage_private_t *dev_priv;
 
@@ -558,7 +558,7 @@
  * in drm_addmap. Therefore we add them manually before the maps are
  * initialized, and tear them down on last close.
  */
-int savage_driver_firstopen(drm_device_t *dev)
+int savage_driver_firstopen(struct drm_device *dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	unsigned long mmio_base, fb_base, fb_size, aperture_base;
@@ -655,7 +655,7 @@
 /*
  * Delete MTRRs and free device-private data.
  */
-void savage_driver_lastclose(drm_device_t *dev)
+void savage_driver_lastclose(struct drm_device *dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -667,7 +667,7 @@
 				 dev_priv->mtrr[i].size, DRM_MTRR_WC);
 }
 
-int savage_driver_unload(drm_device_t *dev)
+int savage_driver_unload(struct drm_device *dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -676,7 +676,7 @@
 	return 0;
 }
 
-static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
+static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -711,7 +711,7 @@
 	dev_priv->texture_offset = init->texture_offset;
 	dev_priv->texture_size = init->texture_size;
 
-	DRM_GETSAREA();
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		savage_do_cleanup_bci(dev);
@@ -898,7 +898,7 @@
 	return 0;
 }
 
-static int savage_do_cleanup_bci(drm_device_t * dev)
+static int savage_do_cleanup_bci(struct drm_device * dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -1007,9 +1007,9 @@
  * 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, struct drm_device *dev, struct drm_dma *d)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
@@ -1034,13 +1034,13 @@
 int savage_bci_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
-	drm_dma_t d;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_dma d;
 	int ret = 0;
 
 	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, (struct drm_dma __user *) data, sizeof(d));
 
 	/* Please don't send us buffers.
 	 */
@@ -1064,14 +1064,14 @@
 		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((struct drm_dma __user *) data, d, sizeof(d));
 
 	return ret;
 }
 
-void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
+void savage_reclaim_buffers(struct drm_device *dev, DRMFILE filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	int i;
 
@@ -1085,7 +1085,7 @@
 	/*i830_flush_queue(dev); */
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_savage_buf_priv_t *buf_priv = buf->dev_private;
 
 		if (buf->filp == filp && buf_priv &&
diff --git a/drivers/char/drm/savage_drm.h b/drivers/char/drm/savage_drm.h
index e1148e8..8a576ef 100644
--- a/drivers/char/drm/savage_drm.h
+++ b/drivers/char/drm/savage_drm.h
@@ -47,7 +47,7 @@
 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 +
+	struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
 						      1];
 	unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
 
@@ -113,7 +113,7 @@
 	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 */
-	drm_clip_rect_t __user *box_addr;
+	struct drm_clip_rect __user *box_addr;
 	unsigned int nbox;	/* number of clipping boxes */
 } drm_savage_cmdbuf_t;
 
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
index 8f04b3d..5fd54de 100644
--- a/drivers/char/drm/savage_drv.h
+++ b/drivers/char/drm/savage_drv.h
@@ -58,7 +58,7 @@
 	struct drm_savage_buf_priv *next;
 	struct drm_savage_buf_priv *prev;
 	drm_savage_age_t age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 } drm_savage_buf_priv_t;
 
 typedef struct drm_savage_dma_page {
@@ -192,7 +192,7 @@
 	/* 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,
-				const drm_clip_rect_t * pbox);
+				const struct drm_clip_rect * pbox);
 	void (*dma_flush) (struct drm_savage_private * dev_priv);
 } drm_savage_private_t;
 
@@ -203,22 +203,22 @@
 /* BCI functions */
 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_freelist_put(struct drm_device * dev, struct drm_buf * 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_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int savage_driver_firstopen(drm_device_t *dev);
-extern void savage_driver_lastclose(drm_device_t *dev);
-extern int savage_driver_unload(drm_device_t *dev);
-extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);
+extern int savage_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int savage_driver_firstopen(struct drm_device *dev);
+extern void savage_driver_lastclose(struct drm_device *dev);
+extern int savage_driver_unload(struct drm_device *dev);
+extern void savage_reclaim_buffers(struct drm_device * dev, DRMFILE filp);
 
 /* state functions */
 extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
-				      const drm_clip_rect_t * pbox);
+				      const struct drm_clip_rect * pbox);
 extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
-				     const drm_clip_rect_t * pbox);
+				     const struct drm_clip_rect * pbox);
 
 #define SAVAGE_FB_SIZE_S3	0x01000000	/*  16MB */
 #define SAVAGE_FB_SIZE_S4	0x02000000	/*  32MB */
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
index 1ca1e9c..7749784 100644
--- a/drivers/char/drm/savage_state.c
+++ b/drivers/char/drm/savage_state.c
@@ -27,7 +27,7 @@
 #include "savage_drv.h"
 
 void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
-			       const drm_clip_rect_t * pbox)
+			       const struct drm_clip_rect * pbox)
 {
 	uint32_t scstart = dev_priv->state.s3d.new_scstart;
 	uint32_t scend = dev_priv->state.s3d.new_scend;
@@ -53,7 +53,7 @@
 }
 
 void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
-			      const drm_clip_rect_t * pbox)
+			      const struct drm_clip_rect * pbox)
 {
 	uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
 	uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
@@ -277,7 +277,7 @@
 
 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)
+				    const struct drm_buf * dmabuf)
 {
 	unsigned char reorder = 0;
 	unsigned int prim = cmd_header->prim.prim;
@@ -536,7 +536,7 @@
 static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
 				   const drm_savage_cmd_header_t * cmd_header,
 				   const uint16_t *idx,
-				   const drm_buf_t * dmabuf)
+				   const struct drm_buf * dmabuf)
 {
 	unsigned char reorder = 0;
 	unsigned int prim = cmd_header->idx.prim;
@@ -792,7 +792,7 @@
 				 const drm_savage_cmd_header_t * cmd_header,
 				 const drm_savage_cmd_header_t *data,
 				 unsigned int nbox,
-				 const drm_clip_rect_t *boxes)
+				 const struct drm_clip_rect *boxes)
 {
 	unsigned int flags = cmd_header->clear0.flags;
 	unsigned int clear_cmd;
@@ -861,7 +861,7 @@
 }
 
 static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
-				unsigned int nbox, const drm_clip_rect_t *boxes)
+				unsigned int nbox, const struct drm_clip_rect *boxes)
 {
 	unsigned int swap_cmd;
 	unsigned int i;
@@ -892,11 +892,11 @@
 static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
 				const drm_savage_cmd_header_t *start,
 				const drm_savage_cmd_header_t *end,
-				const drm_buf_t * dmabuf,
+				const struct drm_buf * dmabuf,
 				const unsigned int *vtxbuf,
 				unsigned int vb_size, unsigned int vb_stride,
 				unsigned int nbox,
-				const drm_clip_rect_t *boxes)
+				const struct drm_clip_rect *boxes)
 {
 	unsigned int i, j;
 	int ret;
@@ -957,13 +957,13 @@
 {
 	DRM_DEVICE;
 	drm_savage_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *dmabuf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *dmabuf;
 	drm_savage_cmdbuf_t cmdbuf;
 	drm_savage_cmd_header_t *kcmd_addr = NULL;
 	drm_savage_cmd_header_t *first_draw_cmd;
 	unsigned int *kvb_addr = NULL;
-	drm_clip_rect_t *kbox_addr = NULL;
+	struct drm_clip_rect *kbox_addr = NULL;
 	unsigned int i, j;
 	int ret = 0;
 
@@ -1019,7 +1019,7 @@
 		cmdbuf.vb_addr = kvb_addr;
 	}
 	if (cmdbuf.nbox) {
-		kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),
+		kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(struct drm_clip_rect),
 				       DRM_MEM_DRIVER);
 		if (kbox_addr == NULL) {
 			ret = DRM_ERR(ENOMEM);
@@ -1027,7 +1027,7 @@
 		}
 
 		if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,
-				       cmdbuf.nbox * sizeof(drm_clip_rect_t))) {
+				       cmdbuf.nbox * sizeof(struct drm_clip_rect))) {
 			ret = DRM_ERR(EFAULT);
 			goto done;
 		}
@@ -1158,7 +1158,7 @@
 	/* If we didn't need to allocate them, these'll be NULL */
 	drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
 	drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);
-	drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),
+	drm_free(kbox_addr, cmdbuf.nbox * sizeof(struct drm_clip_rect),
 		 DRM_MEM_DRIVER);
 
 	return ret;
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 690e0af..1912f58 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -35,7 +35,7 @@
 	sisdrv_PCI_IDS
 };
 
-static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
+static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	drm_sis_private_t *dev_priv;
 	int ret;
@@ -54,7 +54,7 @@
 	return ret;
 }
 
-static int sis_driver_unload(drm_device_t *dev)
+static int sis_driver_unload(struct drm_device *dev)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
 
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 70d4ede..5630df8 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -46,6 +46,7 @@
 
 #include "drm_sman.h"
 
+
 #define SIS_BASE (dev_priv->mmio)
 #define SIS_READ(reg)         DRM_READ32(SIS_BASE, reg);
 #define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val);
@@ -53,7 +54,7 @@
 typedef struct drm_sis_private {
 	drm_local_map_t *mmio;
 	unsigned int idle_fault;
-	drm_sman_t sman;
+	struct drm_sman sman;
 	unsigned int chipset;
 	int vram_initialized;
 	int agp_initialized;
@@ -61,9 +62,9 @@
 	unsigned long agp_offset;
 } drm_sis_private_t;
 
-extern int sis_idle(drm_device_t *dev);
-extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void sis_lastclose(drm_device_t *dev);
+extern int sis_idle(struct drm_device *dev);
+extern void sis_reclaim_buffers_locked(struct drm_device *dev, struct file *filp);
+extern void sis_lastclose(struct drm_device *dev);
 
 extern drm_ioctl_desc_t sis_ioctls[];
 extern int sis_max_ioctl;
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index d26f5db..441bbdb 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -94,7 +94,7 @@
 	mutex_lock(&dev->struct_mutex);
 #if defined(CONFIG_FB_SIS)
 	{
-		drm_sman_mm_t sman_mm;
+		struct drm_sman_mm sman_mm;
 		sman_mm.private = (void *)0xFFFFFFFF;
 		sman_mm.allocate = sis_sman_mm_allocate;
 		sman_mm.free = sis_sman_mm_free;
@@ -123,14 +123,14 @@
 	return 0;
 }
 
-static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
+static int sis_drm_alloc(struct drm_device *dev, struct drm_file * priv,
 			 unsigned long data, int pool)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
 	drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data;
 	drm_sis_mem_t mem;
 	int retval = 0;
-	drm_memblock_item_t *item;
+	struct drm_memblock_item *item;
 
 	DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem));
 
@@ -229,12 +229,12 @@
 	return sis_drm_alloc(dev, priv, data, AGP_TYPE);
 }
 
-static drm_local_map_t *sis_reg_init(drm_device_t *dev)
+static drm_local_map_t *sis_reg_init(struct drm_device *dev)
 {
-	drm_map_list_t *entry;
+	struct drm_map_list *entry;
 	drm_local_map_t *map;
 
-	list_for_each_entry(entry, &dev->maplist->head, head) {
+	list_for_each_entry(entry, &dev->maplist, head) {
 		map = entry->map;
 		if (!map)
 			continue;
@@ -245,7 +245,7 @@
 	return NULL;
 }
 
-int sis_idle(drm_device_t *dev)
+int sis_idle(struct drm_device *dev)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
 	uint32_t idle_reg;
@@ -314,10 +314,10 @@
 	mutex_unlock(&dev->struct_mutex);
 }
 
-void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void sis_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
-	drm_file_t *priv = filp->private_data;
+	struct drm_file *priv = filp->private_data;
 
 	mutex_lock(&dev->struct_mutex);
 	if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index 13a9c5c..7ff2b62 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -151,7 +151,7 @@
 	return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
 }
 
-int via_dma_cleanup(drm_device_t * dev)
+int via_dma_cleanup(struct drm_device * dev)
 {
 	if (dev->dev_private) {
 		drm_via_private_t *dev_priv =
@@ -169,7 +169,7 @@
 	return 0;
 }
 
-static int via_initialize(drm_device_t * dev,
+static int via_initialize(struct drm_device * dev,
 			  drm_via_private_t * dev_priv,
 			  drm_via_dma_init_t * init)
 {
@@ -262,7 +262,7 @@
 	return retcode;
 }
 
-static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
+static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * cmd)
 {
 	drm_via_private_t *dev_priv;
 	uint32_t *vb;
@@ -316,7 +316,7 @@
 	return 0;
 }
 
-int via_driver_dma_quiescent(drm_device_t * dev)
+int via_driver_dma_quiescent(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
 
@@ -356,7 +356,7 @@
 	return 0;
 }
 
-static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
+static int via_dispatch_pci_cmdbuffer(struct drm_device * dev,
 				      drm_via_cmdbuffer_t * cmd)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 2881a06..fdb8609 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -207,7 +207,7 @@
  */
 
 static void
-via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)
+via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -289,7 +289,7 @@
 }
 			
 static void
-via_abort_dmablit(drm_device_t *dev, int engine)
+via_abort_dmablit(struct drm_device *dev, int engine)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -297,7 +297,7 @@
 }
 
 static void
-via_dmablit_engine_off(drm_device_t *dev, int engine)
+via_dmablit_engine_off(struct drm_device *dev, int engine)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -314,7 +314,7 @@
  */
 		
 void
-via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)
+via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 	drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
@@ -433,7 +433,7 @@
  */
 
 static int
-via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine) 
+via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine) 
 {
 
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -466,7 +466,7 @@
 via_dmablit_timer(unsigned long data)
 {
 	drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
-	drm_device_t *dev = blitq->dev;
+	struct drm_device *dev = blitq->dev;
 	int engine = (int)
 		(blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
 		
@@ -502,7 +502,7 @@
 via_dmablit_workqueue(struct work_struct *work)
 {
 	drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
-	drm_device_t *dev = blitq->dev;
+	struct drm_device *dev = blitq->dev;
 	unsigned long irqsave;
 	drm_via_sg_info_t *cur_sg;
 	int cur_released;
@@ -545,7 +545,7 @@
 
 
 void
-via_init_dmablit(drm_device_t *dev)
+via_init_dmablit(struct drm_device *dev)
 {
 	int i,j;
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -582,7 +582,7 @@
 		
 
 static int
-via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
 {
 	int draw = xfer->to_fb;
 	int ret = 0;
@@ -730,7 +730,7 @@
 
 
 static int 
-via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)	 
+via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)	 
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 	drm_via_sg_info_t *vsg;
diff --git a/drivers/char/drm/via_dmablit.h b/drivers/char/drm/via_dmablit.h
index f4036cd..6f6a513 100644
--- a/drivers/char/drm/via_dmablit.h
+++ b/drivers/char/drm/via_dmablit.h
@@ -59,7 +59,7 @@
 } drm_via_sg_info_t;
 
 typedef struct _drm_via_blitq {
-	drm_device_t *dev;
+	struct drm_device *dev;
 	uint32_t cur_blit_handle;
 	uint32_t done_blit_handle;
 	unsigned serviced;
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index e4ee97d..8f53c76 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -40,7 +40,7 @@
 #define VIA_NR_XVMC_LOCKS               5
 #define VIA_MAX_CACHELINE_SIZE          64
 #define XVMCLOCKPTR(saPriv,lockNo)					\
-	((volatile drm_hw_lock_t *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
+	((volatile struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
 				      (VIA_MAX_CACHELINE_SIZE - 1)) &	\
 				     ~(VIA_MAX_CACHELINE_SIZE - 1)) +	\
 				    VIA_MAX_CACHELINE_SIZE*(lockNo)))
@@ -182,7 +182,7 @@
 typedef struct _drm_via_sarea {
 	unsigned int dirty;
 	unsigned int nbox;
-	drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS];
 	drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
 	int texAge;		/* last time texture was uploaded */
 	int ctxOwner;		/* last context to upload state */
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index b46ca8e..5767115 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -87,7 +87,7 @@
 	uint32_t irq_pending_mask;
 	int *irq_map;
 	unsigned int idle_fault;
-	drm_sman_t sman;
+	struct drm_sman sman;
 	int vram_initialized;
 	int agp_initialized;
 	unsigned long vram_offset;
@@ -123,31 +123,31 @@
 extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
 extern int via_dma_blit( DRM_IOCTL_ARGS );
 
-extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int via_driver_unload(drm_device_t *dev);
+extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int via_driver_unload(struct drm_device *dev);
 
-extern int via_init_context(drm_device_t * dev, int context);
-extern int via_final_context(drm_device_t * dev, int context);
+extern int via_init_context(struct drm_device * dev, int context);
+extern int via_final_context(struct drm_device * dev, int context);
 
-extern int via_do_cleanup_map(drm_device_t * dev);
-extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int via_do_cleanup_map(struct drm_device * dev);
+extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 
 extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
-extern void via_driver_irq_preinstall(drm_device_t * dev);
-extern void via_driver_irq_postinstall(drm_device_t * dev);
-extern void via_driver_irq_uninstall(drm_device_t * dev);
+extern void via_driver_irq_preinstall(struct drm_device * dev);
+extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern void via_driver_irq_uninstall(struct drm_device * dev);
 
-extern int via_dma_cleanup(drm_device_t * dev);
+extern int via_dma_cleanup(struct drm_device * dev);
 extern void via_init_command_verifier(void);
-extern int via_driver_dma_quiescent(drm_device_t * dev);
+extern int via_driver_dma_quiescent(struct drm_device * 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_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void via_lastclose(drm_device_t *dev);
+extern void via_reclaim_buffers_locked(struct drm_device *dev, struct file *filp);
+extern void via_lastclose(struct drm_device *dev);
 
-extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
-extern void via_init_dmablit(drm_device_t *dev);
+extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
+extern void via_init_dmablit(struct drm_device *dev);
 
 #endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 1ac5941..8dc99b5 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -98,7 +98,7 @@
 
 irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
 	int handled = 0;
@@ -163,7 +163,7 @@
 	}
 }
 
-int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	unsigned int cur_vblank;
@@ -191,7 +191,7 @@
 }
 
 static int
-via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequence,
 		    unsigned int *sequence)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -244,7 +244,7 @@
  * drm_dma.h hooks
  */
 
-void via_driver_irq_preinstall(drm_device_t * dev)
+void via_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
@@ -293,7 +293,7 @@
 	}
 }
 
-void via_driver_irq_postinstall(drm_device_t * dev)
+void via_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
@@ -312,7 +312,7 @@
 	}
 }
 
-void via_driver_irq_uninstall(drm_device_t * dev)
+void via_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index 4e3fc07..7fb9d2a 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -25,13 +25,13 @@
 #include "via_drm.h"
 #include "via_drv.h"
 
-static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
+static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
 
-	DRM_GETSAREA();
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
@@ -68,7 +68,7 @@
 	return 0;
 }
 
-int via_do_cleanup_map(drm_device_t * dev)
+int via_do_cleanup_map(struct drm_device * dev)
 {
 	via_dma_cleanup(dev);
 
@@ -95,7 +95,7 @@
 	return -EINVAL;
 }
 
-int via_driver_load(drm_device_t *dev, unsigned long chipset)
+int via_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	drm_via_private_t *dev_priv;
 	int ret = 0;
@@ -115,7 +115,7 @@
 	return ret;
 }
 
-int via_driver_unload(drm_device_t *dev)
+int via_driver_unload(struct drm_device *dev)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
 
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 2fcf057..85d56ac 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -127,7 +127,7 @@
 
 	drm_via_mem_t mem;
 	int retval = 0;
-	drm_memblock_item_t *item;
+	struct drm_memblock_item *item;
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	unsigned long tmpSize;
 
@@ -188,10 +188,10 @@
 }
 
 
-void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void via_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
-	drm_file_t *priv = filp->private_data;
+	struct drm_file *priv = filp->private_data;
 
 	mutex_lock(&dev->struct_mutex);
 	if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
index 2e7e080..832d483 100644
--- a/drivers/char/drm/via_verifier.c
+++ b/drivers/char/drm/via_verifier.c
@@ -252,10 +252,9 @@
 static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
 						    unsigned long offset,
 						    unsigned long size,
-						    drm_device_t * dev)
+						    struct drm_device * dev)
 {
-	struct list_head *list;
-	drm_map_list_t *r_list;
+	struct drm_map_list *r_list;
 	drm_local_map_t *map = seq->map_cache;
 
 	if (map && map->offset <= offset
@@ -263,8 +262,7 @@
 		return map;
 	}
 
-	list_for_each(list, &dev->maplist->head) {
-		r_list = (drm_map_list_t *) list;
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		map = r_list->map;
 		if (!map)
 			continue;
@@ -964,7 +962,7 @@
 
 int
 via_verify_command_stream(const uint32_t * buf, unsigned int size,
-			  drm_device_t * dev, int agp)
+			  struct drm_device * dev, int agp)
 {
 
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -1039,7 +1037,7 @@
 }
 
 int
-via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+via_parse_command_stream(struct drm_device * dev, const uint32_t * buf,
 			 unsigned int size)
 {
 
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index b77f59d..28b5029 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -47,7 +47,7 @@
 	drm_via_sequence_t unfinished;
 	int agp_texture;
 	int multitex;
-	drm_device_t *dev;
+	struct drm_device *dev;
 	drm_local_map_t *map_cache;
 	uint32_t vertex_count;
 	int agp;
@@ -55,8 +55,8 @@
 } 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_parse_command_stream(drm_device_t *dev, const uint32_t *buf,
+				     struct drm_device * dev, int agp);
+extern int via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
 				    unsigned int size);
 
 #endif
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index d1bfbaa..74cd511 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1121,8 +1121,6 @@
 	/*
 	 * Set up parity check flag
 	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
 	if (I_INPCK(info->tty))
 		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
@@ -1920,11 +1918,6 @@
 	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
 	unsigned long flags;
 
-	if (   (tty->termios->c_cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-		return;
-
 	change_speed(info);
 
 	spin_lock_irqsave(&info->lock, flags);
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 8ea0275..8facf3e 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -43,16 +43,6 @@
 
 #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
 #define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __FUNCTION__)
-#define NEW_WRITE_LOCKING 1
-#if NEW_WRITE_LOCKING
-#define DECL      /* Nothing */
-#define LOCKIT    mutex_lock(& port->port_write_mutex);
-#define RELEASEIT mutex_unlock(&port->port_write_mutex);
-#else
-#define DECL      unsigned long flags;
-#define LOCKIT    save_flags (flags);cli ()
-#define RELEASEIT restore_flags (flags)
-#endif
 
 #define RS_EVENT_WRITE_WAKEUP	1
 
@@ -62,7 +52,6 @@
 void gs_put_char(struct tty_struct * tty, unsigned char ch)
 {
 	struct gs_port *port;
-	DECL
 
 	func_enter (); 
 
@@ -75,11 +64,11 @@
 	if (! (port->flags & ASYNC_INITIALIZED)) return;
 
 	/* Take a lock on the serial tranmit buffer! */
-	LOCKIT;
+	mutex_lock(& port->port_write_mutex);
 
 	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
 		/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
-		RELEASEIT;
+		mutex_unlock(&port->port_write_mutex);
 		return;
 	}
 
@@ -87,13 +76,11 @@
 	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
 	port->xmit_cnt++;  /* Characters in buffer */
 
-	RELEASEIT;
+	mutex_unlock(&port->port_write_mutex);
 	func_exit ();
 }
 
 
-#ifdef NEW_WRITE_LOCKING
-
 /*
 > Problems to take into account are:
 >       -1- Interrupts that empty part of the buffer.
@@ -166,90 +153,6 @@
 	func_exit ();
 	return total;
 }
-#else
-/*
-> Problems to take into account are:
->       -1- Interrupts that empty part of the buffer.
->       -2- page faults on the access to userspace. 
->       -3- Other processes that are also trying to do a "write". 
-*/
-
-int gs_write(struct tty_struct * tty,
-                    const unsigned char *buf, int count)
-{
-	struct gs_port *port;
-	int c, total = 0;
-	int t;
-	unsigned long flags;
-
-	func_enter ();
-
-	/* The standard serial driver returns 0 in this case. 
-	   That sounds to me as "No error, I just didn't get to writing any
-	   bytes. Feel free to try again." 
-	   The "official" way to write n bytes from buf is:
-
-		 for (nwritten = 0;nwritten < n;nwritten += rv) {
-			 rv = write (fd, buf+nwritten, n-nwritten);
-			 if (rv < 0) break; // Error: bail out. //
-		 } 
-
-	   which will loop endlessly in this case. The manual page for write
-	   agrees with me. In practise almost everybody writes 
-	   "write (fd, buf,n);" but some people might have had to deal with 
-	   incomplete writes in the past and correctly implemented it by now... 
-	 */
-
-	if (!tty) return -EIO;
-
-	port = tty->driver_data;
-	if (!port || !port->xmit_buf)
-		return -EIO;
-
-	local_save_flags(flags);
-	while (1) {
-		cli();
-		c = count;
-
-		/* This is safe because we "OWN" the "head". Noone else can 
-		   change the "head": we own the port_write_mutex. */
-		/* Don't overrun the end of the buffer */
-		t = SERIAL_XMIT_SIZE - port->xmit_head;
-		if (t < c) c = t;
-
-		/* This is safe because the xmit_cnt can only decrease. This 
-		   would increase "t", so we might copy too little chars. */
-		/* Don't copy past the "head" of the buffer */
-		t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
-		if (t < c) c = t;
-
-		/* Can't copy more? break out! */
-		if (c <= 0) {
-			local_restore_flags(flags);
-			break;
-		}
-		memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = ((port->xmit_head + c) &
-		                   (SERIAL_XMIT_SIZE-1));
-		port->xmit_cnt += c;
-		local_restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (port->xmit_cnt && 
-	    !tty->stopped && 
-	    !tty->hw_stopped &&
-	    !(port->flags & GS_TX_INTEN)) {
-		port->flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-	return total;
-}
-
-#endif
 
 
 
@@ -737,23 +640,6 @@
 		gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
 	}
 
-	/* This is an optimization that is only allowed for dumb cards */
-	/* Smart cards require knowledge of iflags and oflags too: that 
-	   might change hardware cooking mode.... */
-	if (old_termios) {
-		if(   (tiosp->c_iflag == old_termios->c_iflag)
-		   && (tiosp->c_oflag == old_termios->c_oflag)
-		   && (tiosp->c_cflag == old_termios->c_cflag)
-		   && (tiosp->c_lflag == old_termios->c_lflag)
-		   && (tiosp->c_line  == old_termios->c_line)
-		   && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) {
-			gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n");
-			return /* 0 */;
-		}
-	} else 
-		gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: "
-		           "no optimization\n");
-
 	if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
 		if(tiosp->c_iflag != old_termios->c_iflag)  printk("c_iflag changed\n");
 		if(tiosp->c_oflag != old_termios->c_oflag)  printk("c_oflag changed\n");
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 9e1fc02..69f0a29 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -173,7 +173,6 @@
 static ssize_t gen_rtc_read(struct file *file, char __user *buf,
 			size_t count, loff_t *ppos)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	unsigned long data;
 	ssize_t retval;
 
@@ -183,18 +182,10 @@
 	if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
 		return -EAGAIN;
 
-	add_wait_queue(&gen_rtc_wait, &wait);
-	retval = -ERESTARTSYS;
-
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		data = xchg(&gen_rtc_irq_data, 0);
-		if (data)
-			break;
-		if (signal_pending(current))
-			goto out;
-		schedule();
-	}
+	retval = wait_event_interruptible(gen_rtc_wait,
+			(data = xchg(&gen_rtc_irq_data, 0)));
+	if (retval)
+		goto out;
 
 	/* first test allows optimizer to nuke this case for 32-bit machines */
 	if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
@@ -206,10 +197,7 @@
 		retval = put_user(data, (unsigned long __user *)buf) ?:
 			sizeof(unsigned long);
 	}
- out:
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&gen_rtc_wait, &wait);
-
+out:
 	return retval;
 }
 
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 322bc5f..83c1151 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -674,11 +674,12 @@
  * calling hvc_poll() who determines whether a console adapter support
  * interrupts.
  */
-int khvcd(void *unused)
+static int khvcd(void *unused)
 {
 	int poll_mask;
 	struct hvc_struct *hp;
 
+	set_freezable();
 	__set_current_state(TASK_RUNNING);
 	do {
 		poll_mask = 0;
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 4ae9811..753f460 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -296,12 +296,10 @@
 	     (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
 	    == BIOS_CNTL_LOCK_ENABLE_MASK) {
 		static __initdata /*const*/ char warning[] =
-			KERN_WARNING PFX "Firmware space is locked read-only. "
-			KERN_WARNING PFX "If you can't or\n don't want to "
-			KERN_WARNING PFX "disable this in firmware setup, and "
-			KERN_WARNING PFX "if\n you are certain that your "
-			KERN_WARNING PFX "system has a functional\n RNG, try"
-			KERN_WARNING PFX "using the 'no_fwh_detect' option.\n";
+			KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
+			KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
+			KERN_WARNING PFX "you are certain that your system has a functional\n"
+			KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
 
 		if (no_fwh_detect)
 			return -ENODEV;
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c
index dd761a1..61ef013 100644
--- a/drivers/char/ip2/i2ellis.c
+++ b/drivers/char/ip2/i2ellis.c
@@ -43,8 +43,6 @@
 static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
 static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
 
-static void ii2DelayTimer(unsigned int);
-static void ii2DelayWakeup(unsigned long id);
 static void ii2Nop(void);
 
 //***************
@@ -55,8 +53,6 @@
 
 static int iiDelayed;	// Set when the iiResetDelay function is
 							// called. Cleared when ANY board is reset.
-static struct timer_list * pDelayTimer;   // Used by iiDelayTimer
-static wait_queue_head_t pDelayWait;    // Used by iiDelayTimer
 static rwlock_t Dl_spinlock;
 
 //********
@@ -86,9 +82,6 @@
 static void
 iiEllisInit(void)
 {
-	pDelayTimer = kmalloc ( sizeof (struct timer_list), GFP_KERNEL );
-	init_timer(pDelayTimer);
-	init_waitqueue_head(&pDelayWait);
 	LOCK_INIT(&Dl_spinlock);
 }
 
@@ -106,7 +99,6 @@
 static void
 iiEllisCleanup(void)
 {
-	kfree(pDelayTimer);
 }
 
 //******************************************************************************
@@ -560,19 +552,6 @@
 	COMPLETE(pB, I2EE_GOOD);
 }
 
-//=======================================================
-// Delay Routines
-//
-// iiDelayIO
-// iiNop
-//=======================================================
-
-static void
-ii2DelayWakeup(unsigned long id)
-{
-	wake_up_interruptible ( &pDelayWait );
-}
-
 //******************************************************************************
 // Function:   ii2DelayTimer(mseconds)
 // Parameters: mseconds - number of milliseconds to delay
@@ -594,28 +573,7 @@
 static void
 ii2DelayTimer(unsigned int mseconds)
 {
-	wait_queue_t wait;
-
-	init_waitqueue_entry(&wait, current);
-
-	init_timer ( pDelayTimer );
-
-	add_wait_queue(&pDelayWait, &wait);
-
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	pDelayTimer->expires  = jiffies + ( mseconds + 9 ) / 10;
-	pDelayTimer->function = ii2DelayWakeup;
-	pDelayTimer->data     = 0;
-
-	add_timer ( pDelayTimer );
-
-	schedule();
-
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pDelayWait, &wait);
-
-	del_timer ( pDelayTimer );
+	msleep_interruptible(mseconds);
 }
 
 #if 0
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index b894f67..0baa8fa 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -2,11 +2,9 @@
 # IPMI device configuration
 #
 
-menu "IPMI"
-	depends on HAS_IOMEM
-
-config IPMI_HANDLER
+menuconfig IPMI_HANDLER
        tristate 'IPMI top-level message handler'
+       depends on HAS_IOMEM
        help
          This enables the central IPMI message handler, required for IPMI
 	 to work.
@@ -18,9 +16,10 @@
 
 	 If unsure, say N.
 
+if IPMI_HANDLER
+
 config IPMI_PANIC_EVENT
        bool 'Generate a panic event to all BMCs on a panic'
-       depends on IPMI_HANDLER
        help
          When a panic occurs, this will cause the IPMI message handler to
 	 generate an IPMI event describing the panic to each interface
@@ -40,14 +39,12 @@
 
 config IPMI_DEVICE_INTERFACE
        tristate 'Device interface for IPMI'
-       depends on IPMI_HANDLER
        help
          This provides an IOCTL interface to the IPMI message handler so
 	 userland processes may use IPMI.  It supports poll() and select().
 
 config IPMI_SI
        tristate 'IPMI System Interface handler'
-       depends on IPMI_HANDLER
        help
          Provides a driver for System Interfaces (KCS, SMIC, BT).
 	 Currently, only KCS and SMIC are supported.  If
@@ -55,15 +52,13 @@
 
 config IPMI_WATCHDOG
        tristate 'IPMI Watchdog Timer'
-       depends on IPMI_HANDLER
        help
          This enables the IPMI watchdog timer.
 
 config IPMI_POWEROFF
        tristate 'IPMI Poweroff'
-       depends on IPMI_HANDLER
        help
          This enables a function to power off the system with IPMI if
 	 the IPMI management controller is capable of this.
 
-endmenu
+endif # IPMI_HANDLER
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e02893b..b86186d 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -679,7 +679,7 @@
 {
 	int rv;
 
-	printk ("Copyright (C) 2004 MontaVista Software -"
+	printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -"
 		" IPMI Powerdown via sys_reboot.\n");
 
 	if (poweroff_powercycle)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 78e1b96..4edfdda 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2857,7 +2857,7 @@
 
 	mutex_unlock(&smi_infos_lock);
 
-	printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
+	printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
 
 	return 0;
 
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 761f777..77a7a4a 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -171,9 +171,6 @@
 static int prev_card = 3;	/*	start servicing isi_card[0]	*/
 static struct tty_driver *isicom_normal;
 
-static DECLARE_COMPLETION(isi_timerdone);
-static char re_schedule = 1;
-
 static void isicom_tx(unsigned long _data);
 static void isicom_start(struct tty_struct *tty);
 
@@ -187,7 +184,7 @@
 
 struct	isi_board {
 	unsigned long		base;
-	unsigned char		irq;
+	int			irq;
 	unsigned char		port_count;
 	unsigned short		status;
 	unsigned short		port_status; /* each bit for each port */
@@ -227,7 +224,7 @@
  *	it wants to talk.
  */
 
-static inline int WaitTillCardIsFree(u16 base)
+static inline int WaitTillCardIsFree(unsigned long base)
 {
 	unsigned int count = 0;
 	unsigned int a = in_atomic(); /* do we run under spinlock? */
@@ -243,17 +240,18 @@
 
 static int lock_card(struct isi_board *card)
 {
-	char		retries;
 	unsigned long base = card->base;
+	unsigned int retries, a;
 
-	for (retries = 0; retries < 100; retries++) {
+	for (retries = 0; retries < 10; retries++) {
 		spin_lock_irqsave(&card->card_lock, card->flags);
-		if (inw(base + 0xe) & 0x1) {
-			return 1;
-		} else {
-			spin_unlock_irqrestore(&card->card_lock, card->flags);
-			udelay(1000);   /* 1ms */
+		for (a = 0; a < 10; a++) {
+			if (inw(base + 0xe) & 0x1)
+				return 1;
+			udelay(10);
 		}
+		spin_unlock_irqrestore(&card->card_lock, card->flags);
+		msleep(10);
 	}
 	printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
 		card->base);
@@ -261,23 +259,6 @@
 	return 0;	/* Failed to acquire the card! */
 }
 
-static int lock_card_at_interrupt(struct isi_board *card)
-{
-	unsigned char		retries;
-	unsigned long base = card->base;
-
-	for (retries = 0; retries < 200; retries++) {
-		spin_lock_irqsave(&card->card_lock, card->flags);
-
-		if (inw(base + 0xe) & 0x1)
-			return 1;
-		else
-			spin_unlock_irqrestore(&card->card_lock, card->flags);
-	}
-	/* Failing in interrupt is an acceptable event */
-	return 0;	/* Failed to acquire the card! */
-}
-
 static void unlock_card(struct isi_board *card)
 {
 	spin_unlock_irqrestore(&card->card_lock, card->flags);
@@ -415,7 +396,9 @@
 
 static void isicom_tx(unsigned long _data)
 {
-	short count = (BOARD_COUNT-1), card, base;
+	unsigned long flags, base;
+	unsigned int retries;
+	short count = (BOARD_COUNT-1), card;
 	short txcount, wrd, residue, word_count, cnt;
 	struct isi_port *port;
 	struct tty_struct *tty;
@@ -435,32 +418,34 @@
 	count = isi_card[card].port_count;
 	port = isi_card[card].ports;
 	base = isi_card[card].base;
+
+	spin_lock_irqsave(&isi_card[card].card_lock, flags);
+	for (retries = 0; retries < 100; retries++) {
+		if (inw(base + 0xe) & 0x1)
+			break;
+		udelay(2);
+	}
+	if (retries >= 100)
+		goto unlock;
+
 	for (;count > 0;count--, port++) {
-		if (!lock_card_at_interrupt(&isi_card[card]))
-			continue;
 		/* port not active or tx disabled to force flow control */
 		if (!(port->flags & ASYNC_INITIALIZED) ||
 				!(port->status & ISI_TXOK))
-			unlock_card(&isi_card[card]);
 			continue;
 
 		tty = port->tty;
 
-
-		if (tty == NULL) {
-			unlock_card(&isi_card[card]);
+		if (tty == NULL)
 			continue;
-		}
 
 		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
-		if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
-			unlock_card(&isi_card[card]);
+		if (txcount <= 0 || tty->stopped || tty->hw_stopped)
 			continue;
-		}
-		if (!(inw(base + 0x02) & (1 << port->channel))) {
-			unlock_card(&isi_card[card]);
+
+		if (!(inw(base + 0x02) & (1 << port->channel)))
 			continue;
-		}
+
 		pr_dbg("txing %d bytes, port%d.\n", txcount,
 			port->channel + 1);
 		outw((port->channel << isi_card[card].shift_count) | txcount,
@@ -508,16 +493,12 @@
 			port->status &= ~ISI_TXOK;
 		if (port->xmit_cnt <= WAKEUP_CHARS)
 			tty_wakeup(tty);
-		unlock_card(&isi_card[card]);
 	}
 
+unlock:
+	spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
 	/*	schedule another tx for hopefully in about 10ms	*/
 sched_again:
-	if (!re_schedule) {
-		complete(&isi_timerdone);
- 		return;
-	}
-
 	mod_timer(&tx, jiffies + msecs_to_jiffies(10));
 }
 
@@ -1749,17 +1730,13 @@
 static int __devinit isicom_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
-	unsigned int ioaddr, signature, index;
+	unsigned int signature, index;
 	int retval = -EPERM;
-	u8 pciirq;
 	struct isi_board *board = NULL;
 
 	if (card_count >= BOARD_COUNT)
 		goto err;
 
-	ioaddr = pci_resource_start(pdev, 3);
-	/* i.e at offset 0x1c in the PCI configuration register space. */
-	pciirq = pdev->irq;
 	dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
 
 	/* allot the first empty slot in the array */
@@ -1770,8 +1747,8 @@
 		}
 
 	board->index = index;
-	board->base = ioaddr;
-	board->irq = pciirq;
+	board->base = pci_resource_start(pdev, 3);
+	board->irq = pdev->irq;
 	card_count++;
 
 	pci_set_drvdata(pdev, board);
@@ -1901,9 +1878,7 @@
 
 static void __exit isicom_exit(void)
 {
-	re_schedule = 0;
-
-	wait_for_completion_timeout(&isi_timerdone, HZ);
+	del_timer_sync(&tx);
 
 	pci_unregister_driver(&isicom_driver);
 	tty_unregister_driver(isicom_normal);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 7b279d1..3c66f40 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1753,9 +1753,6 @@
 		return;
 
 	tiosp = tty->termios;
-	if ((tiosp->c_cflag == old->c_cflag) &&
-	    (tiosp->c_iflag == old->c_iflag))
-		return;
 
 	stli_mkasyport(portp, &aport, tiosp);
 	stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
@@ -2166,14 +2163,10 @@
 	cdkhdr_t __iomem *hdrp;
 	cdkctrl_t __iomem *cp;
 	unsigned char __iomem *bits;
-	unsigned long flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
 
 	if (test_bit(ST_CMDING, &portp->state)) {
 		printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",
 				(int) cmd);
-		spin_unlock_irqrestore(&brd_lock, flags);
 		return;
 	}
 
@@ -2194,7 +2187,6 @@
 	writeb(readb(bits) | portp->portbit, bits);
 	set_bit(ST_CMDING, &portp->state);
 	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
@@ -3218,13 +3210,13 @@
 		goto err;
 	}
 
+	brdp->iosize = ECP_IOSIZE;
+
 	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
 		retval = -EIO;
 		goto err;
 	}
 
-	brdp->iosize = ECP_IOSIZE;
-
 /*
  *	Based on the specific board type setup the common vars to access
  *	and enable shared memory. Set all board specific information now
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 90965b4..2ce0af1 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -24,6 +24,7 @@
  * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
  */
 
+#include <linux/consolemap.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
@@ -308,10 +309,9 @@
  * Many other routines do put_queue, but I think either
  * they produce ASCII, or they produce some user-assigned
  * string, and in both cases we might assume that it is
- * in utf-8 already. UTF-8 is defined for words of up to 31 bits,
- * but we need only 16 bits here
+ * in utf-8 already.
  */
-static void to_utf8(struct vc_data *vc, ushort c)
+static void to_utf8(struct vc_data *vc, uint c)
 {
 	if (c < 0x80)
 		/*  0******* */
@@ -320,11 +320,21 @@
 		/* 110***** 10****** */
 		put_queue(vc, 0xc0 | (c >> 6));
 		put_queue(vc, 0x80 | (c & 0x3f));
-	} else {
+    	} else if (c < 0x10000) {
+	       	if (c >= 0xD800 && c < 0xE000)
+			return;
+		if (c == 0xFFFF)
+			return;
 		/* 1110**** 10****** 10****** */
 		put_queue(vc, 0xe0 | (c >> 12));
 		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
 		put_queue(vc, 0x80 | (c & 0x3f));
+    	} else if (c < 0x110000) {
+		/* 11110*** 10****** 10****** 10****** */
+		put_queue(vc, 0xf0 | (c >> 18));
+		put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
+		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
+		put_queue(vc, 0x80 | (c & 0x3f));
 	}
 }
 
@@ -393,7 +403,7 @@
 		return d;
 
 	if (kbd->kbdmode == VC_UNICODE)
-		to_utf8(vc, d);
+		to_utf8(vc, conv_8bit_to_uni(d));
 	else if (d < 0x100)
 		put_queue(vc, d);
 
@@ -407,7 +417,7 @@
 {
 	if (diacr) {
 		if (kbd->kbdmode == VC_UNICODE)
-			to_utf8(vc, diacr);
+			to_utf8(vc, conv_8bit_to_uni(diacr));
 		else if (diacr < 0x100)
 			put_queue(vc, diacr);
 		diacr = 0;
@@ -617,7 +627,7 @@
 		return;
 	}
 	if (kbd->kbdmode == VC_UNICODE)
-		to_utf8(vc, value);
+		to_utf8(vc, conv_8bit_to_uni(value));
 	else if (value < 0x100)
 		put_queue(vc, value);
 }
@@ -775,7 +785,7 @@
 	/* kludge */
 	if (up_flag && shift_state != old_state && npadch != -1) {
 		if (kbd->kbdmode == VC_UNICODE)
-			to_utf8(vc, npadch & 0xffff);
+			to_utf8(vc, npadch);
 		else
 			put_queue(vc, npadch & 0xff);
 		npadch = -1;
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 4e6fb96..71c8cd7 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -67,25 +67,13 @@
 #ifdef CONFIG_PROC_FS
 static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct miscdevice *p;
-	loff_t off = 0;
-
 	mutex_lock(&misc_mtx);
-	list_for_each_entry(p, &misc_list, list) {
-		if (*pos == off++) 
-			return p;
-	}
-	return NULL;
+	return seq_list_start(&misc_list, *pos);
 }
 
 static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct list_head *n = ((struct miscdevice *)v)->list.next;
-
-	++*pos;
-
-	return (n != &misc_list) ? list_entry(n, struct miscdevice, list)
-		 : NULL;
+	return seq_list_next(v, &misc_list, pos);
 }
 
 static void misc_seq_stop(struct seq_file *seq, void *v)
@@ -95,7 +83,7 @@
 
 static int misc_seq_show(struct seq_file *seq, void *v)
 {
-	const struct miscdevice *p = v;
+	const struct miscdevice *p = list_entry(v, struct miscdevice, list);
 
 	seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : "");
 	return 0;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index e0d35c2..ed76f0a 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -1405,7 +1405,6 @@
 static struct mon_str moxaLog;
 static int moxaFuncTout = HZ / 2;
 
-static void moxadelay(int);
 static void moxafunc(void __iomem *, int, ushort);
 static void wait_finish(void __iomem *);
 static void low_water_check(void __iomem *);
@@ -2404,10 +2403,10 @@
 	ofsAddr = moxa_ports[port].tableAddr;
 	if (ms100) {
 		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
-		moxadelay(ms100 * (HZ / 10));
+		msleep(ms100 * 10);
 	} else {
 		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
-		moxadelay(HZ / 4);	/* 250 ms */
+		msleep(250);
 	}
 	moxafunc(ofsAddr, FC_StopBreak, Magic_code);
 }
@@ -2476,18 +2475,6 @@
 /*****************************************************************************
  *	Static local functions: 					     *
  *****************************************************************************/
-/*
- * moxadelay - delays a specified number ticks
- */
-static void moxadelay(int tick)
-{
-	unsigned long st, et;
-
-	st = jiffies;
-	et = st + tick;
-	while (time_before(jiffies, et));
-}
-
 static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
 {
 
@@ -2535,7 +2522,7 @@
 		return -EFAULT;
 	baseAddr = moxa_boards[cardno].basemem;
 	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
-	moxadelay(1);		/* delay 10 ms */
+	msleep(10);
 	for (i = 0; i < 4096; i++)
 		writeb(0, baseAddr + i);	/* clear fix page */
 	for (i = 0; i < len; i++)
@@ -2713,7 +2700,7 @@
 			for (i = 0; i < 100; i++) {
 				if (readw(baseAddr + C218_key) == keycode)
 					break;
-				moxadelay(1);	/* delay 10 ms */
+				msleep(10);
 			}
 			if (readw(baseAddr + C218_key) != keycode) {
 				return (-1);
@@ -2725,7 +2712,7 @@
 		for (i = 0; i < 100; i++) {
 			if (readw(baseAddr + C218_key) == keycode)
 				break;
-			moxadelay(1);	/* delay 10 ms */
+			msleep(10);
 		}
 		retry++;
 	} while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
@@ -2736,7 +2723,7 @@
 	for (i = 0; i < 100; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);	/* delay 10 ms */
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code) {
 		return (-1);
@@ -2746,7 +2733,7 @@
 	for (i = 0; i < 100; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);	/* delay 10 ms */
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code) {
 		return (-1);
@@ -2788,7 +2775,7 @@
 			for (i = 0; i < 10; i++) {
 				if (readw(baseAddr + C320_key) == C320_KeyCode)
 					break;
-				moxadelay(1);
+				msleep(10);
 			}
 			if (readw(baseAddr + C320_key) != C320_KeyCode)
 				return (-1);
@@ -2799,7 +2786,7 @@
 		for (i = 0; i < 10; i++) {
 			if (readw(baseAddr + C320_key) == C320_KeyCode)
 				break;
-			moxadelay(1);
+			msleep(10);
 		}
 		retry++;
 	} while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
@@ -2809,7 +2796,7 @@
 	for (i = 0; i < 600; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code)
 		return (-100);
@@ -2828,7 +2815,7 @@
 	for (i = 0; i < 500; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code)
 		return (-102);
@@ -2842,7 +2829,7 @@
 	for (i = 0; i < 600; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code)
 		return (-102);
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 7ac3061..c716ef0 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -265,7 +265,7 @@
 	vdata->refcnt = ATOMIC_INIT(1);
 	vma->vm_private_data = vdata;
 
-	vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
+	vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP);
 	if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	vma->vm_ops = &mspec_vm_ops;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 5953a45..2aee3fe 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -90,8 +90,6 @@
 #define UART_MCR_AFE		0x20
 #define UART_LSR_SPECIAL	0x1E
 
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
-					  IXON|IXOFF))
 
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED)
 
@@ -1729,16 +1727,12 @@
 	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
-	if ((tty->termios->c_cflag != old_termios->c_cflag) ||
-			(RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+	mxser_change_speed(info, old_termios);
 
-		mxser_change_speed(info, old_termios);
-
-		if ((old_termios->c_cflag & CRTSCTS) &&
-				!(tty->termios->c_cflag & CRTSCTS)) {
-			tty->hw_stopped = 0;
-			mxser_start(tty);
-		}
+	if ((old_termios->c_cflag & CRTSCTS) &&
+			!(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		mxser_start(tty);
 	}
 
 /* Handle sw stopped */
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 6cde448..6a56393 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -72,8 +72,6 @@
 #define UART_MCR_AFE		0x20
 #define UART_LSR_SPECIAL	0x1E
 
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
-					  IXON|IXOFF))
 
 #define C168_ASIC_ID    1
 #define C104_ASIC_ID    2
@@ -1560,7 +1558,7 @@
 			return -EFAULT;
 		return 0;
 	case MOXA_ASPP_MON_EXT: {
-		int status, p, shiftbit;
+		int p, shiftbit;
 		unsigned long opmode;
 		unsigned cflag, iflag;
 
@@ -1990,18 +1988,14 @@
 	struct mxser_port *info = tty->driver_data;
 	unsigned long flags;
 
-	if ((tty->termios->c_cflag != old_termios->c_cflag) ||
-			(RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+	spin_lock_irqsave(&info->slock, flags);
+	mxser_change_speed(info, old_termios);
+	spin_unlock_irqrestore(&info->slock, flags);
 
-		spin_lock_irqsave(&info->slock, flags);
-		mxser_change_speed(info, old_termios);
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		if ((old_termios->c_cflag & CRTSCTS) &&
-				!(tty->termios->c_cflag & CRTSCTS)) {
-			tty->hw_stopped = 0;
-			mxser_start(tty);
-		}
+	if ((old_termios->c_cflag & CRTSCTS) &&
+			!(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		mxser_start(tty);
 	}
 
 	/* Handle sw stopped */
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 337a87f..e8332f3 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -400,7 +400,12 @@
 		/* Send the next block of data to device */
 		tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 		actual = tty->driver->write(tty, tbuf->buf, tbuf->count);
-		    
+
+		/* rollback was possible and has been done */
+		if (actual == -ERESTARTSYS) {
+			n_hdlc->tbuf = tbuf;
+			break;
+		}
 		/* if transmit error, throw frame away by */
 		/* pretending it was accepted by driver */
 		if (actual < 0)
@@ -780,13 +785,14 @@
 		poll_wait(filp, &tty->write_wait, wait);
 
 		/* set bits for operations that won't block */
-		if(n_hdlc->rx_buf_list.head)
+		if (n_hdlc->rx_buf_list.head)
 			mask |= POLLIN | POLLRDNORM;	/* readable */
 		if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 			mask |= POLLHUP;
-		if(tty_hung_up_p(filp))
+		if (tty_hung_up_p(filp))
 			mask |= POLLHUP;
-		if(n_hdlc->tx_free_buf_list.head)
+		if (!tty_is_writelocked(tty) &&
+				n_hdlc->tx_free_buf_list.head)
 			mask |= POLLOUT | POLLWRNORM;	/* writable */
 	}
 	return mask;
@@ -861,7 +867,7 @@
 	spin_lock_irqsave(&list->spinlock,flags);
 	
 	buf->link=NULL;
-	if(list->tail)
+	if (list->tail)
 		list->tail->link = buf;
 	else
 		list->head = buf;
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 14557a4..6b918b8 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1071,8 +1071,6 @@
 	struct r3964_client_info *pClient;
 	struct r3964_message *pMsg;
 	struct r3964_client_message theMsg;
-	DECLARE_WAITQUEUE(wait, current);
-
 	int count;
 
 	TRACE_L("read()");
@@ -1086,16 +1084,8 @@
 				return -EAGAIN;
 			}
 			/* block until there is a message: */
-			add_wait_queue(&pInfo->read_wait, &wait);
-repeat:
-			__set_current_state(TASK_INTERRUPTIBLE);
-			pMsg = remove_msg(pInfo, pClient);
-			if (!pMsg && !signal_pending(current)) {
-				schedule();
-				goto repeat;
-			}
-			__set_current_state(TASK_RUNNING);
-			remove_wait_queue(&pInfo->read_wait, &wait);
+			wait_event_interruptible(pInfo->read_wait,
+					(pMsg = remove_msg(pInfo, pClient)));
 		}
 
 		/* If we still haven't got a message, we must have been signalled */
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 154f422..0380569 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -45,6 +45,8 @@
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/bitops.h>
+#include <linux/audit.h>
+#include <linux/file.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -78,6 +80,13 @@
 		free_page((unsigned long) buf);
 }
 
+static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
+			       unsigned char __user *ptr)
+{
+	tty_audit_add_data(tty, &x, 1);
+	return put_user(x, ptr);
+}
+
 /**
  *	n_tty_set__room	-	receive space
  *	@tty: terminal
@@ -1153,6 +1162,7 @@
 	if (n) {
 		retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
 		n -= retval;
+		tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
 		spin_lock_irqsave(&tty->read_lock, flags);
 		tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
 		tty->read_cnt -= n;
@@ -1279,7 +1289,7 @@
 				break;
 			cs = tty->link->ctrl_status;
 			tty->link->ctrl_status = 0;
-			if (put_user(cs, b++)) {
+			if (tty_put_user(tty, cs, b++)) {
 				retval = -EFAULT;
 				b--;
 				break;
@@ -1321,7 +1331,7 @@
 
 		/* Deal with packet mode. */
 		if (tty->packet && b == buf) {
-			if (put_user(TIOCPKT_DATA, b++)) {
+			if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
 				retval = -EFAULT;
 				b--;
 				break;
@@ -1352,15 +1362,17 @@
 				spin_unlock_irqrestore(&tty->read_lock, flags);
 
 				if (!eol || (c != __DISABLED_CHAR)) {
-					if (put_user(c, b++)) {
+					if (tty_put_user(tty, c, b++)) {
 						retval = -EFAULT;
 						b--;
 						break;
 					}
 					nr--;
 				}
-				if (eol)
+				if (eol) {
+					tty_audit_push(tty);
 					break;
+				}
 			}
 			if (retval)
 				break;
@@ -1538,7 +1550,8 @@
 		else
 			tty->minimum_to_wake = 1;
 	}
-	if (tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
+	if (!tty_is_writelocked(tty) &&
+			tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
 			tty->driver->write_room(tty) > 0)
 		mask |= POLLOUT | POLLWRNORM;
 	return mask;
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 204deaa..98dec38 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -42,19 +42,12 @@
 
 #define PC		1
 #define ATARI		2
-#define COBALT		3
 
 /* select machine configuration */
 #if defined(CONFIG_ATARI)
 #  define MACH ATARI
 #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)  /* and others?? */
-#define MACH PC
-#  if defined(CONFIG_COBALT)
-#    include <linux/cobalt-nvram.h>
-#    define MACH COBALT
-#  else
-#    define MACH PC
-#  endif
+#  define MACH PC
 #else
 #  error Cannot build nvram driver for this machine configuration.
 #endif
@@ -76,18 +69,6 @@
 
 #endif
 
-#if MACH == COBALT
-
-#define CHECK_DRIVER_INIT()     1
-
-#define NVRAM_BYTES		(128-NVRAM_FIRST_BYTE)
-
-#define mach_check_checksum	cobalt_check_checksum
-#define mach_set_checksum	cobalt_set_checksum
-#define mach_proc_infos		cobalt_proc_infos
-
-#endif
-
 #if MACH == ATARI
 
 /* Special parameters for RTC in Atari machines */
@@ -604,177 +585,6 @@
 
 #endif /* MACH == PC */
 
-#if MACH == COBALT
-
-/* the cobalt CMOS has a wider range of its checksum */
-static int cobalt_check_checksum(void)
-{
-	int i;
-	unsigned short sum = 0;
-	unsigned short expect;
-
-	for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
-		if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
-			continue;
-
-		sum += __nvram_read_byte(i);
-	}
-	expect = __nvram_read_byte(COBT_CMOS_CHECKSUM) << 8 |
-	    __nvram_read_byte(COBT_CMOS_CHECKSUM+1);
-	return ((sum & 0xffff) == expect);
-}
-
-static void cobalt_set_checksum(void)
-{
-	int i;
-	unsigned short sum = 0;
-
-	for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
-		if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
-			continue;
-
-		sum += __nvram_read_byte(i);
-	}
-
-	__nvram_write_byte(sum >> 8, COBT_CMOS_CHECKSUM);
-	__nvram_write_byte(sum & 0xff, COBT_CMOS_CHECKSUM+1);
-}
-
-#ifdef CONFIG_PROC_FS
-
-static int cobalt_proc_infos(unsigned char *nvram, char *buffer, int *len,
-	off_t *begin, off_t offset, int size)
-{
-	int i;
-	unsigned int checksum;
-	unsigned int flags;
-	char sernum[14];
-	char *key = "cNoEbTaWlOtR!";
-	unsigned char bto_csum;
-
-	spin_lock_irq(&rtc_lock);
-	checksum = __nvram_check_checksum();
-	spin_unlock_irq(&rtc_lock);
-
-	PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not ");
-
-	flags = nvram[COBT_CMOS_FLAG_BYTE_0] << 8 
-	    | nvram[COBT_CMOS_FLAG_BYTE_1];
-
-	PRINT_PROC("Console: %s\n",
-		flags & COBT_CMOS_CONSOLE_FLAG ?  "on": "off");
-
-	PRINT_PROC("Firmware Debug Messages: %s\n",
-		flags & COBT_CMOS_DEBUG_FLAG ? "on": "off");
-
-	PRINT_PROC("Auto Prompt: %s\n",
-		flags & COBT_CMOS_AUTO_PROMPT_FLAG ? "on": "off");
-
-	PRINT_PROC("Shutdown Status: %s\n",
-		flags & COBT_CMOS_CLEAN_BOOT_FLAG ? "clean": "dirty");
-
-	PRINT_PROC("Hardware Probe: %s\n",
-		flags & COBT_CMOS_HW_NOPROBE_FLAG ? "partial": "full");
-
-	PRINT_PROC("System Fault: %sdetected\n",
-		flags & COBT_CMOS_SYSFAULT_FLAG ? "": "not ");
-
-	PRINT_PROC("Panic on OOPS: %s\n",
-		flags & COBT_CMOS_OOPSPANIC_FLAG ? "yes": "no");
-
-	PRINT_PROC("Delayed Cache Initialization: %s\n",
-		flags & COBT_CMOS_DELAY_CACHE_FLAG ? "yes": "no");
-
-	PRINT_PROC("Show Logo at Boot: %s\n",
-		flags & COBT_CMOS_NOLOGO_FLAG ? "no": "yes");
-
-	PRINT_PROC("Boot Method: ");
-	switch (nvram[COBT_CMOS_BOOT_METHOD]) {
-	case COBT_CMOS_BOOT_METHOD_DISK:
-		PRINT_PROC("disk\n");
-		break;
-
-	case COBT_CMOS_BOOT_METHOD_ROM:
-		PRINT_PROC("rom\n");
-		break;
-
-	case COBT_CMOS_BOOT_METHOD_NET:
-		PRINT_PROC("net\n");
-		break;
-
-	default:
-		PRINT_PROC("unknown\n");
-		break;
-	}
-
-	PRINT_PROC("Primary Boot Device: %d:%d\n",
-		nvram[COBT_CMOS_BOOT_DEV0_MAJ],
-		nvram[COBT_CMOS_BOOT_DEV0_MIN] );
-	PRINT_PROC("Secondary Boot Device: %d:%d\n",
-		nvram[COBT_CMOS_BOOT_DEV1_MAJ],
-		nvram[COBT_CMOS_BOOT_DEV1_MIN] );
-	PRINT_PROC("Tertiary Boot Device: %d:%d\n",
-		nvram[COBT_CMOS_BOOT_DEV2_MAJ],
-		nvram[COBT_CMOS_BOOT_DEV2_MIN] );
-
-	PRINT_PROC("Uptime: %d\n",
-		nvram[COBT_CMOS_UPTIME_0] << 24 |
-		nvram[COBT_CMOS_UPTIME_1] << 16 |
-		nvram[COBT_CMOS_UPTIME_2] << 8  |
-		nvram[COBT_CMOS_UPTIME_3]);
-
-	PRINT_PROC("Boot Count: %d\n",
-		nvram[COBT_CMOS_BOOTCOUNT_0] << 24 |
-		nvram[COBT_CMOS_BOOTCOUNT_1] << 16 |
-		nvram[COBT_CMOS_BOOTCOUNT_2] << 8  |
-		nvram[COBT_CMOS_BOOTCOUNT_3]);
-
-	/* 13 bytes of serial num */
-	for (i=0 ; i<13 ; i++) {
-		sernum[i] = nvram[COBT_CMOS_SYS_SERNUM_0 + i];
-	}
-	sernum[13] = '\0';
-
-	checksum = 0;
-	for (i=0 ; i<13 ; i++) {
-		checksum += sernum[i] ^ key[i];
-	}
-	checksum = ((checksum & 0x7f) ^ (0xd6)) & 0xff;
-
-	PRINT_PROC("Serial Number: %s", sernum);
-	if (checksum != nvram[COBT_CMOS_SYS_SERNUM_CSUM]) {
-		PRINT_PROC(" (invalid checksum)");
-	}
-	PRINT_PROC("\n");
-
-	PRINT_PROC("Rom Revison: %d.%d.%d\n", nvram[COBT_CMOS_ROM_REV_MAJ],
-		nvram[COBT_CMOS_ROM_REV_MIN], nvram[COBT_CMOS_ROM_REV_REV]);
-
-	PRINT_PROC("BTO Server: %d.%d.%d.%d", nvram[COBT_CMOS_BTO_IP_0],
-		nvram[COBT_CMOS_BTO_IP_1], nvram[COBT_CMOS_BTO_IP_2],
-		nvram[COBT_CMOS_BTO_IP_3]);
-	bto_csum = nvram[COBT_CMOS_BTO_IP_0] + nvram[COBT_CMOS_BTO_IP_1]
-		+ nvram[COBT_CMOS_BTO_IP_2] + nvram[COBT_CMOS_BTO_IP_3];
-	if (bto_csum != nvram[COBT_CMOS_BTO_IP_CSUM]) {
-		PRINT_PROC(" (invalid checksum)");
-	}
-	PRINT_PROC("\n");
-
-	if (flags & COBT_CMOS_VERSION_FLAG
-	 && nvram[COBT_CMOS_VERSION] >= COBT_CMOS_VER_BTOCODE) {
-		PRINT_PROC("BTO Code: 0x%x\n",
-			nvram[COBT_CMOS_BTO_CODE_0] << 24 |
-			nvram[COBT_CMOS_BTO_CODE_1] << 16 |
-			nvram[COBT_CMOS_BTO_CODE_2] << 8 |
-			nvram[COBT_CMOS_BTO_CODE_3]);
-	}
-
-	return 1;
-}
-#endif /* CONFIG_PROC_FS */
-
-#endif /* MACH == COBALT */
-
 #if MACH == ATARI
 
 static int
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 3494e3f..b37e626 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -213,14 +213,6 @@
 		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
 }
 	
-/* Must be called with enabled interrupts */
-static inline void rc_long_delay(unsigned long delay)
-{
-	unsigned long i;
-	
-	for (i = jiffies + delay; time_after(i,jiffies); ) ;
-}
-
 /* Reset and setup CD180 chip */
 static void __init rc_init_CD180(struct riscom_board const * bp)
 {
@@ -231,7 +223,7 @@
 	rc_wait_CCR(bp);			   /* Wait for CCR ready        */
 	rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip          */
 	sti();
-	rc_long_delay(HZ/20);                      /* Delay 0.05 sec            */
+	msleep(50);				   /* Delay 0.05 sec            */
 	cli();
 	rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip      */
 	rc_out(bp, CD180_GICR, 0);                 /* Clear all bits            */
@@ -280,7 +272,7 @@
 		rc_wait_CCR(bp);
 		rc_out(bp, CD180_CCR, CCR_TXEN);        /* Enable transmitter     */
 		rc_out(bp, CD180_IER, IER_TXRDY);       /* Enable tx empty intr   */
-		rc_long_delay(HZ/20);	       		
+		msleep(50);
 		irqs = probe_irq_off(irqs);
 		val1 = rc_in(bp, RC_BSR);		/* Get Board Status reg   */
 		val2 = rc_in(bp, RC_ACK_TINT);          /* ACK interrupt          */
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index a3fd7e7..0270080 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1702,7 +1702,8 @@
 	if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
 		return 0;
 
-	mutex_lock_interruptible(&info->write_mtx);
+	if (mutex_lock_interruptible(&info->write_mtx))
+		return -ERESTARTSYS;
 
 #ifdef ROCKET_DEBUG_WRITE
 	printk(KERN_INFO "rp_write %d chars...", count);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 20380a2..22cf7aa 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1159,7 +1159,8 @@
 
 	spin_unlock_irq(&rtc_lock);
 
-	printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
+	if (printk_ratelimit())
+		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
 
 	/* Now we have new data */
 	wake_up_interruptible(&rtc_wait);
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index a69f094..d63f5cc 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -20,6 +20,7 @@
 
 #include <asm/uaccess.h>
 
+#include <linux/kbd_kern.h>
 #include <linux/vt_kern.h>
 #include <linux/consolemap.h>
 #include <linux/selection.h>
@@ -34,6 +35,7 @@
 /* Variables for selection control. */
 /* Use a dynamic buffer, instead of static (Dec 1994) */
 struct vc_data *sel_cons;		/* must not be deallocated */
+static int use_unicode;
 static volatile int sel_start = -1; 	/* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
@@ -54,10 +56,11 @@
 	complement_pos(sel_cons, where);
 }
 
-static unsigned char
+static u16
 sel_pos(int n)
 {
-	return inverse_translate(sel_cons, screen_glyph(sel_cons, n));
+	return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
+				use_unicode);
 }
 
 /* remove the current selection highlight, if any,
@@ -86,8 +89,8 @@
   0xFF7FFFFF  /* latin-1 accented letters, not division sign */
 };
 
-static inline int inword(const unsigned char c) {
-	return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
+static inline int inword(const u16 c) {
+	return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
 }
 
 /* set inwordLut contents. Invoked by ioctl(). */
@@ -108,13 +111,36 @@
 	return (v > u) ? u : v;
 }
 
+/* stores the char in UTF8 and returns the number of bytes used (1-3) */
+static int store_utf8(u16 c, char *p)
+{
+	if (c < 0x80) {
+		/*  0******* */
+		p[0] = c;
+		return 1;
+	} else if (c < 0x800) {
+		/* 110***** 10****** */
+		p[0] = 0xc0 | (c >> 6);
+		p[1] = 0x80 | (c & 0x3f);
+		return 2;
+    	} else {
+		/* 1110**** 10****** 10****** */
+		p[0] = 0xe0 | (c >> 12);
+		p[1] = 0x80 | ((c >> 6) & 0x3f);
+		p[2] = 0x80 | (c & 0x3f);
+		return 3;
+    	}
+}
+
 /* set the current selection. Invoked by ioctl() or by kernel code. */
 int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	int sel_mode, new_sel_start, new_sel_end, spc;
 	char *bp, *obp;
-	int i, ps, pe;
+	int i, ps, pe, multiplier;
+	u16 c;
+	struct kbd_struct *kbd = kbd_table + fg_console;
 
 	poke_blanked_console();
 
@@ -158,6 +184,7 @@
 		clear_selection();
 		sel_cons = vc_cons[fg_console].d;
 	}
+	use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
 
 	switch (sel_mode)
 	{
@@ -240,7 +267,8 @@
 	sel_end = new_sel_end;
 
 	/* Allocate a new buffer before freeing the old one ... */
-	bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
+	multiplier = use_unicode ? 3 : 1;  /* chars can take up to 3 bytes */
+	bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL);
 	if (!bp) {
 		printk(KERN_WARNING "selection: kmalloc() failed\n");
 		clear_selection();
@@ -251,8 +279,12 @@
 
 	obp = bp;
 	for (i = sel_start; i <= sel_end; i += 2) {
-		*bp = sel_pos(i);
-		if (!isspace(*bp++))
+		c = sel_pos(i);
+		if (use_unicode)
+			bp += store_utf8(c, bp);
+		else
+			*bp++ = c;
+		if (!isspace(c))
 			obp = bp;
 		if (! ((i + 2) % vc->vc_size_row)) {
 			/* strip trailing blanks from line and add newline,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 3ef593a..73037a4 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -885,53 +885,6 @@
 	return IRQ_HANDLED;
 }
 
-/* External camera command (exported to the motion eye v4l driver) */
-int sonypi_camera_command(int command, u8 value)
-{
-	if (!camera)
-		return -EIO;
-
-	mutex_lock(&sonypi_device.lock);
-
-	switch (command) {
-	case SONYPI_COMMAND_SETCAMERA:
-		if (value)
-			sonypi_camera_on();
-		else
-			sonypi_camera_off();
-		break;
-	case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
-		sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERACONTRAST:
-		sonypi_set(SONYPI_CAMERA_CONTRAST, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERAHUE:
-		sonypi_set(SONYPI_CAMERA_HUE, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERACOLOR:
-		sonypi_set(SONYPI_CAMERA_COLOR, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERASHARPNESS:
-		sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERAPICTURE:
-		sonypi_set(SONYPI_CAMERA_PICTURE, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERAAGC:
-		sonypi_set(SONYPI_CAMERA_AGC, value);
-		break;
-	default:
-		printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n",
-		       command);
-		break;
-	}
-	mutex_unlock(&sonypi_device.lock);
-	return 0;
-}
-
-EXPORT_SYMBOL(sonypi_camera_command);
-
 static int sonypi_misc_fasync(int fd, struct file *filp, int on)
 {
 	int retval;
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index baf7234..4558556 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -345,18 +345,6 @@
 }
 
 
-/* Must be called with enabled interrupts */
-/* 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); ) ;
-}
-
-
-
 /* Set the IRQ using the RTS lines that run to the PAL on the board.... */
 static int sx_set_irq ( struct specialix_board *bp)
 {
@@ -397,7 +385,7 @@
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out_off(bp, CD186x_CCR, CCR_HARDRESET);      /* Reset CD186x chip          */
 	spin_unlock_irqrestore(&bp->lock, flags);
-	sx_long_delay(HZ/20);                      /* Delay 0.05 sec            */
+	msleep(50);					/* Delay 0.05 sec            */
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out_off(bp, CD186x_GIVR, SX_ID);             /* Set ID for this chip      */
 	sx_out_off(bp, CD186x_GICR, 0);                 /* Clear all bits            */
@@ -533,7 +521,7 @@
 		sx_wait_CCR(bp);
 		sx_out(bp, CD186x_CCR, CCR_TXEN);        /* Enable transmitter     */
 		sx_out(bp, CD186x_IER, IER_TXRDY);       /* Enable tx empty intr   */
-		sx_long_delay(HZ/20);
+		msleep(50);
 		irqs = probe_irq_off(irqs);
 
 		dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 8c73ccb..93d0bb8 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1788,7 +1788,6 @@
 	if (tty == NULL)
 		return;
 
-	lock_kernel();
 	if (test_bit(ASYI_TXLOW, &portp->istate))
 		tty_wakeup(tty);
 
@@ -1802,7 +1801,6 @@
 			if (portp->flags & ASYNC_CHECK_CD)
 				tty_hangup(tty);	/* FIXME: module removal race here - AKPM */
 	}
-	unlock_kernel();
 }
 
 /*****************************************************************************/
@@ -2357,9 +2355,6 @@
 	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
 		goto err;
 
-	dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
-			pdev->vendor, pdev->device, pdev->class);
-
 	retval = pci_enable_device(pdev);
 	if (retval)
 		goto err;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index f02a079..f53e51d 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -160,8 +160,6 @@
 
 #define IO_PIN_SHUTDOWN_LIMIT 100
 
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 struct	_input_signal_events {
 	int	ri_up;	
 	int	ri_down;
@@ -3064,12 +3062,6 @@
 		printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__,
 			tty->driver->name );
 	
-	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	mgsl_change_params(info);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 02b49bc..428b514 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -144,8 +144,6 @@
 /*
  * tty support and callbacks
  */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 static struct tty_driver *serial_driver;
 
 static int  open(struct tty_struct *tty, struct file * filp);
@@ -823,12 +821,6 @@
 
 	DBGINFO(("%s set_termios\n", tty->driver->name));
 
-	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag)
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-		return;
-
 	change_params(info);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ef93d05..a65407b 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -135,8 +135,6 @@
 
 #define IO_PIN_SHUTDOWN_LIMIT 100
 
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 struct	_input_signal_events {
 	int	ri_up;
 	int	ri_down;
@@ -927,12 +925,6 @@
 		printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__,
 			tty->driver->name );
 
-	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag)
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	change_params(info);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index dc4e1ff..8f3f762 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -2,11 +2,9 @@
 # TPM device configuration
 #
 
-menu "TPM devices"
-	depends on HAS_IOMEM
-
-config TCG_TPM
+menuconfig TCG_TPM
 	tristate "TPM Hardware Support"
+	depends on HAS_IOMEM
 	depends on EXPERIMENTAL
 	---help---
 	  If you have a TPM security chip in your system, which
@@ -21,9 +19,11 @@
 	  Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
 	  and CONFIG_PNPACPI.
 
+if TCG_TPM
+
 config TCG_TIS
 	tristate "TPM Interface Specification 1.2 Interface"
-	depends on TCG_TPM && PNPACPI
+	depends on PNPACPI
 	---help---
 	  If you have a TPM security chip that is compliant with the
 	  TCG TIS 1.2 TPM specification say Yes and it will be accessible
@@ -32,7 +32,7 @@
 
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
-	depends on TCG_TPM && PNPACPI
+	depends on PNPACPI
 	---help---
 	  If you have a TPM security chip from National Semiconductor 
 	  say Yes and it will be accessible from within Linux.  To 
@@ -41,7 +41,6 @@
 
 config TCG_ATMEL
 	tristate "Atmel TPM Interface"
-	depends on TCG_TPM
 	---help---
 	  If you have a TPM security chip from Atmel say Yes and it 
 	  will be accessible from within Linux.  To compile this driver 
@@ -49,7 +48,7 @@
 
 config TCG_INFINEON
 	tristate "Infineon Technologies TPM Interface"
-	depends on TCG_TPM && PNPACPI
+	depends on PNPACPI
 	---help---
 	  If you have a TPM security chip from Infineon Technologies
 	  (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
@@ -59,5 +58,4 @@
 	  Further information on this driver and the supported hardware
 	  can be found at http://www.prosec.rub.de/tpm
 
-endmenu
-
+endif # TCG_TPM
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
new file mode 100644
index 0000000..d222012
--- /dev/null
+++ b/drivers/char/tty_audit.c
@@ -0,0 +1,345 @@
+/*
+ * Creating audit events from TTY input.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.  All rights reserved.  This copyrighted
+ * material is made available to anyone wishing to use, modify, copy, or
+ * redistribute it subject to the terms and conditions of the GNU General
+ * Public License v.2.
+ *
+ * Authors: Miloslav Trmac <mitr@redhat.com>
+ */
+
+#include <linux/audit.h>
+#include <linux/file.h>
+#include <linux/tty.h>
+
+struct tty_audit_buf {
+	atomic_t count;
+	struct mutex mutex;	/* Protects all data below */
+	int major, minor;	/* The TTY which the data is from */
+	unsigned icanon:1;
+	size_t valid;
+	unsigned char *data;	/* Allocated size N_TTY_BUF_SIZE */
+};
+
+static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
+						 int icanon)
+{
+	struct tty_audit_buf *buf;
+
+	buf = kmalloc(sizeof (*buf), GFP_KERNEL);
+	if (!buf)
+		goto err;
+	if (PAGE_SIZE != N_TTY_BUF_SIZE)
+		buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+	else
+		buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (!buf->data)
+		goto err_buf;
+	atomic_set(&buf->count, 1);
+	mutex_init(&buf->mutex);
+	buf->major = major;
+	buf->minor = minor;
+	buf->icanon = icanon;
+	buf->valid = 0;
+	return buf;
+
+err_buf:
+	kfree(buf);
+err:
+	return NULL;
+}
+
+static void tty_audit_buf_free(struct tty_audit_buf *buf)
+{
+	WARN_ON(buf->valid != 0);
+	if (PAGE_SIZE != N_TTY_BUF_SIZE)
+		kfree(buf->data);
+	else
+		free_page((unsigned long)buf->data);
+	kfree(buf);
+}
+
+static void tty_audit_buf_put(struct tty_audit_buf *buf)
+{
+	if (atomic_dec_and_test(&buf->count))
+		tty_audit_buf_free(buf);
+}
+
+/**
+ *	tty_audit_buf_push	-	Push buffered data out
+ *
+ *	Generate an audit message from the contents of @buf, which is owned by
+ *	@tsk with @loginuid.  @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
+			       struct tty_audit_buf *buf)
+{
+	struct audit_buffer *ab;
+
+	if (buf->valid == 0)
+		return;
+	if (audit_enabled == 0)
+		return;
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
+	if (ab) {
+		char name[sizeof(tsk->comm)];
+
+		audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
+				 "minor=%d comm=", tsk->pid, tsk->uid,
+				 loginuid, buf->major, buf->minor);
+		get_task_comm(name, tsk);
+		audit_log_untrustedstring(ab, name);
+		audit_log_format(ab, " data=");
+		audit_log_n_untrustedstring(ab, buf->valid, buf->data);
+		audit_log_end(ab);
+	}
+	buf->valid = 0;
+}
+
+/**
+ *	tty_audit_buf_push_current	-	Push buffered data out
+ *
+ *	Generate an audit message from the contents of @buf, which is owned by
+ *	the current task.  @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
+{
+	tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
+			   buf);
+}
+
+/**
+ *	tty_audit_exit	-	Handle a task exit
+ *
+ *	Make sure all buffered data is written out and deallocate the buffer.
+ *	Only needs to be called if current->signal->tty_audit_buf != %NULL.
+ */
+void tty_audit_exit(void)
+{
+	struct tty_audit_buf *buf;
+
+	spin_lock_irq(&current->sighand->siglock);
+	buf = current->signal->tty_audit_buf;
+	current->signal->tty_audit_buf = NULL;
+	spin_unlock_irq(&current->sighand->siglock);
+	if (!buf)
+		return;
+
+	mutex_lock(&buf->mutex);
+	tty_audit_buf_push_current(buf);
+	mutex_unlock(&buf->mutex);
+
+	tty_audit_buf_put(buf);
+}
+
+/**
+ *	tty_audit_fork	-	Copy TTY audit state for a new task
+ *
+ *	Set up TTY audit state in @sig from current.  @sig needs no locking.
+ */
+void tty_audit_fork(struct signal_struct *sig)
+{
+	spin_lock_irq(&current->sighand->siglock);
+	sig->audit_tty = current->signal->audit_tty;
+	spin_unlock_irq(&current->sighand->siglock);
+	sig->tty_audit_buf = NULL;
+}
+
+/**
+ *	tty_audit_push_task	-	Flush task's pending audit data
+ */
+void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+{
+	struct tty_audit_buf *buf;
+
+	spin_lock_irq(&tsk->sighand->siglock);
+	buf = tsk->signal->tty_audit_buf;
+	if (buf)
+		atomic_inc(&buf->count);
+	spin_unlock_irq(&tsk->sighand->siglock);
+	if (!buf)
+		return;
+
+	mutex_lock(&buf->mutex);
+	tty_audit_buf_push(tsk, loginuid, buf);
+	mutex_unlock(&buf->mutex);
+
+	tty_audit_buf_put(buf);
+}
+
+/**
+ *	tty_audit_buf_get	-	Get an audit buffer.
+ *
+ *	Get an audit buffer for @tty, allocate it if necessary.  Return %NULL
+ *	if TTY auditing is disabled or out of memory.  Otherwise, return a new
+ *	reference to the buffer.
+ */
+static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
+{
+	struct tty_audit_buf *buf, *buf2;
+
+	buf = NULL;
+	buf2 = NULL;
+	spin_lock_irq(&current->sighand->siglock);
+	if (likely(!current->signal->audit_tty))
+		goto out;
+	buf = current->signal->tty_audit_buf;
+	if (buf) {
+		atomic_inc(&buf->count);
+		goto out;
+	}
+	spin_unlock_irq(&current->sighand->siglock);
+
+	buf2 = tty_audit_buf_alloc(tty->driver->major,
+				   tty->driver->minor_start + tty->index,
+				   tty->icanon);
+	if (buf2 == NULL) {
+		audit_log_lost("out of memory in TTY auditing");
+		return NULL;
+	}
+
+	spin_lock_irq(&current->sighand->siglock);
+	if (!current->signal->audit_tty)
+		goto out;
+	buf = current->signal->tty_audit_buf;
+	if (!buf) {
+		current->signal->tty_audit_buf = buf2;
+		buf = buf2;
+		buf2 = NULL;
+	}
+	atomic_inc(&buf->count);
+	/* Fall through */
+ out:
+	spin_unlock_irq(&current->sighand->siglock);
+	if (buf2)
+		tty_audit_buf_free(buf2);
+	return buf;
+}
+
+/**
+ *	tty_audit_add_data	-	Add data for TTY auditing.
+ *
+ *	Audit @data of @size from @tty, if necessary.
+ */
+void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+			size_t size)
+{
+	struct tty_audit_buf *buf;
+	int major, minor;
+
+	if (unlikely(size == 0))
+		return;
+
+	buf = tty_audit_buf_get(tty);
+	if (!buf)
+		return;
+
+	mutex_lock(&buf->mutex);
+	major = tty->driver->major;
+	minor = tty->driver->minor_start + tty->index;
+	if (buf->major != major || buf->minor != minor
+	    || buf->icanon != tty->icanon) {
+		tty_audit_buf_push_current(buf);
+		buf->major = major;
+		buf->minor = minor;
+		buf->icanon = tty->icanon;
+	}
+	do {
+		size_t run;
+
+		run = N_TTY_BUF_SIZE - buf->valid;
+		if (run > size)
+			run = size;
+		memcpy(buf->data + buf->valid, data, run);
+		buf->valid += run;
+		data += run;
+		size -= run;
+		if (buf->valid == N_TTY_BUF_SIZE)
+			tty_audit_buf_push_current(buf);
+	} while (size != 0);
+	mutex_unlock(&buf->mutex);
+	tty_audit_buf_put(buf);
+}
+
+/**
+ *	tty_audit_push	-	Push buffered data out
+ *
+ *	Make sure no audit data is pending for @tty on the current process.
+ */
+void tty_audit_push(struct tty_struct *tty)
+{
+	struct tty_audit_buf *buf;
+
+	spin_lock_irq(&current->sighand->siglock);
+	if (likely(!current->signal->audit_tty)) {
+		spin_unlock_irq(&current->sighand->siglock);
+		return;
+	}
+	buf = current->signal->tty_audit_buf;
+	if (buf)
+		atomic_inc(&buf->count);
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (buf) {
+		int major, minor;
+
+		major = tty->driver->major;
+		minor = tty->driver->minor_start + tty->index;
+		mutex_lock(&buf->mutex);
+		if (buf->major == major && buf->minor == minor)
+			tty_audit_buf_push_current(buf);
+		mutex_unlock(&buf->mutex);
+		tty_audit_buf_put(buf);
+	}
+}
+
+/**
+ *	tty_audit_opening	-	A TTY is being opened.
+ *
+ *	As a special hack, tasks that close all their TTYs and open new ones
+ *	are assumed to be system daemons (e.g. getty) and auditing is
+ *	automatically disabled for them.
+ */
+void tty_audit_opening(void)
+{
+	int disable;
+
+	disable = 1;
+	spin_lock_irq(&current->sighand->siglock);
+	if (current->signal->audit_tty == 0)
+		disable = 0;
+	spin_unlock_irq(&current->sighand->siglock);
+	if (!disable)
+		return;
+
+	task_lock(current);
+	if (current->files) {
+		struct fdtable *fdt;
+		unsigned i;
+
+		/*
+		 * We don't take a ref to the file, so we must hold ->file_lock
+		 * instead.
+		 */
+		spin_lock(&current->files->file_lock);
+		fdt = files_fdtable(current->files);
+		for (i = 0; i < fdt->max_fds; i++) {
+			struct file *filp;
+
+			filp = fcheck_files(current->files, i);
+			if (filp && is_tty(filp)) {
+				disable = 0;
+				break;
+			}
+		}
+		spin_unlock(&current->files->file_lock);
+	}
+	task_unlock(current);
+	if (!disable)
+		return;
+
+	spin_lock_irq(&current->sighand->siglock);
+	current->signal->audit_tty = 0;
+	spin_unlock_irq(&current->sighand->siglock);
+}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a96f26a..de37ebc 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1503,6 +1503,15 @@
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
+/**
+ * is_tty	-	checker whether file is a TTY
+ */
+int is_tty(struct file *filp)
+{
+	return filp->f_op->read == tty_read
+		|| filp->f_op->read == hung_up_tty_read;
+}
+
 static void session_clear_tty(struct pid *session)
 {
 	struct task_struct *p;
@@ -1726,6 +1735,23 @@
 	return i;
 }
 
+void tty_write_unlock(struct tty_struct *tty)
+{
+	mutex_unlock(&tty->atomic_write_lock);
+	wake_up_interruptible(&tty->write_wait);
+}
+
+int tty_write_lock(struct tty_struct *tty, int ndelay)
+{
+	if (!mutex_trylock(&tty->atomic_write_lock)) {
+		if (ndelay)
+			return -EAGAIN;
+		if (mutex_lock_interruptible(&tty->atomic_write_lock))
+			return -ERESTARTSYS;
+	}
+	return 0;
+}
+
 /*
  * Split writes up in sane blocksizes to avoid
  * denial-of-service type attacks
@@ -1737,13 +1763,12 @@
 	const char __user *buf,
 	size_t count)
 {
-	ssize_t ret = 0, written = 0;
+	ssize_t ret, written = 0;
 	unsigned int chunk;
 	
-	/* FIXME: O_NDELAY ... */
-	if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
-		return -ERESTARTSYS;
-	}
+	ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
+	if (ret < 0)
+		return ret;
 
 	/*
 	 * We chunk up writes into a temporary buffer. This
@@ -1776,8 +1801,8 @@
 
 		buf = kmalloc(chunk, GFP_KERNEL);
 		if (!buf) {
-			mutex_unlock(&tty->atomic_write_lock);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto out;
 		}
 		kfree(tty->write_buf);
 		tty->write_cnt = chunk;
@@ -1812,7 +1837,8 @@
 		inode->i_mtime = current_fs_time(inode->i_sb);
 		ret = written;
 	}
-	mutex_unlock(&tty->atomic_write_lock);
+out:
+	tty_write_unlock(tty);
 	return ret;
 }
 
@@ -2016,11 +2042,9 @@
 	}
 
 	if (!*ltp_loc) {
-		ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
-						 GFP_KERNEL);
+		ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
 		if (!ltp)
 			goto free_mem_out;
-		memset(ltp, 0, sizeof(struct ktermios));
 	}
 
 	if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -2049,11 +2073,9 @@
 		}
 
 		if (!*o_ltp_loc) {
-			o_ltp = (struct ktermios *)
-				kmalloc(sizeof(struct ktermios), GFP_KERNEL);
+			o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
 			if (!o_ltp)
 				goto free_mem_out;
-			memset(o_ltp, 0, sizeof(struct ktermios));
 		}
 
 		/*
@@ -2660,6 +2682,7 @@
 		__proc_set_tty(current, tty);
 	spin_unlock_irq(&current->sighand->siglock);
 	mutex_unlock(&tty_mutex);
+	tty_audit_opening();
 	return 0;
 }
 
@@ -2722,8 +2745,10 @@
 
 	check_tty_count(tty, "tty_open");
 	retval = ptm_driver->open(tty, filp);
-	if (!retval)
+	if (!retval) {
+		tty_audit_opening();
 		return 0;
+	}
 out1:
 	release_dev(filp);
 	return retval;
@@ -3163,14 +3188,13 @@
 
 static int send_break(struct tty_struct *tty, unsigned int duration)
 {
-	if (mutex_lock_interruptible(&tty->atomic_write_lock))
+	if (tty_write_lock(tty, 0) < 0)
 		return -EINTR;
 	tty->driver->break_ctl(tty, -1);
-	if (!signal_pending(current)) {
+	if (!signal_pending(current))
 		msleep_interruptible(duration);
-	}
 	tty->driver->break_ctl(tty, 0);
-	mutex_unlock(&tty->atomic_write_lock);
+	tty_write_unlock(tty);
 	if (signal_pending(current))
 		return -EINTR;
 	return 0;
@@ -3739,9 +3763,8 @@
 {
 	struct tty_driver *driver;
 
-	driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
+	driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
 	if (driver) {
-		memset(driver, 0, sizeof(struct tty_driver));
 		driver->magic = TTY_DRIVER_MAGIC;
 		driver->num = lines;
 		/* later we'll move allocation of tables here */
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index fd471cb..3423e9ee 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -52,8 +52,6 @@
 
 void tty_wait_until_sent(struct tty_struct * tty, long timeout)
 {
-	DECLARE_WAITQUEUE(wait, current);
-
 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
 	char buf[64];
 	
@@ -61,26 +59,13 @@
 #endif
 	if (!tty->driver->chars_in_buffer)
 		return;
-	add_wait_queue(&tty->write_wait, &wait);
 	if (!timeout)
 		timeout = MAX_SCHEDULE_TIMEOUT;
-	do {
-#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
-		printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
-		       tty->driver->chars_in_buffer(tty));
-#endif
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (signal_pending(current))
-			goto stop_waiting;
-		if (!tty->driver->chars_in_buffer(tty))
-			break;
-		timeout = schedule_timeout(timeout);
-	} while (timeout);
+	if (wait_event_interruptible_timeout(tty->write_wait,
+			!tty->driver->chars_in_buffer(tty), timeout))
+		return;
 	if (tty->driver->wait_until_sent)
 		tty->driver->wait_until_sent(tty, timeout);
-stop_waiting:
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&tty->write_wait, &wait);
 }
 
 EXPORT_SYMBOL(tty_wait_until_sent);
@@ -276,13 +261,12 @@
 				termios->c_cflag |= (baud_bits[i] << IBSHIFT);
 			ifound = i;
 		}
-	}
-	while(++i < n_baud_table);
+	} while (++i < n_baud_table);
 	if (ofound == -1)
 		termios->c_cflag |= BOTHER;
 	/* Set exact input bits only if the input and output differ or the
 	   user already did */
-	if (ifound == -1 && (ibaud != obaud  || ibinput))
+	if (ifound == -1 && (ibaud != obaud || ibinput))
 		termios->c_cflag |= (BOTHER << IBSHIFT);
 }
 
@@ -575,7 +559,7 @@
 		return -EFAULT;
 
 	mutex_lock(&tty->termios_mutex);
-	termios =  *tty->termios;
+	termios = *tty->termios;
 	termios.c_cc[VERASE] = tmp.sg_erase;
 	termios.c_cc[VKILL] = tmp.sg_kill;
 	set_sgflags(&termios, tmp.sg_flags);
@@ -667,7 +651,7 @@
 		return 0;
 	}
 
-	if (mutex_lock_interruptible(&tty->atomic_write_lock))
+	if (tty_write_lock(tty, 0) < 0)
 		return -ERESTARTSYS;
 
 	if (was_stopped)
@@ -675,7 +659,7 @@
 	tty->driver->write(tty, &ch, 1);
 	if (was_stopped)
 		stop_tty(tty);
-	mutex_unlock(&tty->atomic_write_lock);
+	tty_write_unlock(tty);
 	return 0;
 }
 
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 13faf8d..db57277 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -873,12 +873,12 @@
 }
 
 const struct file_operations viotap_fops = {
-	owner: THIS_MODULE,
-	read: viotap_read,
-	write: viotap_write,
-	ioctl: viotap_ioctl,
-	open: viotap_open,
-	release: viotap_release,
+	.owner =	THIS_MODULE,
+	.read =		viotap_read,
+	.write =	viotap_write,
+	.ioctl =	viotap_ioctl,
+	.open =		viotap_open,
+	.release =	viotap_release,
 };
 
 /* Handle interrupt events for tape */
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6650ae1..edb7002 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -729,10 +729,9 @@
 	    /* although the numbers above are not valid since long ago, the
 	       point is still up-to-date and the comment still has its value
 	       even if only as a historical artifact.  --mj, July 1998 */
-	    vc = kmalloc(sizeof(struct vc_data), GFP_KERNEL);
+	    vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL);
 	    if (!vc)
 		return -ENOMEM;
-	    memset(vc, 0, sizeof(*vc));
 	    vc_cons[currcons].d = vc;
 	    INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
 	    visual_init(vc, currcons, 1);
@@ -1991,8 +1990,7 @@
 		{ 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },
 		{ 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
 	};
-	return bisearch(ucs, double_width,
-		sizeof(double_width) / sizeof(*double_width) - 1);
+	return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);
 }
 
 /* acquires console_sem */
@@ -2989,8 +2987,24 @@
 	return retval;
 }
 
-static int unbind_con_driver(const struct consw *csw, int first, int last,
-			     int deflt)
+/**
+ * unbind_con_driver - unbind a console driver
+ * @csw: pointer to console driver to unregister
+ * @first: first in range of consoles that @csw should be unbound from
+ * @last: last in range of consoles that @csw should be unbound from
+ * @deflt: should next bound console driver be default after @csw is unbound?
+ *
+ * To unbind a driver from all possible consoles, pass 0 as @first and
+ * %MAX_NR_CONSOLES as @last.
+ *
+ * @deflt controls whether the console that ends up replacing @csw should be
+ * the default console.
+ *
+ * RETURNS:
+ * -ENODEV if @csw isn't a registered console driver or can't be unregistered
+ * or 0 on success.
+ */
+int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
 {
 	struct module *owner = csw->owner;
 	const struct consw *defcsw = NULL;
@@ -3075,6 +3089,7 @@
 	return retval;
 
 }
+EXPORT_SYMBOL(unbind_con_driver);
 
 static int vt_bind(struct con_driver *con)
 {
@@ -3491,9 +3506,6 @@
 		}
 		return;
 	}
-	if (blank_state != blank_normal_wait)
-		return;
-	blank_state = blank_off;
 
 	/* entering graphics mode? */
 	if (entering_gfx) {
@@ -3501,10 +3513,15 @@
 		save_screen(vc);
 		vc->vc_sw->con_blank(vc, -1, 1);
 		console_blanked = fg_console + 1;
+		blank_state = blank_off;
 		set_origin(vc);
 		return;
 	}
 
+	if (blank_state != blank_normal_wait)
+		return;
+	blank_state = blank_off;
+
 	/* don't blank graphics */
 	if (vc->vc_mode != KD_TEXT) {
 		console_blanked = fg_console + 1;
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
index e0bdc0d..100bfd4 100644
--- a/drivers/connector/Kconfig
+++ b/drivers/connector/Kconfig
@@ -1,6 +1,5 @@
-menu "Connector - unified userspace <-> kernelspace linker"
 
-config CONNECTOR
+menuconfig CONNECTOR
 	tristate "Connector - unified userspace <-> kernelspace linker"
 	depends on NET
 	---help---
@@ -10,6 +9,8 @@
 	  Connector support can also be built as a module.  If so, the module
 	  will be called cn.ko.
 
+if CONNECTOR
+
 config PROC_EVENTS
 	boolean "Report process events to userspace"
 	depends on CONNECTOR=y
@@ -18,4 +19,4 @@
 	  Provide a connector that reports process events to userspace. Send
 	  events such as fork, exec, id change (uid, gid, suid, etc), and exit.
 
-endmenu
+endif # CONNECTOR
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index bb90cbd..84ebfcc 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -1,4 +1,9 @@
-menu "Hardware crypto devices"
+
+menuconfig CRYPTO_HW
+	bool "Hardware crypto devices"
+	default y
+
+if CRYPTO_HW
 
 config CRYPTO_DEV_PADLOCK
 	tristate "Support for VIA PadLock ACE"
@@ -78,4 +83,4 @@
 	  that contains all parts of the crypto device driver (ap bus,
 	  request router and all the card drivers).
 
-endmenu
+endif # CRYPTO_HW
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b31756d..8f670da 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menu "DMA Engine support"
-	depends on !S390
+	depends on HAS_DMA
 
 config DMA_ENGINE
 	bool "Support for DMA engines"
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 807c402..debf1d8 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -6,11 +6,9 @@
 # $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
 #
 
-menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)'
+menuconfig EDAC
+	tristate "EDAC - error detection and reporting (EXPERIMENTAL)"
 	depends on HAS_IOMEM
-
-config EDAC
-	tristate "EDAC core system error reporting (EXPERIMENTAL)"
 	depends on X86 && EXPERIMENTAL
 	help
 	  EDAC is designed to report errors in the core system.
@@ -30,13 +28,12 @@
 	  There is also a mailing list for the EDAC project, which can
 	  be found via the sourceforge page.
 
+if EDAC
 
 comment "Reporting subsystems"
-	depends on EDAC
 
 config EDAC_DEBUG
 	bool "Debugging"
-	depends on EDAC
 	help
 	  This turns on debugging information for the entire EDAC
 	  sub-system. You can insert module with "debug_level=x", current
@@ -45,7 +42,6 @@
 
 config EDAC_MM_EDAC
 	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
-	depends on EDAC
 	default y
 	help
 	  Some systems are able to detect and correct errors in main
@@ -100,15 +96,13 @@
 
 choice
 	prompt "Error detecting method"
-	depends on EDAC
 	default EDAC_POLL
 
 config EDAC_POLL
 	bool "Poll for errors"
-	depends on EDAC
 	help
 	  Poll the chipset periodically to detect errors.
 
 endchoice
 
-endmenu
+endif # EDAC
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 7b62230..804875d 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1906,6 +1906,7 @@
 
 static int edac_kernel_thread(void *arg)
 {
+	set_freezable();
 	while (!kthread_should_stop()) {
 		do_edac_check();
 
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 1523227..0fb730e 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -669,7 +669,7 @@
 	struct edd_info *info = edd_dev_get_info(edev);
 
 	if (edd_dev_is_type(edev, "PCI")) {
-		return pci_find_slot(info->params.interface_path.pci.bus,
+		return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
 				     PCI_DEVFN(info->params.interface_path.pci.slot,
 					       info->params.interface_path.pci.
 					       function));
@@ -682,9 +682,12 @@
 {
 
 	struct pci_dev *pci_dev = edd_get_pci_dev(edev);
+	int ret;
 	if (!pci_dev)
 		return 1;
-	return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+	ret = sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+	pci_dev_put(pci_dev);
+	return ret;
 }
 
 static inline void
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index 2b4b76e..58e9f8e 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -15,6 +15,7 @@
 #include <linux/console.h>
 #include <linux/efi.h>
 #include <linux/serial.h>
+#include <linux/serial_8250.h>
 #include <asm/vga.h>
 #include "pcdp.h"
 
@@ -27,7 +28,7 @@
 	char parity;
 
 	mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
-	p += sprintf(p, "console=uart,%s,0x%lx",
+	p += sprintf(p, "uart8250,%s,0x%lx",
 		mmio ? "mmio" : "io", uart->addr.address);
 	if (uart->baud) {
 		p += sprintf(p, ",%lu", uart->baud);
@@ -41,7 +42,8 @@
 		}
 	}
 
-	return early_serial_console_init(options);
+	add_preferred_console("uart", 8250, &options[9]);
+	return setup_early_serial8250_console(options);
 #else
 	return -ENODEV;
 #endif
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 7eaae38..275d392 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -96,6 +96,10 @@
 	struct lm70 *p_lm70;
 	int status;
 
+	/* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */
+	if ((spi->mode & (SPI_CPOL|SPI_CPHA)) || !(spi->mode & SPI_3WIRE))
+		return -EINVAL;
+
 	p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
 	if (!p_lm70)
 		return -ENOMEM;
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index 03188d2..17cecf1 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -630,7 +630,7 @@
 static struct platform_driver pmcmsptwi_driver = {
 	.probe  = pmcmsptwi_probe,
 	.remove	= __devexit_p(pmcmsptwi_remove),
-	.driver {
+	.driver = {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
 	},
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 3944e88..2e1c24f 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -153,4 +153,14 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called tsl2550.
 
+config MENELAUS
+	bool "TWL92330/Menelaus PM chip"
+	depends on I2C=y && ARCH_OMAP24XX
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  TWL92330/Menelaus Power Management chip. This include voltage
+	  regulators, Dual slot memory card tranceivers, real-time clock
+	  and other features that are often used in portable devices like
+	  cell phones and PDAs.
+
 endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index d8cbeb3..ca924e1 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -13,6 +13,7 @@
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
+obj-$(CONFIG_MENELAUS)		+= menelaus.o
 obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
new file mode 100644
index 0000000..48a7e2f
--- /dev/null
+++ b/drivers/i2c/chips/menelaus.c
@@ -0,0 +1,1281 @@
+#define DEBUG
+/*
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Some parts based tps65010.c:
+ * Copyright (C) 2004 Texas Instruments and
+ * Copyright (C) 2004-2005 David Brownell
+ *
+ * Some parts based on tlv320aic24.c:
+ * Copyright (C) by Kai Svahn <kai.svahn@nokia.com>
+ *
+ * Changes for interrupt handling and clean-up by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Cleanup and generalized support for voltage setting by
+ * Juha Yrjola
+ * Added support for controlling VCORE and regulator sleep states,
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Copyright (C) 2005, 2006 Nokia 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 <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/menelaus.h>
+
+#define DRIVER_NAME			"menelaus"
+
+#define pr_err(fmt, arg...)	printk(KERN_ERR DRIVER_NAME ": ", ## arg);
+
+#define MENELAUS_I2C_ADDRESS		0x72
+
+#define MENELAUS_REV			0x01
+#define MENELAUS_VCORE_CTRL1		0x02
+#define MENELAUS_VCORE_CTRL2		0x03
+#define MENELAUS_VCORE_CTRL3		0x04
+#define MENELAUS_VCORE_CTRL4		0x05
+#define MENELAUS_VCORE_CTRL5		0x06
+#define MENELAUS_DCDC_CTRL1		0x07
+#define MENELAUS_DCDC_CTRL2		0x08
+#define MENELAUS_DCDC_CTRL3		0x09
+#define MENELAUS_LDO_CTRL1		0x0A
+#define MENELAUS_LDO_CTRL2		0x0B
+#define MENELAUS_LDO_CTRL3		0x0C
+#define MENELAUS_LDO_CTRL4		0x0D
+#define MENELAUS_LDO_CTRL5		0x0E
+#define MENELAUS_LDO_CTRL6		0x0F
+#define MENELAUS_LDO_CTRL7		0x10
+#define MENELAUS_LDO_CTRL8		0x11
+#define MENELAUS_SLEEP_CTRL1		0x12
+#define MENELAUS_SLEEP_CTRL2		0x13
+#define MENELAUS_DEVICE_OFF		0x14
+#define MENELAUS_OSC_CTRL		0x15
+#define MENELAUS_DETECT_CTRL		0x16
+#define MENELAUS_INT_MASK1		0x17
+#define MENELAUS_INT_MASK2		0x18
+#define MENELAUS_INT_STATUS1		0x19
+#define MENELAUS_INT_STATUS2		0x1A
+#define MENELAUS_INT_ACK1		0x1B
+#define MENELAUS_INT_ACK2		0x1C
+#define MENELAUS_GPIO_CTRL		0x1D
+#define MENELAUS_GPIO_IN		0x1E
+#define MENELAUS_GPIO_OUT		0x1F
+#define MENELAUS_BBSMS			0x20
+#define MENELAUS_RTC_CTRL		0x21
+#define MENELAUS_RTC_UPDATE		0x22
+#define MENELAUS_RTC_SEC		0x23
+#define MENELAUS_RTC_MIN		0x24
+#define MENELAUS_RTC_HR			0x25
+#define MENELAUS_RTC_DAY		0x26
+#define MENELAUS_RTC_MON		0x27
+#define MENELAUS_RTC_YR			0x28
+#define MENELAUS_RTC_WKDAY		0x29
+#define MENELAUS_RTC_AL_SEC		0x2A
+#define MENELAUS_RTC_AL_MIN		0x2B
+#define MENELAUS_RTC_AL_HR		0x2C
+#define MENELAUS_RTC_AL_DAY		0x2D
+#define MENELAUS_RTC_AL_MON		0x2E
+#define MENELAUS_RTC_AL_YR		0x2F
+#define MENELAUS_RTC_COMP_MSB		0x30
+#define MENELAUS_RTC_COMP_LSB		0x31
+#define MENELAUS_S1_PULL_EN		0x32
+#define MENELAUS_S1_PULL_DIR		0x33
+#define MENELAUS_S2_PULL_EN		0x34
+#define MENELAUS_S2_PULL_DIR		0x35
+#define MENELAUS_MCT_CTRL1		0x36
+#define MENELAUS_MCT_CTRL2		0x37
+#define MENELAUS_MCT_CTRL3		0x38
+#define MENELAUS_MCT_PIN_ST		0x39
+#define MENELAUS_DEBOUNCE1		0x3A
+
+#define IH_MENELAUS_IRQS		12
+#define MENELAUS_MMC_S1CD_IRQ		0	/* MMC slot 1 card change */
+#define MENELAUS_MMC_S2CD_IRQ		1	/* MMC slot 2 card change */
+#define MENELAUS_MMC_S1D1_IRQ		2	/* MMC DAT1 low in slot 1 */
+#define MENELAUS_MMC_S2D1_IRQ		3	/* MMC DAT1 low in slot 2 */
+#define MENELAUS_LOWBAT_IRQ		4	/* Low battery */
+#define MENELAUS_HOTDIE_IRQ		5	/* Hot die detect */
+#define MENELAUS_UVLO_IRQ		6	/* UVLO detect */
+#define MENELAUS_TSHUT_IRQ		7	/* Thermal shutdown */
+#define MENELAUS_RTCTMR_IRQ		8	/* RTC timer */
+#define MENELAUS_RTCALM_IRQ		9	/* RTC alarm */
+#define MENELAUS_RTCERR_IRQ		10	/* RTC error */
+#define MENELAUS_PSHBTN_IRQ		11	/* Push button */
+#define MENELAUS_RESERVED12_IRQ		12	/* Reserved */
+#define MENELAUS_RESERVED13_IRQ		13	/* Reserved */
+#define MENELAUS_RESERVED14_IRQ		14	/* Reserved */
+#define MENELAUS_RESERVED15_IRQ		15	/* Reserved */
+
+static void menelaus_work(struct work_struct *_menelaus);
+
+struct menelaus_chip {
+	struct mutex		lock;
+	struct i2c_client	*client;
+	struct work_struct	work;
+#ifdef CONFIG_RTC_DRV_TWL92330
+	struct rtc_device	*rtc;
+	u8			rtc_control;
+	unsigned		uie:1;
+#endif
+	unsigned		vcore_hw_mode:1;
+	u8			mask1, mask2;
+	void			(*handlers[16])(struct menelaus_chip *);
+	void			(*mmc_callback)(void *data, u8 mask);
+	void			*mmc_callback_data;
+};
+
+static struct menelaus_chip *the_menelaus;
+
+static int menelaus_write_reg(int reg, u8 value)
+{
+	int val = i2c_smbus_write_byte_data(the_menelaus->client, reg, value);
+
+	if (val < 0) {
+		pr_err("write error");
+		return val;
+	}
+
+	return 0;
+}
+
+static int menelaus_read_reg(int reg)
+{
+	int val = i2c_smbus_read_byte_data(the_menelaus->client, reg);
+
+	if (val < 0)
+		pr_err("read error");
+
+	return val;
+}
+
+static int menelaus_enable_irq(int irq)
+{
+	if (irq > 7) {
+		irq -= 8;
+		the_menelaus->mask2 &= ~(1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK2,
+				the_menelaus->mask2);
+	} else {
+		the_menelaus->mask1 &= ~(1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK1,
+				the_menelaus->mask1);
+	}
+}
+
+static int menelaus_disable_irq(int irq)
+{
+	if (irq > 7) {
+		irq -= 8;
+		the_menelaus->mask2 |= (1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK2,
+				the_menelaus->mask2);
+	} else {
+		the_menelaus->mask1 |= (1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK1,
+				the_menelaus->mask1);
+	}
+}
+
+static int menelaus_ack_irq(int irq)
+{
+	if (irq > 7)
+		return menelaus_write_reg(MENELAUS_INT_ACK2, 1 << (irq - 8));
+	else
+		return menelaus_write_reg(MENELAUS_INT_ACK1, 1 << irq);
+}
+
+/* Adds a handler for an interrupt. Does not run in interrupt context */
+static int menelaus_add_irq_work(int irq,
+		void (*handler)(struct menelaus_chip *))
+{
+	int ret = 0;
+
+	mutex_lock(&the_menelaus->lock);
+	the_menelaus->handlers[irq] = handler;
+	ret = menelaus_enable_irq(irq);
+	mutex_unlock(&the_menelaus->lock);
+
+	return ret;
+}
+
+/* Removes handler for an interrupt */
+static int menelaus_remove_irq_work(int irq)
+{
+	int ret = 0;
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_disable_irq(irq);
+	the_menelaus->handlers[irq] = NULL;
+	mutex_unlock(&the_menelaus->lock);
+
+	return ret;
+}
+
+/*
+ * Gets scheduled when a card detect interrupt happens. Note that in some cases
+ * this line is wired to card cover switch rather than the card detect switch
+ * in each slot. In this case the cards are not seen by menelaus.
+ * FIXME: Add handling for D1 too
+ */
+static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw)
+{
+	int reg;
+	unsigned char card_mask = 0;
+
+	reg = menelaus_read_reg(MENELAUS_MCT_PIN_ST);
+	if (reg < 0)
+		return;
+
+	if (!(reg & 0x1))
+		card_mask |= (1 << 0);
+
+	if (!(reg & 0x2))
+		card_mask |= (1 << 1);
+
+	if (menelaus_hw->mmc_callback)
+		menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data,
+					  card_mask);
+}
+
+/*
+ * Toggles the MMC slots between open-drain and push-pull mode.
+ */
+int menelaus_set_mmc_opendrain(int slot, int enable)
+{
+	int ret, val;
+
+	if (slot != 1 && slot != 2)
+		return -EINVAL;
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_read_reg(MENELAUS_MCT_CTRL1);
+	if (ret < 0) {
+		mutex_unlock(&the_menelaus->lock);
+		return ret;
+	}
+	val = ret;
+	if (slot == 1) {
+		if (enable)
+			val |= 1 << 2;
+		else
+			val &= ~(1 << 2);
+	} else {
+		if (enable)
+			val |= 1 << 3;
+		else
+			val &= ~(1 << 3);
+	}
+	ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val);
+	mutex_unlock(&the_menelaus->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_set_mmc_opendrain);
+
+int menelaus_set_slot_sel(int enable)
+{
+	int ret;
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
+	if (ret < 0)
+		goto out;
+	ret |= 0x02;
+	if (enable)
+		ret |= 1 << 5;
+	else
+		ret &= ~(1 << 5);
+	ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_set_slot_sel);
+
+int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en)
+{
+	int ret, val;
+
+	if (slot != 1 && slot != 2)
+		return -EINVAL;
+	if (power >= 3)
+		return -EINVAL;
+
+	mutex_lock(&the_menelaus->lock);
+
+	ret = menelaus_read_reg(MENELAUS_MCT_CTRL2);
+	if (ret < 0)
+		goto out;
+	val = ret;
+	if (slot == 1) {
+		if (cd_en)
+			val |= (1 << 4) | (1 << 6);
+		else
+			val &= ~((1 << 4) | (1 << 6));
+	} else {
+		if (cd_en)
+			val |= (1 << 5) | (1 << 7);
+		else
+			val &= ~((1 << 5) | (1 << 7));
+	}
+	ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val);
+	if (ret < 0)
+		goto out;
+
+	ret = menelaus_read_reg(MENELAUS_MCT_CTRL3);
+	if (ret < 0)
+		goto out;
+	val = ret;
+	if (slot == 1) {
+		if (enable)
+			val |= 1 << 0;
+		else
+			val &= ~(1 << 0);
+	} else {
+		int b;
+
+		if (enable)
+			ret |= 1 << 1;
+		else
+			ret &= ~(1 << 1);
+		b = menelaus_read_reg(MENELAUS_MCT_CTRL2);
+		b &= ~0x03;
+		b |= power;
+		ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b);
+		if (ret < 0)
+			goto out;
+	}
+	/* Disable autonomous shutdown */
+	val &= ~(0x03 << 2);
+	ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_set_mmc_slot);
+
+int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
+				   void *data)
+{
+	int ret = 0;
+
+	the_menelaus->mmc_callback_data = data;
+	the_menelaus->mmc_callback = callback;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S1CD_IRQ,
+				    menelaus_mmc_cd_work);
+	if (ret < 0)
+		return ret;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S2CD_IRQ,
+				    menelaus_mmc_cd_work);
+	if (ret < 0)
+		return ret;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S1D1_IRQ,
+				    menelaus_mmc_cd_work);
+	if (ret < 0)
+		return ret;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S2D1_IRQ,
+				    menelaus_mmc_cd_work);
+
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_register_mmc_callback);
+
+void menelaus_unregister_mmc_callback(void)
+{
+	menelaus_remove_irq_work(MENELAUS_MMC_S1CD_IRQ);
+	menelaus_remove_irq_work(MENELAUS_MMC_S2CD_IRQ);
+	menelaus_remove_irq_work(MENELAUS_MMC_S1D1_IRQ);
+	menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ);
+
+	the_menelaus->mmc_callback = NULL;
+	the_menelaus->mmc_callback_data = 0;
+}
+EXPORT_SYMBOL(menelaus_unregister_mmc_callback);
+
+struct menelaus_vtg {
+	const char *name;
+	u8 vtg_reg;
+	u8 vtg_shift;
+	u8 vtg_bits;
+	u8 mode_reg;
+};
+
+struct menelaus_vtg_value {
+	u16 vtg;
+	u16 val;
+};
+
+static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV,
+				int vtg_val, int mode)
+{
+	int val, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	mutex_lock(&the_menelaus->lock);
+	if (vtg == 0)
+		goto set_voltage;
+
+	ret = menelaus_read_reg(vtg->vtg_reg);
+	if (ret < 0)
+		goto out;
+	val = ret & ~(((1 << vtg->vtg_bits) - 1) << vtg->vtg_shift);
+	val |= vtg_val << vtg->vtg_shift;
+
+	dev_dbg(&c->dev, "Setting voltage '%s'"
+			 "to %d mV (reg 0x%02x, val 0x%02x)\n",
+			vtg->name, mV, vtg->vtg_reg, val);
+
+	ret = menelaus_write_reg(vtg->vtg_reg, val);
+	if (ret < 0)
+		goto out;
+set_voltage:
+	ret = menelaus_write_reg(vtg->mode_reg, mode);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	if (ret == 0) {
+		/* Wait for voltage to stabilize */
+		msleep(1);
+	}
+	return ret;
+}
+
+static int menelaus_get_vtg_value(int vtg, const struct menelaus_vtg_value *tbl,
+				  int n)
+{
+	int i;
+
+	for (i = 0; i < n; i++, tbl++)
+		if (tbl->vtg == vtg)
+			return tbl->val;
+	return -EINVAL;
+}
+
+/*
+ * Vcore can be programmed in two ways:
+ * SW-controlled: Required voltage is programmed into VCORE_CTRL1
+ * HW-controlled: Required range (roof-floor) is programmed into VCORE_CTRL3
+ * and VCORE_CTRL4
+ *
+ * Call correct 'set' function accordingly
+ */
+
+static const struct menelaus_vtg_value vcore_values[] = {
+	{ 1000, 0 },
+	{ 1025, 1 },
+	{ 1050, 2 },
+	{ 1075, 3 },
+	{ 1100, 4 },
+	{ 1125, 5 },
+	{ 1150, 6 },
+	{ 1175, 7 },
+	{ 1200, 8 },
+	{ 1225, 9 },
+	{ 1250, 10 },
+	{ 1275, 11 },
+	{ 1300, 12 },
+	{ 1325, 13 },
+	{ 1350, 14 },
+	{ 1375, 15 },
+	{ 1400, 16 },
+	{ 1425, 17 },
+	{ 1450, 18 },
+};
+
+int menelaus_set_vcore_sw(unsigned int mV)
+{
+	int val, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	val = menelaus_get_vtg_value(mV, vcore_values,
+				     ARRAY_SIZE(vcore_values));
+	if (val < 0)
+		return -EINVAL;
+
+	dev_dbg(&c->dev, "Setting VCORE to %d mV (val 0x%02x)\n", mV, val);
+
+	/* Set SW mode and the voltage in one go. */
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
+	if (ret == 0)
+		the_menelaus->vcore_hw_mode = 0;
+	mutex_unlock(&the_menelaus->lock);
+	msleep(1);
+
+	return ret;
+}
+
+int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV)
+{
+	int fval, rval, val, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	rval = menelaus_get_vtg_value(roof_mV, vcore_values,
+				      ARRAY_SIZE(vcore_values));
+	if (rval < 0)
+		return -EINVAL;
+	fval = menelaus_get_vtg_value(floor_mV, vcore_values,
+				      ARRAY_SIZE(vcore_values));
+	if (fval < 0)
+		return -EINVAL;
+
+	dev_dbg(&c->dev, "Setting VCORE FLOOR to %d mV and ROOF to %d mV\n",
+	       floor_mV, roof_mV);
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_write_reg(MENELAUS_VCORE_CTRL3, fval);
+	if (ret < 0)
+		goto out;
+	ret = menelaus_write_reg(MENELAUS_VCORE_CTRL4, rval);
+	if (ret < 0)
+		goto out;
+	if (!the_menelaus->vcore_hw_mode) {
+		val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
+		/* HW mode, turn OFF byte comparator */
+		val |= ((1 << 7) | (1 << 5));
+		ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
+		the_menelaus->vcore_hw_mode = 1;
+	}
+	msleep(1);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+
+static const struct menelaus_vtg vmem_vtg = {
+	.name = "VMEM",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 0,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL3,
+};
+
+static const struct menelaus_vtg_value vmem_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 1900, 2 },
+	{ 2500, 3 },
+};
+
+int menelaus_set_vmem(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vmem_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vmem_values, ARRAY_SIZE(vmem_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vmem_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vmem);
+
+static const struct menelaus_vtg vio_vtg = {
+	.name = "VIO",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 2,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL4,
+};
+
+static const struct menelaus_vtg_value vio_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 2500, 2 },
+	{ 2800, 3 },
+};
+
+int menelaus_set_vio(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vio_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vio_values, ARRAY_SIZE(vio_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vio_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vio);
+
+static const struct menelaus_vtg_value vdcdc_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 2000, 2 },
+	{ 2200, 3 },
+	{ 2400, 4 },
+	{ 2800, 5 },
+	{ 3000, 6 },
+	{ 3300, 7 },
+};
+
+static const struct menelaus_vtg vdcdc2_vtg = {
+	.name = "VDCDC2",
+	.vtg_reg = MENELAUS_DCDC_CTRL1,
+	.vtg_shift = 0,
+	.vtg_bits = 3,
+	.mode_reg = MENELAUS_DCDC_CTRL2,
+};
+
+static const struct menelaus_vtg vdcdc3_vtg = {
+	.name = "VDCDC3",
+	.vtg_reg = MENELAUS_DCDC_CTRL1,
+	.vtg_shift = 3,
+	.vtg_bits = 3,
+	.mode_reg = MENELAUS_DCDC_CTRL3,
+};
+
+int menelaus_set_vdcdc(int dcdc, unsigned int mV)
+{
+	const struct menelaus_vtg *vtg;
+	int val;
+
+	if (dcdc != 2 && dcdc != 3)
+		return -EINVAL;
+	if (dcdc == 2)
+		vtg = &vdcdc2_vtg;
+	else
+		vtg = &vdcdc3_vtg;
+
+	if (mV == 0)
+		return menelaus_set_voltage(vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vdcdc_values,
+				     ARRAY_SIZE(vdcdc_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(vtg, mV, val, 0x03);
+}
+
+static const struct menelaus_vtg_value vmmc_values[] = {
+	{ 1850, 0 },
+	{ 2800, 1 },
+	{ 3000, 2 },
+	{ 3100, 3 },
+};
+
+static const struct menelaus_vtg vmmc_vtg = {
+	.name = "VMMC",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 6,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL7,
+};
+
+int menelaus_set_vmmc(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vmmc_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vmmc_values, ARRAY_SIZE(vmmc_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vmmc_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vmmc);
+
+
+static const struct menelaus_vtg_value vaux_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 2500, 2 },
+	{ 2800, 3 },
+};
+
+static const struct menelaus_vtg vaux_vtg = {
+	.name = "VAUX",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 4,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL6,
+};
+
+int menelaus_set_vaux(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vaux_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vaux_values, ARRAY_SIZE(vaux_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vaux_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vaux);
+
+int menelaus_get_slot_pin_states(void)
+{
+	return menelaus_read_reg(MENELAUS_MCT_PIN_ST);
+}
+EXPORT_SYMBOL(menelaus_get_slot_pin_states);
+
+int menelaus_set_regulator_sleep(int enable, u32 val)
+{
+	int t, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_write_reg(MENELAUS_SLEEP_CTRL2, val);
+	if (ret < 0)
+		goto out;
+
+	dev_dbg(&c->dev, "regulator sleep configuration: %02x\n", val);
+
+	ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
+	if (ret < 0)
+		goto out;
+	t = ((1 << 6) | 0x04);
+	if (enable)
+		ret |= t;
+	else
+		ret &= ~t;
+	ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Handles Menelaus interrupts. Does not run in interrupt context */
+static void menelaus_work(struct work_struct *_menelaus)
+{
+	struct menelaus_chip *menelaus =
+			container_of(_menelaus, struct menelaus_chip, work);
+	void (*handler)(struct menelaus_chip *menelaus);
+
+	while (1) {
+		unsigned isr;
+
+		isr = (menelaus_read_reg(MENELAUS_INT_STATUS2)
+				& ~menelaus->mask2) << 8;
+		isr |= menelaus_read_reg(MENELAUS_INT_STATUS1)
+				& ~menelaus->mask1;
+		if (!isr)
+			break;
+
+		while (isr) {
+			int irq = fls(isr) - 1;
+			isr &= ~(1 << irq);
+
+			mutex_lock(&menelaus->lock);
+			menelaus_disable_irq(irq);
+			menelaus_ack_irq(irq);
+			handler = menelaus->handlers[irq];
+			if (handler)
+				handler(menelaus);
+			menelaus_enable_irq(irq);
+			mutex_unlock(&menelaus->lock);
+		}
+	}
+	enable_irq(menelaus->client->irq);
+}
+
+/*
+ * We cannot use I2C in interrupt context, so we just schedule work.
+ */
+static irqreturn_t menelaus_irq(int irq, void *_menelaus)
+{
+	struct menelaus_chip *menelaus = _menelaus;
+
+	disable_irq_nosync(irq);
+	(void)schedule_work(&menelaus->work);
+
+	return IRQ_HANDLED;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/*
+ * The RTC needs to be set once, then it runs on backup battery power.
+ * It supports alarms, including system wake alarms (from some modes);
+ * and 1/second IRQs if requested.
+ */
+#ifdef CONFIG_RTC_DRV_TWL92330
+
+#define RTC_CTRL_RTC_EN		(1 << 0)
+#define RTC_CTRL_AL_EN		(1 << 1)
+#define RTC_CTRL_MODE12		(1 << 2)
+#define RTC_CTRL_EVERY_MASK	(3 << 3)
+#define RTC_CTRL_EVERY_SEC	(0 << 3)
+#define RTC_CTRL_EVERY_MIN	(1 << 3)
+#define RTC_CTRL_EVERY_HR	(2 << 3)
+#define RTC_CTRL_EVERY_DAY	(3 << 3)
+
+#define RTC_UPDATE_EVERY	0x08
+
+#define RTC_HR_PM		(1 << 7)
+
+static void menelaus_to_time(char *regs, struct rtc_time *t)
+{
+	t->tm_sec = BCD2BIN(regs[0]);
+	t->tm_min = BCD2BIN(regs[1]);
+	if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
+		t->tm_hour = BCD2BIN(regs[2] & 0x1f) - 1;
+		if (regs[2] & RTC_HR_PM)
+			t->tm_hour += 12;
+	} else
+		t->tm_hour = BCD2BIN(regs[2] & 0x3f);
+	t->tm_mday = BCD2BIN(regs[3]);
+	t->tm_mon = BCD2BIN(regs[4]) - 1;
+	t->tm_year = BCD2BIN(regs[5]) + 100;
+}
+
+static int time_to_menelaus(struct rtc_time *t, int regnum)
+{
+	int	hour, status;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_sec));
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_min));
+	if (status < 0)
+		goto fail;
+
+	if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
+		hour = t->tm_hour + 1;
+		if (hour > 12)
+			hour = RTC_HR_PM | BIN2BCD(hour - 12);
+		else
+			hour = BIN2BCD(hour);
+	} else
+		hour = BIN2BCD(t->tm_hour);
+	status = menelaus_write_reg(regnum++, hour);
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mday));
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mon + 1));
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_year - 100));
+	if (status < 0)
+		goto fail;
+
+	return 0;
+fail:
+	dev_err(&the_menelaus->client->dev, "rtc write reg %02x, err %d\n",
+			--regnum, status);
+	return status;
+}
+
+static int menelaus_read_time(struct device *dev, struct rtc_time *t)
+{
+	struct i2c_msg	msg[2];
+	char		regs[7];
+	int		status;
+
+	/* block read date and time registers */
+	regs[0] = MENELAUS_RTC_SEC;
+
+	msg[0].addr = MENELAUS_I2C_ADDRESS;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = regs;
+
+	msg[1].addr = MENELAUS_I2C_ADDRESS;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = sizeof(regs);
+	msg[1].buf = regs;
+
+	status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
+	if (status != 2) {
+		dev_err(dev, "%s error %d\n", "read", status);
+		return -EIO;
+	}
+
+	menelaus_to_time(regs, t);
+	t->tm_wday = BCD2BIN(regs[6]);
+
+	return 0;
+}
+
+static int menelaus_set_time(struct device *dev, struct rtc_time *t)
+{
+	int		status;
+
+	/* write date and time registers */
+	status = time_to_menelaus(t, MENELAUS_RTC_SEC);
+	if (status < 0)
+		return status;
+	status = menelaus_write_reg(MENELAUS_RTC_WKDAY, BIN2BCD(t->tm_wday));
+	if (status < 0) {
+		dev_err(&the_menelaus->client->dev, "rtc write reg %02x",
+				"err %d\n", MENELAUS_RTC_WKDAY, status);
+		return status;
+	}
+
+	/* now commit the write */
+	status = menelaus_write_reg(MENELAUS_RTC_UPDATE, RTC_UPDATE_EVERY);
+	if (status < 0)
+		dev_err(&the_menelaus->client->dev, "rtc commit time, err %d\n",
+				status);
+
+	return 0;
+}
+
+static int menelaus_read_alarm(struct device *dev, struct rtc_wkalrm *w)
+{
+	struct i2c_msg	msg[2];
+	char		regs[6];
+	int		status;
+
+	/* block read alarm registers */
+	regs[0] = MENELAUS_RTC_AL_SEC;
+
+	msg[0].addr = MENELAUS_I2C_ADDRESS;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = regs;
+
+	msg[1].addr = MENELAUS_I2C_ADDRESS;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = sizeof(regs);
+	msg[1].buf = regs;
+
+	status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
+	if (status != 2) {
+		dev_err(dev, "%s error %d\n", "alarm read", status);
+		return -EIO;
+	}
+
+	menelaus_to_time(regs, &w->time);
+
+	w->enabled = !!(the_menelaus->rtc_control & RTC_CTRL_AL_EN);
+
+	/* NOTE we *could* check if actually pending... */
+	w->pending = 0;
+
+	return 0;
+}
+
+static int menelaus_set_alarm(struct device *dev, struct rtc_wkalrm *w)
+{
+	int		status;
+
+	if (the_menelaus->client->irq <= 0 && w->enabled)
+		return -ENODEV;
+
+	/* clear previous alarm enable */
+	if (the_menelaus->rtc_control & RTC_CTRL_AL_EN) {
+		the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+		status = menelaus_write_reg(MENELAUS_RTC_CTRL,
+				the_menelaus->rtc_control);
+		if (status < 0)
+			return status;
+	}
+
+	/* write alarm registers */
+	status = time_to_menelaus(&w->time, MENELAUS_RTC_AL_SEC);
+	if (status < 0)
+		return status;
+
+	/* enable alarm if requested */
+	if (w->enabled) {
+		the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
+		status = menelaus_write_reg(MENELAUS_RTC_CTRL,
+				the_menelaus->rtc_control);
+	}
+
+	return status;
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static void menelaus_rtc_update_work(struct menelaus_chip *m)
+{
+	/* report 1/sec update */
+	local_irq_disable();
+	rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_UF);
+	local_irq_enable();
+}
+
+static int menelaus_ioctl(struct device *dev, unsigned cmd, unsigned long arg)
+{
+	int	status;
+
+	if (the_menelaus->client->irq <= 0)
+		return -ENOIOCTLCMD;
+
+	switch (cmd) {
+	/* alarm IRQ */
+	case RTC_AIE_ON:
+		if (the_menelaus->rtc_control & RTC_CTRL_AL_EN)
+			return 0;
+		the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
+		break;
+	case RTC_AIE_OFF:
+		if (!(the_menelaus->rtc_control & RTC_CTRL_AL_EN))
+			return 0;
+		the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+		break;
+	/* 1/second "update" IRQ */
+	case RTC_UIE_ON:
+		if (the_menelaus->uie)
+			return 0;
+		status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
+		status = menelaus_add_irq_work(MENELAUS_RTCTMR_IRQ,
+				menelaus_rtc_update_work);
+		if (status == 0)
+			the_menelaus->uie = 1;
+		return status;
+	case RTC_UIE_OFF:
+		if (!the_menelaus->uie)
+			return 0;
+		status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
+		if (status == 0)
+			the_menelaus->uie = 0;
+		return status;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
+}
+
+#else
+#define menelaus_ioctl	NULL
+#endif
+
+/* REVISIT no compensation register support ... */
+
+static const struct rtc_class_ops menelaus_rtc_ops = {
+	.ioctl			= menelaus_ioctl,
+	.read_time		= menelaus_read_time,
+	.set_time		= menelaus_set_time,
+	.read_alarm		= menelaus_read_alarm,
+	.set_alarm		= menelaus_set_alarm,
+};
+
+static void menelaus_rtc_alarm_work(struct menelaus_chip *m)
+{
+	/* report alarm */
+	local_irq_disable();
+	rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_AF);
+	local_irq_enable();
+
+	/* then disable it; alarms are oneshot */
+	the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+	menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
+}
+
+static inline void menelaus_rtc_init(struct menelaus_chip *m)
+{
+	int	alarm = (m->client->irq > 0);
+
+	/* assume 32KDETEN pin is pulled high */
+	if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) {
+		dev_dbg(&m->client->dev, "no 32k oscillator\n");
+		return;
+	}
+
+	/* support RTC alarm; it can issue wakeups */
+	if (alarm) {
+		if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ,
+				menelaus_rtc_alarm_work) < 0) {
+			dev_err(&m->client->dev, "can't handle RTC alarm\n");
+			return;
+		}
+		device_init_wakeup(&m->client->dev, 1);
+	}
+
+	/* be sure RTC is enabled; allow 1/sec irqs; leave 12hr mode alone */
+	m->rtc_control = menelaus_read_reg(MENELAUS_RTC_CTRL);
+	if (!(m->rtc_control & RTC_CTRL_RTC_EN)
+			|| (m->rtc_control & RTC_CTRL_AL_EN)
+			|| (m->rtc_control & RTC_CTRL_EVERY_MASK)) {
+		if (!(m->rtc_control & RTC_CTRL_RTC_EN)) {
+			dev_warn(&m->client->dev, "rtc clock needs setting\n");
+			m->rtc_control |= RTC_CTRL_RTC_EN;
+		}
+		m->rtc_control &= ~RTC_CTRL_EVERY_MASK;
+		m->rtc_control &= ~RTC_CTRL_AL_EN;
+		menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control);
+	}
+
+	m->rtc = rtc_device_register(DRIVER_NAME,
+			&m->client->dev,
+			&menelaus_rtc_ops, THIS_MODULE);
+	if (IS_ERR(m->rtc)) {
+		if (alarm) {
+			menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
+			device_init_wakeup(&m->client->dev, 0);
+		}
+		dev_err(&m->client->dev, "can't register RTC: %d\n",
+				(int) PTR_ERR(m->rtc));
+		the_menelaus->rtc = NULL;
+	}
+}
+
+#else
+
+static inline void menelaus_rtc_init(struct menelaus_chip *m)
+{
+	/* nothing */
+}
+
+#endif
+
+/*-----------------------------------------------------------------------*/
+
+static struct i2c_driver menelaus_i2c_driver;
+
+static int menelaus_probe(struct i2c_client *client)
+{
+	struct menelaus_chip	*menelaus;
+	int			rev = 0, val;
+	int			err = 0;
+	struct menelaus_platform_data *menelaus_pdata =
+					client->dev.platform_data;
+
+	if (the_menelaus) {
+		dev_dbg(&client->dev, "only one %s for now\n",
+				DRIVER_NAME);
+		return -ENODEV;
+	}
+
+	menelaus = kzalloc(sizeof *menelaus, GFP_KERNEL);
+	if (!menelaus)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, menelaus);
+
+	the_menelaus = menelaus;
+	menelaus->client = client;
+
+	/* If a true probe check the device */
+	rev = menelaus_read_reg(MENELAUS_REV);
+	if (rev < 0) {
+		pr_err("device not found");
+		err = -ENODEV;
+		goto fail1;
+	}
+
+	/* Ack and disable all Menelaus interrupts */
+	menelaus_write_reg(MENELAUS_INT_ACK1, 0xff);
+	menelaus_write_reg(MENELAUS_INT_ACK2, 0xff);
+	menelaus_write_reg(MENELAUS_INT_MASK1, 0xff);
+	menelaus_write_reg(MENELAUS_INT_MASK2, 0xff);
+	menelaus->mask1 = 0xff;
+	menelaus->mask2 = 0xff;
+
+	/* Set output buffer strengths */
+	menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73);
+
+	if (client->irq > 0) {
+		err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED,
+				  DRIVER_NAME, menelaus);
+		if (err) {
+			dev_dbg(&client->dev,  "can't get IRQ %d, err %d",
+					client->irq, err);
+			goto fail1;
+		}
+	}
+
+	mutex_init(&menelaus->lock);
+	INIT_WORK(&menelaus->work, menelaus_work);
+
+	pr_info("Menelaus rev %d.%d\n", rev >> 4, rev & 0x0f);
+
+	val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
+	if (val < 0)
+		goto fail2;
+	if (val & (1 << 7))
+		menelaus->vcore_hw_mode = 1;
+	else
+		menelaus->vcore_hw_mode = 0;
+
+	if (menelaus_pdata != NULL && menelaus_pdata->late_init != NULL) {
+		err = menelaus_pdata->late_init(&client->dev);
+		if (err < 0)
+			goto fail2;
+	}
+
+	menelaus_rtc_init(menelaus);
+
+	return 0;
+fail2:
+	free_irq(client->irq, menelaus);
+	flush_scheduled_work();
+fail1:
+	kfree(menelaus);
+	return err;
+}
+
+static int __exit menelaus_remove(struct i2c_client *client)
+{
+	struct menelaus_chip	*menelaus = i2c_get_clientdata(client);
+
+	free_irq(client->irq, menelaus);
+	kfree(menelaus);
+	i2c_set_clientdata(client, NULL);
+	the_menelaus = NULL;
+	return 0;
+}
+
+static struct i2c_driver menelaus_i2c_driver = {
+	.driver = {
+		.name		= DRIVER_NAME,
+	},
+	.probe		= menelaus_probe,
+	.remove		= __exit_p(menelaus_remove),
+};
+
+static int __init menelaus_init(void)
+{
+	int res;
+
+	res = i2c_add_driver(&menelaus_i2c_driver);
+	if (res < 0) {
+		pr_err("driver registration failed\n");
+		return res;
+	}
+
+	return 0;
+}
+
+static void __exit menelaus_exit(void)
+{
+	i2c_del_driver(&menelaus_i2c_driver);
+
+	/* FIXME: Shutdown menelaus parts that can be shut down */
+}
+
+MODULE_AUTHOR("Texas Instruments, Inc. (and others)");
+MODULE_DESCRIPTION("I2C interface for Menelaus.");
+MODULE_LICENSE("GPL");
+
+module_init(menelaus_init);
+module_exit(menelaus_exit);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index f429be8..a21f585 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1258,19 +1258,25 @@
 	set_bit(PC_DMA_RECOMMENDED, &pc->flags);
 }
 
-static int
+static void
 idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
 {
-	/*
-	 * just support eject for now, it would not be hard to make the
-	 * REQ_BLOCK_PC support fully-featured
-	 */
-	if (rq->cmd[0] != IDEFLOPPY_START_STOP_CMD)
-		return 1;
-
 	idefloppy_init_pc(pc);
+	pc->callback = &idefloppy_rw_callback;
 	memcpy(pc->c, rq->cmd, sizeof(pc->c));
-	return 0;
+	pc->rq = rq;
+	pc->b_count = rq->data_len;
+	if (rq->data_len && rq_data_dir(rq) == WRITE)
+		set_bit(PC_WRITING, &pc->flags);
+	pc->buffer = rq->data;
+	if (rq->bio)
+		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
+		
+	/*
+	 * possibly problematic, doesn't look like ide-floppy correctly
+	 * handled scattered requests if dma fails...
+	 */
+	pc->request_transfer = pc->buffer_size = rq->data_len;
 }
 
 /*
@@ -1317,10 +1323,7 @@
 		pc = (idefloppy_pc_t *) rq->buffer;
 	} else if (blk_pc_request(rq)) {
 		pc = idefloppy_next_pc_storage(drive);
-		if (idefloppy_blockpc_cmd(floppy, pc, rq)) {
-			idefloppy_do_end_request(drive, 0, 0);
-			return ide_stopped;
-		}
+		idefloppy_blockpc_cmd(floppy, pc, rq);
 	} else {
 		blk_dump_rq_flags(rq,
 			"ide-floppy: unsupported command in queue");
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index cc58013..5a4c5ea 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1073,14 +1073,14 @@
 		hwgroup->hwif->next = hwif;
 		spin_unlock_irq(&ide_lock);
 	} else {
-		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
+		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),
+					GFP_KERNEL | __GFP_ZERO,
 					hwif_to_node(hwif->drives[0].hwif));
 		if (!hwgroup)
 	       		goto out_up;
 
 		hwif->hwgroup = hwgroup;
 
-		memset(hwgroup, 0, sizeof(ide_hwgroup_t));
 		hwgroup->hwif     = hwif->next = hwif;
 		hwgroup->rq       = NULL;
 		hwgroup->handler  = NULL;
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index c948a5c..8cd7694 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1049,9 +1049,13 @@
 	unsigned long flags;
 	ide_driver_t *drv;
 	void __user *p = (void __user *)arg;
-	int err = 0, (*setfunc)(ide_drive_t *, int);
+	int err, (*setfunc)(ide_drive_t *, int);
 	u8 *val;
 
+	err = scsi_cmd_ioctl(file, bdev->bd_disk->queue, bdev->bd_disk, cmd, p);
+	if (err != -ENOTTY)
+		return err;
+
 	switch (cmd) {
 	case HDIO_GET_32BIT:	    val = &drive->io_32bit;	 goto read_val;
 	case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
@@ -1171,10 +1175,6 @@
 			return 0;
 		}
 
-		case CDROMEJECT:
-		case CDROMCLOSETRAY:
-			return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p);
-
 		case HDIO_GET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 0fc8c6e..ee45259 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -30,6 +30,7 @@
 #include <linux/moduleparam.h>
 #include <linux/bitops.h>
 #include <linux/kdev_t.h>
+#include <linux/freezer.h>
 #include <linux/suspend.h>
 #include <linux/kthread.h>
 #include <linux/preempt.h>
@@ -1128,8 +1129,6 @@
 	struct list_head tmp;
 	int may_schedule;
 
-	current->flags |= PF_NOFREEZE;
-
 	while (!kthread_should_stop()) {
 
 		INIT_LIST_HEAD(&tmp);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 51a1206..2ffd534 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1699,6 +1699,7 @@
 	unsigned int g, generation = 0;
 	int i, reset_cycles = 0;
 
+	set_freezable();
 	/* Setup our device-model entries */
 	nodemgr_create_host_dev_files(host);
 
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index bd686a2..20896d5 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -445,6 +445,7 @@
 
 static int gameport_thread(void *nothing)
 {
+	set_freezable();
 	do {
 		gameport_handle_event();
 		wait_event_interruptible(gameport_wait,
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index a8f3bc1..372ca49 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -384,6 +384,7 @@
 
 static int serio_thread(void *nothing)
 {
+	set_freezable();
 	do {
 		serio_handle_event();
 		wait_event_interruptible(serio_wait,
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index f0cbcdb..36f9440 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -292,6 +292,7 @@
 
 	sched_setscheduler(tsk, SCHED_FIFO, &param);
 
+	set_freezable();
 	while (!kthread_should_stop()) {
 		unsigned int x, y, p;
 		long timeout;
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 3e088c4..cf906c8 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -2,12 +2,10 @@
 # ISDN device configuration
 #
 
-menu "ISDN subsystem"
-	depends on !S390
-
-config ISDN
+menuconfig ISDN
 	tristate "ISDN support"
 	depends on NET
+	depends on !S390
 	---help---
 	  ISDN ("Integrated Services Digital Networks", called RNIS in France)
 	  is a special type of fully digital telephone service; it's mostly
@@ -21,9 +19,9 @@
 
 	  Select this option if you want your kernel to support ISDN.
 
+if ISDN
 
 menu "Old ISDN4Linux"
-	depends on NET && ISDN
 
 config ISDN_I4L
 	tristate "Old ISDN4Linux (deprecated)"
@@ -50,20 +48,21 @@
 endmenu
 
 comment "CAPI subsystem"
-	depends on NET && ISDN
 
 config ISDN_CAPI
 	tristate "CAPI2.0 support"
-	depends on ISDN
 	help
 	  This provides the CAPI (Common ISDN Application Programming
 	  Interface, a standard making it easy for programs to access ISDN
 	  hardware, see <http://www.capi.org/>.  This is needed for AVM's set
 	  of active ISDN controllers like B1, T1, M1.
 
+if ISDN_CAPI
+
 source "drivers/isdn/capi/Kconfig"
 
 source "drivers/isdn/hardware/Kconfig"
 
-endmenu
+endif # ISDN_CAPI
 
+endif # ISDN
diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig
index c92f9d7..e1afd60 100644
--- a/drivers/isdn/capi/Kconfig
+++ b/drivers/isdn/capi/Kconfig
@@ -3,7 +3,6 @@
 #
 config ISDN_DRV_AVMB1_VERBOSE_REASON
 	bool "Verbose reason code reporting"
-	depends on ISDN_CAPI
 	default y
 	help
 	  If you say Y here, the CAPI drivers will give verbose reasons for
@@ -12,7 +11,6 @@
 
 config CAPI_TRACE
 	bool "CAPI trace support"
-	depends on ISDN_CAPI
 	default y
 	help
 	  If you say Y here, the kernelcapi driver can make verbose traces
@@ -23,7 +21,7 @@
 
 config ISDN_CAPI_MIDDLEWARE
 	bool "CAPI2.0 Middleware support (EXPERIMENTAL)"
-	depends on ISDN_CAPI && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  This option will enhance the capabilities of the /dev/capi20
 	  interface.  It will provide a means of moving a data connection,
@@ -33,7 +31,6 @@
 
 config ISDN_CAPI_CAPI20
 	tristate "CAPI2.0 /dev/capi support"
-	depends on ISDN_CAPI
 	help
 	  This option will provide the CAPI 2.0 interface to userspace
 	  applications via /dev/capi20. Applications should use the
@@ -56,7 +53,7 @@
 
 config ISDN_CAPI_CAPIDRV
 	tristate "CAPI2.0 capidrv interface support"
-	depends on ISDN_CAPI && ISDN_I4L
+	depends on ISDN_I4L
 	help
 	  This option provides the glue code to hook up CAPI driven cards to
 	  the legacy isdn4linux link layer.  If you have a card which is
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 81661b8..f449dae 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -549,7 +549,7 @@
 		capimsg_setu8 (skb->data, 5, CAPI_REQ);
 		capimsg_setu16(skb->data, 6, mp->msgid++);
 		capimsg_setu32(skb->data, 8, mp->ncci);	/* NCCI */
-		capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
+		capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
 		capimsg_setu16(skb->data, 16, len);	/* Data length */
 		capimsg_setu16(skb->data, 18, datahandle);
 		capimsg_setu16(skb->data, 20, 0);	/* Flags */
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 3ed34f7..9f73bc2 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -258,7 +258,7 @@
 	if ((!ap) || (ap->release_in_progress))
 		return;
 
-	down(&ap->recv_sem);
+	mutex_lock(&ap->recv_mtx);
 	while ((skb = skb_dequeue(&ap->recv_queue))) {
 		if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
 			ap->nrecvdatapkt++;
@@ -267,7 +267,7 @@
 
 		ap->recv_message(ap, skb);
 	}
-	up(&ap->recv_sem);
+	mutex_unlock(&ap->recv_mtx);
 }
 
 void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb)
@@ -547,7 +547,7 @@
 	ap->nsentctlpkt = 0;
 	ap->nsentdatapkt = 0;
 	ap->callback = NULL;
-	init_MUTEX(&ap->recv_sem);
+	mutex_init(&ap->recv_mtx);
 	skb_queue_head_init(&ap->recv_queue);
 	INIT_WORK(&ap->recv_work, recv_handler);
 	ap->release_in_progress = 0;
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 31f4fd8..845a797 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -243,36 +243,15 @@
 
 // ---------------------------------------------------------------------------
 
-
-static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos)
-{
-	struct capi_driver *drv = NULL;
-	struct list_head *l;
-	loff_t i;
-
-	i = 0;
-	list_for_each(l, &capi_drivers) {
-		drv = list_entry(l, struct capi_driver, list);
-		if (i++ == pos)
-			return drv;
-	}
-	return NULL;
-}
-
 static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
 {
-	struct capi_driver *drv;
 	read_lock(&capi_drivers_list_lock);
-	drv = capi_driver_get_idx(*pos);
-	return drv;
+	return seq_list_start(&capi_drivers, *pos);
 }
 
 static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct capi_driver *drv = (struct capi_driver *)v;
-	++*pos;
-	if (drv->list.next == &capi_drivers) return NULL;
-	return list_entry(drv->list.next, struct capi_driver, list);
+	return seq_list_next(v, &capi_drivers, pos);
 }
 
 static void capi_driver_stop(struct seq_file *seq, void *v)
@@ -282,7 +261,8 @@
 
 static int capi_driver_show(struct seq_file *seq, void *v)
 {
-	struct capi_driver *drv = (struct capi_driver *)v;
+	struct capi_driver *drv = list_entry(v, struct capi_driver, list);
+
 	seq_printf(seq, "%-32s %s\n", drv->name, drv->revision);
 	return 0;
 }
diff --git a/drivers/isdn/hardware/Kconfig b/drivers/isdn/hardware/Kconfig
index 139f197..30d028d 100644
--- a/drivers/isdn/hardware/Kconfig
+++ b/drivers/isdn/hardware/Kconfig
@@ -2,7 +2,6 @@
 # ISDN hardware drivers
 #
 comment "CAPI hardware drivers"
-	depends on NET && ISDN && ISDN_CAPI
 
 source "drivers/isdn/hardware/avm/Kconfig"
 
diff --git a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig
index 29a32a8..5dbcbe3 100644
--- a/drivers/isdn/hardware/avm/Kconfig
+++ b/drivers/isdn/hardware/avm/Kconfig
@@ -2,23 +2,22 @@
 # ISDN AVM drivers
 #
 
-menu "Active AVM cards"
-	depends on NET && ISDN && ISDN_CAPI!=n
-
-config CAPI_AVM
-	bool "Support AVM cards"
+menuconfig CAPI_AVM
+	bool "Active AVM cards"
 	help
 	  Enable support for AVM active ISDN cards.
 
+if CAPI_AVM
+
 config ISDN_DRV_AVMB1_B1ISA
 	tristate "AVM B1 ISA support"
-	depends on CAPI_AVM && ISDN_CAPI && ISA
+	depends on ISA
 	help
 	  Enable support for the ISA version of the AVM B1 card.
 
 config ISDN_DRV_AVMB1_B1PCI
 	tristate "AVM B1 PCI support"
-	depends on CAPI_AVM && ISDN_CAPI && PCI
+	depends on PCI
 	help
 	  Enable support for the PCI version of the AVM B1 card.
 
@@ -30,14 +29,13 @@
 
 config ISDN_DRV_AVMB1_T1ISA
 	tristate "AVM T1/T1-B ISA support"
-	depends on CAPI_AVM && ISDN_CAPI && ISA
+	depends on ISA
 	help
 	  Enable support for the AVM T1 T1B card.
 	  Note: This is a PRI card and handle 30 B-channels.
 
 config ISDN_DRV_AVMB1_B1PCMCIA
 	tristate "AVM B1/M1/M2 PCMCIA support"
-	depends on CAPI_AVM && ISDN_CAPI
 	help
 	  Enable support for the PCMCIA version of the AVM B1 card.
 
@@ -50,17 +48,16 @@
 
 config ISDN_DRV_AVMB1_T1PCI
 	tristate "AVM T1/T1-B PCI support"
-	depends on CAPI_AVM && ISDN_CAPI && PCI
+	depends on PCI
 	help
 	  Enable support for the AVM T1 T1B card.
 	  Note: This is a PRI card and handle 30 B-channels.
 
 config ISDN_DRV_AVMB1_C4
 	tristate "AVM C4/C2 support"
-	depends on CAPI_AVM && ISDN_CAPI && PCI
+	depends on PCI
 	help
 	  Enable support for the AVM C4/C2 PCI cards.
 	  These cards handle 4/2 BRI ISDN lines (8/4 channels).
 
-endmenu
-
+endif # CAPI_AVM
diff --git a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig
index 01d4afd..6082b6a 100644
--- a/drivers/isdn/hardware/eicon/Kconfig
+++ b/drivers/isdn/hardware/eicon/Kconfig
@@ -2,52 +2,50 @@
 # ISDN DIVAS Eicon driver
 #
 
-menu "Active Eicon DIVA Server cards"
-	depends on NET && ISDN && ISDN_CAPI!=n
-
-config CAPI_EICON
-	bool "Support Eicon cards"
+menuconfig CAPI_EICON
+	bool "Active Eicon DIVA Server cards"
 	help
 	  Enable support for Eicon Networks active ISDN cards.
 
+if CAPI_EICON
+
 config ISDN_DIVAS
 	tristate "Support Eicon DIVA Server cards"
-	depends on CAPI_EICON && PROC_FS && PCI
+	depends on PROC_FS && PCI
 	help
 	  Say Y here if you have an Eicon Networks DIVA Server PCI ISDN card.
 	  In order to use this card, additional firmware is necessary, which
 	  has to be downloaded into the card using the divactrl utility.
 
+if ISDN_DIVAS
+
 config ISDN_DIVAS_BRIPCI
 	bool "DIVA Server BRI/PCI support"
-	depends on ISDN_DIVAS
 	help
 	  Enable support for DIVA Server BRI-PCI.
 
 config ISDN_DIVAS_PRIPCI
 	bool "DIVA Server PRI/PCI support"
-	depends on ISDN_DIVAS
 	help
 	  Enable support for DIVA Server PRI-PCI.
 
 config ISDN_DIVAS_DIVACAPI
 	tristate "DIVA CAPI2.0 interface support"
-	depends on ISDN_DIVAS && ISDN_CAPI
 	help
 	  You need this to provide the CAPI interface
 	  for DIVA Server cards.
 
 config ISDN_DIVAS_USERIDI
 	tristate "DIVA User-IDI interface support"
-	depends on ISDN_DIVAS
 	help
 	  Enable support for user-mode IDI interface.
 
 config ISDN_DIVAS_MAINT
 	tristate "DIVA Maint driver support"
-	depends on ISDN_DIVAS && m
+	depends on m
 	help
 	  Enable Divas Maintenance driver.
 
-endmenu
+endif # ISDN_DIVAS
 
+endif # CAPI_EICON
diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
index 4cbc68c..db87d51 100644
--- a/drivers/isdn/hardware/eicon/idifunc.c
+++ b/drivers/isdn/hardware/eicon/idifunc.c
@@ -106,6 +106,7 @@
 	} else {
 		DBG_ERR(("could not create user mode idi card %d",
 			 adapter_nr));
+		diva_os_free(0, card);
 	}
 }
 
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 8d53a7f..a43162c 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -361,11 +361,11 @@
 
 int nrcards;
 
-extern char *l1_revision;
-extern char *l2_revision;
-extern char *l3_revision;
-extern char *lli_revision;
-extern char *tei_revision;
+extern const char *l1_revision;
+extern const char *l2_revision;
+extern const char *l3_revision;
+extern const char *lli_revision;
+extern const char *tei_revision;
 
 char *HiSax_getrev(const char *revision)
 {
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 030d162..ad06f3c 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -451,6 +451,9 @@
 			spin_unlock_irqrestore(&cs->lock, flags);
 			return(0);
 		case CARD_RELEASE:
+			if (cs->hw.sedl.bus == SEDL_BUS_PCI)
+				/* disable all IRQ */
+				byteout(cs->hw.sedl.cfg_reg+ 5, 0);
 			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
 				spin_lock_irqsave(&cs->lock, flags);
 				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
@@ -468,6 +471,9 @@
 			return(0);
 		case CARD_INIT:
 			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->hw.sedl.bus == SEDL_BUS_PCI)
+				/* enable all IRQ */
+				byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
 			reset_sedlbauer(cs);
 			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
 				clear_pending_isac_ints(cs);
@@ -667,7 +673,7 @@
 		byteout(cs->hw.sedl.cfg_reg, 0xff);
 		byteout(cs->hw.sedl.cfg_reg, 0x00);
 		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+		byteout(cs->hw.sedl.cfg_reg+ 5, 0); /* disable all IRQ */
 		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
 		mdelay(2);
 		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 3ef567b..e91c187 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -86,7 +86,6 @@
 
 
 menu "ISDN feature submodules"
-	depends on ISDN
 
 config ISDN_DRV_LOOP
 	tristate "isdnloop support"
@@ -100,7 +99,7 @@
 
 config ISDN_DIVERSION
 	tristate "Support isdn diversion services"
-	depends on ISDN && ISDN_I4L
+	depends on ISDN_I4L
 	help
 	  This option allows you to use some supplementary diversion
 	  services in conjunction with the HiSax driver on an EURO/DSS1
@@ -120,13 +119,13 @@
 endmenu
 
 comment "ISDN4Linux hardware drivers"
-	depends on NET && ISDN && ISDN_I4L
+	depends on ISDN_I4L
 
 source "drivers/isdn/hisax/Kconfig"
 
 
 menu "Active cards"
-	depends on NET && ISDN && ISDN_I4L!=n
+	depends on ISDN_I4L!=n
 
 source "drivers/isdn/icn/Kconfig"
 
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index adfea3c..bc77c5e 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -248,21 +248,15 @@
 static int
 adb_probe_task(void *x)
 {
-	sigset_t blocked;
-
 	strcpy(current->comm, "kadbprobe");
 
-	sigfillset(&blocked);
-	sigprocmask(SIG_BLOCK, &blocked, NULL);
-	flush_signals(current);
-
 	printk(KERN_INFO "adb: starting probe task...\n");
 	do_adb_reset_bus();
 	printk(KERN_INFO "adb: finished probe task...\n");
-	
+
 	adb_probe_task_pid = 0;
 	up(&adb_probe_mutex);
-	
+
 	return 0;
 }
 
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index bd55e6a..f25685b 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -335,6 +335,7 @@
 {
 	struct thermostat* th = arg;
 
+	set_freezable();
 	while(!kthread_should_stop()) {
 		try_to_freeze();
 		msleep_interruptible(2000);
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 4fcb245..e18d265 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -92,6 +92,7 @@
 
 	DBG("wf: thread started\n");
 
+	set_freezable();
 	while(!kthread_should_stop()) {
 		if (time_after_eq(jiffies, next)) {
 			wf_notify(WF_EVENT_TICK, NULL);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 64bf3a8..531d4d1 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -2,19 +2,17 @@
 # Block device driver configuration
 #
 
-if BLOCK
-
-menu "Multi-device support (RAID and LVM)"
-
-config MD
+menuconfig MD
 	bool "Multiple devices driver support (RAID and LVM)"
+	depends on BLOCK
 	help
 	  Support multiple physical spindles through a single logical device.
 	  Required for RAID and logical volume management.
 
+if MD
+
 config BLK_DEV_MD
 	tristate "RAID support"
-	depends on MD
 	---help---
 	  This driver lets you combine several hard disk partitions into one
 	  logical block device. This can be used to simply append one
@@ -191,7 +189,6 @@
 
 config BLK_DEV_DM
 	tristate "Device mapper support"
-	depends on MD
 	---help---
 	  Device-mapper is a low level volume manager.  It works by allowing
 	  people to specify mappings for ranges of logical sectors.  Various
@@ -279,6 +276,4 @@
 
 	If unsure, say N.
 
-endmenu
-
-endif
+endif # MD
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 9620d45..927cb34 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -268,6 +268,31 @@
 			if (page->index == bitmap->file_pages-1)
 				size = roundup(bitmap->last_page_size,
 					       bdev_hardsect_size(rdev->bdev));
+			/* Just make sure we aren't corrupting data or
+			 * metadata
+			 */
+			if (bitmap->offset < 0) {
+				/* DATA  BITMAP METADATA  */
+				if (bitmap->offset
+				    + page->index * (PAGE_SIZE/512)
+				    + size/512 > 0)
+					/* bitmap runs in to metadata */
+					return -EINVAL;
+				if (rdev->data_offset + mddev->size*2
+				    > rdev->sb_offset*2 + bitmap->offset)
+					/* data runs in to bitmap */
+					return -EINVAL;
+			} else if (rdev->sb_offset*2 < rdev->data_offset) {
+				/* METADATA BITMAP DATA */
+				if (rdev->sb_offset*2
+				    + bitmap->offset
+				    + page->index*(PAGE_SIZE/512) + size/512
+				    > rdev->data_offset)
+					/* bitmap runs in to data */
+					return -EINVAL;
+			} else {
+				/* DATA METADATA BITMAP - no problems */
+			}
 			md_super_write(mddev, rdev,
 				       (rdev->sb_offset<<1) + bitmap->offset
 				       + page->index * (PAGE_SIZE/512),
@@ -280,32 +305,38 @@
 	return 0;
 }
 
+static void bitmap_file_kick(struct bitmap *bitmap);
 /*
  * write out a page to a file
  */
-static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+static void write_page(struct bitmap *bitmap, struct page *page, int wait)
 {
 	struct buffer_head *bh;
 
-	if (bitmap->file == NULL)
-		return write_sb_page(bitmap, page, wait);
+	if (bitmap->file == NULL) {
+		switch (write_sb_page(bitmap, page, wait)) {
+		case -EINVAL:
+			bitmap->flags |= BITMAP_WRITE_ERROR;
+		}
+	} else {
 
-	bh = page_buffers(page);
+		bh = page_buffers(page);
 
-	while (bh && bh->b_blocknr) {
-		atomic_inc(&bitmap->pending_writes);
-		set_buffer_locked(bh);
-		set_buffer_mapped(bh);
-		submit_bh(WRITE, bh);
-		bh = bh->b_this_page;
+		while (bh && bh->b_blocknr) {
+			atomic_inc(&bitmap->pending_writes);
+			set_buffer_locked(bh);
+			set_buffer_mapped(bh);
+			submit_bh(WRITE, bh);
+			bh = bh->b_this_page;
+		}
+
+		if (wait) {
+			wait_event(bitmap->write_wait,
+				   atomic_read(&bitmap->pending_writes)==0);
+		}
 	}
-
-	if (wait) {
-		wait_event(bitmap->write_wait,
-			   atomic_read(&bitmap->pending_writes)==0);
-		return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
-	}
-	return 0;
+	if (bitmap->flags & BITMAP_WRITE_ERROR)
+		bitmap_file_kick(bitmap);
 }
 
 static void end_bitmap_write(struct buffer_head *bh, int uptodate)
@@ -425,17 +456,17 @@
  */
 
 /* update the event counter and sync the superblock to disk */
-int bitmap_update_sb(struct bitmap *bitmap)
+void bitmap_update_sb(struct bitmap *bitmap)
 {
 	bitmap_super_t *sb;
 	unsigned long flags;
 
 	if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
-		return 0;
+		return;
 	spin_lock_irqsave(&bitmap->lock, flags);
 	if (!bitmap->sb_page) { /* no superblock */
 		spin_unlock_irqrestore(&bitmap->lock, flags);
-		return 0;
+		return;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
@@ -443,7 +474,7 @@
 	if (!bitmap->mddev->degraded)
 		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
 	kunmap_atomic(sb, KM_USER0);
-	return write_page(bitmap, bitmap->sb_page, 1);
+	write_page(bitmap, bitmap->sb_page, 1);
 }
 
 /* print out the bitmap file superblock */
@@ -572,20 +603,22 @@
 	MASK_UNSET
 };
 
-/* record the state of the bitmap in the superblock */
-static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
-				enum bitmap_mask_op op)
+/* record the state of the bitmap in the superblock.  Return the old value */
+static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
+			     enum bitmap_mask_op op)
 {
 	bitmap_super_t *sb;
 	unsigned long flags;
+	int old;
 
 	spin_lock_irqsave(&bitmap->lock, flags);
 	if (!bitmap->sb_page) { /* can't set the state */
 		spin_unlock_irqrestore(&bitmap->lock, flags);
-		return;
+		return 0;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
+	old = le32_to_cpu(sb->state) & bits;
 	switch (op) {
 		case MASK_SET: sb->state |= cpu_to_le32(bits);
 				break;
@@ -594,6 +627,7 @@
 		default: BUG();
 	}
 	kunmap_atomic(sb, KM_USER0);
+	return old;
 }
 
 /*
@@ -687,18 +721,23 @@
 {
 	char *path, *ptr = NULL;
 
-	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
-	bitmap_update_sb(bitmap);
+	if (bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET) == 0) {
+		bitmap_update_sb(bitmap);
 
-	if (bitmap->file) {
-		path = kmalloc(PAGE_SIZE, GFP_KERNEL);
-		if (path)
-			ptr = file_path(bitmap->file, path, PAGE_SIZE);
+		if (bitmap->file) {
+			path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+			if (path)
+				ptr = file_path(bitmap->file, path, PAGE_SIZE);
 
-		printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
-		       bmname(bitmap), ptr ? ptr : "");
+			printk(KERN_ALERT
+			      "%s: kicking failed bitmap file %s from array!\n",
+			      bmname(bitmap), ptr ? ptr : "");
 
-		kfree(path);
+			kfree(path);
+		} else
+			printk(KERN_ALERT
+			       "%s: disabling internal bitmap due to errors\n",
+			       bmname(bitmap));
 	}
 
 	bitmap_file_put(bitmap);
@@ -769,16 +808,15 @@
 /* this gets called when the md device is ready to unplug its underlying
  * (slave) device queues -- before we let any writes go down, we need to
  * sync the dirty pages of the bitmap file to disk */
-int bitmap_unplug(struct bitmap *bitmap)
+void bitmap_unplug(struct bitmap *bitmap)
 {
 	unsigned long i, flags;
 	int dirty, need_write;
 	struct page *page;
 	int wait = 0;
-	int err;
 
 	if (!bitmap)
-		return 0;
+		return;
 
 	/* look at each page to see if there are any set bits that need to be
 	 * flushed out to disk */
@@ -786,7 +824,7 @@
 		spin_lock_irqsave(&bitmap->lock, flags);
 		if (!bitmap->filemap) {
 			spin_unlock_irqrestore(&bitmap->lock, flags);
-			return 0;
+			return;
 		}
 		page = bitmap->filemap[i];
 		dirty = test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
@@ -798,7 +836,7 @@
 		spin_unlock_irqrestore(&bitmap->lock, flags);
 
 		if (dirty | need_write)
-			err = write_page(bitmap, page, 0);
+			write_page(bitmap, page, 0);
 	}
 	if (wait) { /* if any writes were performed, we need to wait on them */
 		if (bitmap->file)
@@ -809,7 +847,6 @@
 	}
 	if (bitmap->flags & BITMAP_WRITE_ERROR)
 		bitmap_file_kick(bitmap);
-	return 0;
 }
 
 static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
@@ -858,21 +895,21 @@
 			bmname(bitmap),
 			(unsigned long) i_size_read(file->f_mapping->host),
 			bytes + sizeof(bitmap_super_t));
-		goto out;
+		goto err;
 	}
 
 	ret = -ENOMEM;
 
 	bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
 	if (!bitmap->filemap)
-		goto out;
+		goto err;
 
 	/* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */
 	bitmap->filemap_attr = kzalloc(
 		roundup( DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
 		GFP_KERNEL);
 	if (!bitmap->filemap_attr)
-		goto out;
+		goto err;
 
 	oldindex = ~0L;
 
@@ -905,7 +942,7 @@
 			}
 			if (IS_ERR(page)) { /* read error */
 				ret = PTR_ERR(page);
-				goto out;
+				goto err;
 			}
 
 			oldindex = index;
@@ -920,11 +957,13 @@
 				memset(paddr + offset, 0xff,
 				       PAGE_SIZE - offset);
 				kunmap_atomic(paddr, KM_USER0);
-				ret = write_page(bitmap, page, 1);
-				if (ret) {
+				write_page(bitmap, page, 1);
+
+				ret = -EIO;
+				if (bitmap->flags & BITMAP_WRITE_ERROR) {
 					/* release, page not in filemap yet */
 					put_page(page);
-					goto out;
+					goto err;
 				}
 			}
 
@@ -956,11 +995,15 @@
 		md_wakeup_thread(bitmap->mddev->thread);
 	}
 
-out:
 	printk(KERN_INFO "%s: bitmap initialized from disk: "
-		"read %lu/%lu pages, set %lu bits, status: %d\n",
-		bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, ret);
+		"read %lu/%lu pages, set %lu bits\n",
+		bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt);
 
+	return 0;
+
+ err:
+	printk(KERN_INFO "%s: bitmap initialisation failed: %d\n",
+	       bmname(bitmap), ret);
 	return ret;
 }
 
@@ -997,19 +1040,18 @@
  *			out to disk
  */
 
-int bitmap_daemon_work(struct bitmap *bitmap)
+void bitmap_daemon_work(struct bitmap *bitmap)
 {
 	unsigned long j;
 	unsigned long flags;
 	struct page *page = NULL, *lastpage = NULL;
-	int err = 0;
 	int blocks;
 	void *paddr;
 
 	if (bitmap == NULL)
-		return 0;
+		return;
 	if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
-		return 0;
+		return;
 	bitmap->daemon_lastrun = jiffies;
 
 	for (j = 0; j < bitmap->chunks; j++) {
@@ -1032,14 +1074,8 @@
 					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
 
 				spin_unlock_irqrestore(&bitmap->lock, flags);
-				if (need_write) {
-					switch (write_page(bitmap, page, 0)) {
-					case 0:
-						break;
-					default:
-						bitmap_file_kick(bitmap);
-					}
-				}
+				if (need_write)
+					write_page(bitmap, page, 0);
 				continue;
 			}
 
@@ -1048,13 +1084,11 @@
 				if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
 					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
-					err = write_page(bitmap, lastpage, 0);
+					write_page(bitmap, lastpage, 0);
 				} else {
 					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 				}
-				if (err)
-					bitmap_file_kick(bitmap);
 			} else
 				spin_unlock_irqrestore(&bitmap->lock, flags);
 			lastpage = page;
@@ -1097,14 +1131,13 @@
 		if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
-			err = write_page(bitmap, lastpage, 0);
+			write_page(bitmap, lastpage, 0);
 		} else {
 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
 		}
 	}
 
-	return err;
 }
 
 static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1517,7 +1550,9 @@
 
 	mddev->thread->timeout = bitmap->daemon_sleep * HZ;
 
-	return bitmap_update_sb(bitmap);
+	bitmap_update_sb(bitmap);
+
+	return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
 
  error:
 	bitmap_free(bitmap);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index f4f7d35..846614e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -161,9 +161,7 @@
 {
 	kmem_cache_destroy(_tio_cache);
 	kmem_cache_destroy(_io_cache);
-
-	if (unregister_blkdev(_major, _name) < 0)
-		DMERR("unregister_blkdev failed");
+	unregister_blkdev(_major, _name);
 
 	_major = 0;
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 33beaa7..65ddc88 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1640,7 +1640,6 @@
 
 static void md_update_sb(mddev_t * mddev, int force_change)
 {
-	int err;
 	struct list_head *tmp;
 	mdk_rdev_t *rdev;
 	int sync_req;
@@ -1727,7 +1726,7 @@
 		"md: updating %s RAID superblock on device (in sync %d)\n",
 		mdname(mddev),mddev->in_sync);
 
-	err = bitmap_update_sb(mddev->bitmap);
+	bitmap_update_sb(mddev->bitmap);
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		char b[BDEVNAME_SIZE];
 		dprintk(KERN_INFO "md: ");
@@ -2073,9 +2072,11 @@
 		err = super_types[super_format].
 			load_super(rdev, NULL, super_minor);
 		if (err == -EINVAL) {
-			printk(KERN_WARNING 
-				"md: %s has invalid sb, not importing!\n",
-				bdevname(rdev->bdev,b));
+			printk(KERN_WARNING
+				"md: %s does not have a valid v%d.%d "
+			       "superblock, not importing!\n",
+				bdevname(rdev->bdev,b),
+			       super_format, super_minor);
 			goto abort_free;
 		}
 		if (err < 0) {
@@ -3174,13 +3175,33 @@
 	 * Drop all container device buffers, from now on
 	 * the only valid external interface is through the md
 	 * device.
-	 * Also find largest hardsector size
 	 */
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		if (test_bit(Faulty, &rdev->flags))
 			continue;
 		sync_blockdev(rdev->bdev);
 		invalidate_bdev(rdev->bdev);
+
+		/* perform some consistency tests on the device.
+		 * We don't want the data to overlap the metadata,
+		 * Internal Bitmap issues has handled elsewhere.
+		 */
+		if (rdev->data_offset < rdev->sb_offset) {
+			if (mddev->size &&
+			    rdev->data_offset + mddev->size*2
+			    > rdev->sb_offset*2) {
+				printk("md: %s: data overlaps metadata\n",
+				       mdname(mddev));
+				return -EINVAL;
+			}
+		} else {
+			if (rdev->sb_offset*2 + rdev->sb_size/512
+			    > rdev->data_offset) {
+				printk("md: %s: metadata overlaps data\n",
+				       mdname(mddev));
+				return -EINVAL;
+			}
+		}
 	}
 
 	md_probe(mddev->unit, NULL, NULL);
@@ -4642,7 +4663,6 @@
 	 * many dirty RAID5 blocks.
 	 */
 
-	current->flags |= PF_NOFREEZE;
 	allow_signal(SIGKILL);
 	while (!kthread_should_stop()) {
 
@@ -5090,7 +5110,7 @@
 	mdk_rdev_t * rdev;
 	struct list_head *tmp;
 	int idle;
-	unsigned long curr_events;
+	long curr_events;
 
 	idle = 1;
 	ITERATE_RDEV(mddev,rdev,tmp) {
@@ -5098,20 +5118,29 @@
 		curr_events = disk_stat_read(disk, sectors[0]) + 
 				disk_stat_read(disk, sectors[1]) - 
 				atomic_read(&disk->sync_io);
-		/* The difference between curr_events and last_events
-		 * will be affected by any new non-sync IO (making
-		 * curr_events bigger) and any difference in the amount of
-		 * in-flight syncio (making current_events bigger or smaller)
-		 * The amount in-flight is currently limited to
-		 * 32*64K in raid1/10 and 256*PAGE_SIZE in raid5/6
-		 * which is at most 4096 sectors.
-		 * These numbers are fairly fragile and should be made
-		 * more robust, probably by enforcing the
-		 * 'window size' that md_do_sync sort-of uses.
+		/* sync IO will cause sync_io to increase before the disk_stats
+		 * as sync_io is counted when a request starts, and
+		 * disk_stats is counted when it completes.
+		 * So resync activity will cause curr_events to be smaller than
+		 * when there was no such activity.
+		 * non-sync IO will cause disk_stat to increase without
+		 * increasing sync_io so curr_events will (eventually)
+		 * be larger than it was before.  Once it becomes
+		 * substantially larger, the test below will cause
+		 * the array to appear non-idle, and resync will slow
+		 * down.
+		 * If there is a lot of outstanding resync activity when
+		 * we set last_event to curr_events, then all that activity
+		 * completing might cause the array to appear non-idle
+		 * and resync will be slowed down even though there might
+		 * not have been non-resync activity.  This will only
+		 * happen once though.  'last_events' will soon reflect
+		 * the state where there is little or no outstanding
+		 * resync requests, and further resync activity will
+		 * always make curr_events less than last_events.
 		 *
-		 * Note: the following is an unsigned comparison.
 		 */
-		if ((long)curr_events - (long)rdev->last_events > 4096) {
+		if (curr_events - rdev->last_events > 4096) {
 			rdev->last_events = curr_events;
 			idle = 0;
 		}
@@ -5772,7 +5801,7 @@
 	for (i = 0; i < dev_cnt; i++) {
 		dev_t dev = detected_devices[i];
 
-		rdev = md_import_device(dev,0, 0);
+		rdev = md_import_device(dev,0, 90);
 		if (IS_ERR(rdev))
 			continue;
 
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 46677d7..00c78b7 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1526,8 +1526,7 @@
 			blk_remove_plug(mddev->queue);
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			/* flush any pending bitmap writes to disk before proceeding w/ I/O */
-			if (bitmap_unplug(mddev->bitmap) != 0)
-				printk("%s: bitmap file write failed!\n", mdname(mddev));
+			bitmap_unplug(mddev->bitmap);
 
 			while (bio) { /* submit pending writes */
 				struct bio *next = bio->bi_next;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9eb66c1..a95ada1 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1510,8 +1510,7 @@
 			blk_remove_plug(mddev->queue);
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			/* flush any pending bitmap writes to disk before proceeding w/ I/O */
-			if (bitmap_unplug(mddev->bitmap) != 0)
-				printk("%s: bitmap file write failed!\n", mdname(mddev));
+			bitmap_unplug(mddev->bitmap);
 
 			while (bio) { /* submit pending writes */
 				struct bio *next = bio->bi_next;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index f4e4ca2..b6c7f66 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -523,6 +523,7 @@
 
 	dvb_frontend_init(fe);
 
+	set_freezable();
 	while (1) {
 		up(&fepriv->sem);	    /* is locked when we enter the thread... */
 restart:
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 259ea08..1cc2d28 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -906,6 +906,7 @@
 	u32 mode = 0;
 
 	dprintk("cx88: tvaudio thread started\n");
+	set_freezable();
 	for (;;) {
 		msleep_interruptible(1000);
 		if (kthread_should_stop())
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index e1821eb..d5ee262 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/freezer.h>
 #include <linux/videodev.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
@@ -468,6 +469,7 @@
 
 
 	v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
 		msp_sleep(state, -1);
@@ -646,7 +648,7 @@
 	int val, i, std, count;
 
 	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
-
+	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
 		msp_sleep(state,-1);
@@ -940,7 +942,7 @@
 	int val, i;
 
 	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
-
+	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
 		msp_sleep(state, -1);
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index c9bf9db..9da338d 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -271,7 +271,7 @@
 	struct CHIPDESC  *desc = chiplist + chip->type;
 
 	v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
-
+	set_freezable();
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (!kthread_should_stop())
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index fcc5467..e617925 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -47,6 +47,7 @@
 	int err;
 
 	dprintk("dvb thread started\n");
+	set_freezable();
 	videobuf_read_start(&dvb->dvbq);
 
 	for (;;) {
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index f7e1d19..3ef4d01 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -573,6 +573,7 @@
 	dprintk(1,"thread started\n");
 
 	mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+	set_freezable();
 
 	for (;;) {
 		vivi_sleep(dma_q);
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index f4ac21e..5afa0e3 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -1,9 +1,6 @@
 
-menu "I2O device support"
-	depends on PCI
-
-config I2O
-	tristate "I2O support"
+menuconfig I2O
+	tristate "I2O device support"
 	depends on PCI
 	---help---
 	  The Intelligent Input/Output (I2O) architecture allows hardware
@@ -25,9 +22,10 @@
 
 	  If unsure, say N.
 
+if I2O
+
 config I2O_LCT_NOTIFY_ON_CHANGES
 	bool "Enable LCT notification"
-	depends on I2O
 	default y
 	---help---
 	  Only say N here if you have a I2O controller from SUN. The SUN
@@ -39,7 +37,6 @@
 
 config I2O_EXT_ADAPTEC
 	bool "Enable Adaptec extensions"
-	depends on I2O
 	default y
 	---help---
 	  Say Y for support of raidutils for Adaptec I2O controllers. You also
@@ -57,7 +54,7 @@
 
 config I2O_CONFIG
 	tristate "I2O Configuration support"
-	depends on I2O
+	depends on VIRT_TO_BUS
 	---help---
 	  Say Y for support of the configuration interface for the I2O adapters.
 	  If you have a RAID controller from Adaptec and you want to use the
@@ -78,7 +75,6 @@
 
 config I2O_BUS
 	tristate "I2O Bus Adapter OSM"
-	depends on I2O
 	---help---
 	  Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
 	  provides access to the busses on the I2O controller. The main purpose
@@ -89,7 +85,7 @@
 
 config I2O_BLOCK
 	tristate "I2O Block OSM"
-	depends on I2O && BLOCK
+	depends on BLOCK
 	---help---
 	  Include support for the I2O Block OSM. The Block OSM presents disk
 	  and other structured block devices to the operating system. If you
@@ -102,7 +98,7 @@
 
 config I2O_SCSI
 	tristate "I2O SCSI OSM"
-	depends on I2O && SCSI
+	depends on SCSI
 	---help---
 	  Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
 	  I2O controller. You can use both the SCSI and Block OSM together if
@@ -114,7 +110,6 @@
 
 config I2O_PROC
 	tristate "I2O /proc support"
-	depends on I2O
 	---help---
 	  If you say Y here and to "/proc file system support", you will be
 	  able to read I2O related information from the virtual directory
@@ -123,5 +118,4 @@
 	  To compile this support as a module, choose M here: the
 	  module will be called i2o_proc.
 
-endmenu
-
+endif # I2O
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 8abe45e..ce62d8b 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -24,7 +24,7 @@
 	if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
 		return;		// No status in this reply
 
-	printk(KERN_DEBUG "%s%s: ", severity, str);
+	printk("%s%s: ", severity, str);
 
 	if (cmd < 0x1F)		// Utility cmd
 		i2o_report_util_cmd(cmd);
@@ -32,7 +32,7 @@
 	else if (cmd >= 0xA0 && cmd <= 0xEF)	// Executive cmd
 		i2o_report_exec_cmd(cmd);
 	else
-		printk(KERN_DEBUG "Cmd = %0#2x, ", cmd);	// Other cmds
+		printk("Cmd = %0#2x, ", cmd);	// Other cmds
 
 	if (msg[0] & MSG_FAIL) {
 		i2o_report_fail_status(req_status, msg);
@@ -44,7 +44,7 @@
 	if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF))
 		i2o_report_common_dsc(detailed_status);
 	else
-		printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n",
+		printk(" / DetailedStatus = %0#4x.\n",
 		       detailed_status);
 }
 
@@ -89,10 +89,10 @@
 	};
 
 	if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
-		printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
+		printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
 		       req_status);
 	else
-		printk(KERN_DEBUG "TRANSPORT_%s.\n",
+		printk("TRANSPORT_%s.\n",
 		       FAIL_STATUS[req_status & 0x0F]);
 
 	/* Dump some details */
@@ -104,7 +104,7 @@
 	printk(KERN_ERR "  FailingHostUnit = 0x%04X,  FailingIOP = 0x%03X\n",
 	       msg[5] >> 16, msg[5] & 0xFFF);
 
-	printk(KERN_ERR "  Severity:  0x%02X ", (msg[4] >> 16) & 0xFF);
+	printk(KERN_ERR "  Severity:  0x%02X\n", (msg[4] >> 16) & 0xFF);
 	if (msg[4] & (1 << 16))
 		printk(KERN_DEBUG "(FormatError), "
 		       "this msg can never be delivered/processed.\n");
@@ -142,9 +142,9 @@
 	};
 
 	if (req_status >= ARRAY_SIZE(REPLY_STATUS))
-		printk(KERN_DEBUG "RequestStatus = %0#2x", req_status);
+		printk("RequestStatus = %0#2x", req_status);
 	else
-		printk(KERN_DEBUG "%s", REPLY_STATUS[req_status]);
+		printk("%s", REPLY_STATUS[req_status]);
 }
 
 /*
@@ -187,10 +187,10 @@
 	};
 
 	if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE)
-		printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n",
+		printk(" / DetailedStatus = %0#4x.\n",
 		       detailed_status);
 	else
-		printk(KERN_DEBUG " / %s.\n", COMMON_DSC[detailed_status]);
+		printk(" / %s.\n", COMMON_DSC[detailed_status]);
 }
 
 /*
@@ -200,49 +200,49 @@
 {
 	switch (cmd) {
 	case I2O_CMD_UTIL_NOP:
-		printk(KERN_DEBUG "UTIL_NOP, ");
+		printk("UTIL_NOP, ");
 		break;
 	case I2O_CMD_UTIL_ABORT:
-		printk(KERN_DEBUG "UTIL_ABORT, ");
+		printk("UTIL_ABORT, ");
 		break;
 	case I2O_CMD_UTIL_CLAIM:
-		printk(KERN_DEBUG "UTIL_CLAIM, ");
+		printk("UTIL_CLAIM, ");
 		break;
 	case I2O_CMD_UTIL_RELEASE:
-		printk(KERN_DEBUG "UTIL_CLAIM_RELEASE, ");
+		printk("UTIL_CLAIM_RELEASE, ");
 		break;
 	case I2O_CMD_UTIL_CONFIG_DIALOG:
-		printk(KERN_DEBUG "UTIL_CONFIG_DIALOG, ");
+		printk("UTIL_CONFIG_DIALOG, ");
 		break;
 	case I2O_CMD_UTIL_DEVICE_RESERVE:
-		printk(KERN_DEBUG "UTIL_DEVICE_RESERVE, ");
+		printk("UTIL_DEVICE_RESERVE, ");
 		break;
 	case I2O_CMD_UTIL_DEVICE_RELEASE:
-		printk(KERN_DEBUG "UTIL_DEVICE_RELEASE, ");
+		printk("UTIL_DEVICE_RELEASE, ");
 		break;
 	case I2O_CMD_UTIL_EVT_ACK:
-		printk(KERN_DEBUG "UTIL_EVENT_ACKNOWLEDGE, ");
+		printk("UTIL_EVENT_ACKNOWLEDGE, ");
 		break;
 	case I2O_CMD_UTIL_EVT_REGISTER:
-		printk(KERN_DEBUG "UTIL_EVENT_REGISTER, ");
+		printk("UTIL_EVENT_REGISTER, ");
 		break;
 	case I2O_CMD_UTIL_LOCK:
-		printk(KERN_DEBUG "UTIL_LOCK, ");
+		printk("UTIL_LOCK, ");
 		break;
 	case I2O_CMD_UTIL_LOCK_RELEASE:
-		printk(KERN_DEBUG "UTIL_LOCK_RELEASE, ");
+		printk("UTIL_LOCK_RELEASE, ");
 		break;
 	case I2O_CMD_UTIL_PARAMS_GET:
-		printk(KERN_DEBUG "UTIL_PARAMS_GET, ");
+		printk("UTIL_PARAMS_GET, ");
 		break;
 	case I2O_CMD_UTIL_PARAMS_SET:
-		printk(KERN_DEBUG "UTIL_PARAMS_SET, ");
+		printk("UTIL_PARAMS_SET, ");
 		break;
 	case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY:
-		printk(KERN_DEBUG "UTIL_REPLY_FAULT_NOTIFY, ");
+		printk("UTIL_REPLY_FAULT_NOTIFY, ");
 		break;
 	default:
-		printk(KERN_DEBUG "Cmd = %0#2x, ", cmd);
+		printk("Cmd = %0#2x, ", cmd);
 	}
 }
 
@@ -253,106 +253,106 @@
 {
 	switch (cmd) {
 	case I2O_CMD_ADAPTER_ASSIGN:
-		printk(KERN_DEBUG "EXEC_ADAPTER_ASSIGN, ");
+		printk("EXEC_ADAPTER_ASSIGN, ");
 		break;
 	case I2O_CMD_ADAPTER_READ:
-		printk(KERN_DEBUG "EXEC_ADAPTER_READ, ");
+		printk("EXEC_ADAPTER_READ, ");
 		break;
 	case I2O_CMD_ADAPTER_RELEASE:
-		printk(KERN_DEBUG "EXEC_ADAPTER_RELEASE, ");
+		printk("EXEC_ADAPTER_RELEASE, ");
 		break;
 	case I2O_CMD_BIOS_INFO_SET:
-		printk(KERN_DEBUG "EXEC_BIOS_INFO_SET, ");
+		printk("EXEC_BIOS_INFO_SET, ");
 		break;
 	case I2O_CMD_BOOT_DEVICE_SET:
-		printk(KERN_DEBUG "EXEC_BOOT_DEVICE_SET, ");
+		printk("EXEC_BOOT_DEVICE_SET, ");
 		break;
 	case I2O_CMD_CONFIG_VALIDATE:
-		printk(KERN_DEBUG "EXEC_CONFIG_VALIDATE, ");
+		printk("EXEC_CONFIG_VALIDATE, ");
 		break;
 	case I2O_CMD_CONN_SETUP:
-		printk(KERN_DEBUG "EXEC_CONN_SETUP, ");
+		printk("EXEC_CONN_SETUP, ");
 		break;
 	case I2O_CMD_DDM_DESTROY:
-		printk(KERN_DEBUG "EXEC_DDM_DESTROY, ");
+		printk("EXEC_DDM_DESTROY, ");
 		break;
 	case I2O_CMD_DDM_ENABLE:
-		printk(KERN_DEBUG "EXEC_DDM_ENABLE, ");
+		printk("EXEC_DDM_ENABLE, ");
 		break;
 	case I2O_CMD_DDM_QUIESCE:
-		printk(KERN_DEBUG "EXEC_DDM_QUIESCE, ");
+		printk("EXEC_DDM_QUIESCE, ");
 		break;
 	case I2O_CMD_DDM_RESET:
-		printk(KERN_DEBUG "EXEC_DDM_RESET, ");
+		printk("EXEC_DDM_RESET, ");
 		break;
 	case I2O_CMD_DDM_SUSPEND:
-		printk(KERN_DEBUG "EXEC_DDM_SUSPEND, ");
+		printk("EXEC_DDM_SUSPEND, ");
 		break;
 	case I2O_CMD_DEVICE_ASSIGN:
-		printk(KERN_DEBUG "EXEC_DEVICE_ASSIGN, ");
+		printk("EXEC_DEVICE_ASSIGN, ");
 		break;
 	case I2O_CMD_DEVICE_RELEASE:
-		printk(KERN_DEBUG "EXEC_DEVICE_RELEASE, ");
+		printk("EXEC_DEVICE_RELEASE, ");
 		break;
 	case I2O_CMD_HRT_GET:
-		printk(KERN_DEBUG "EXEC_HRT_GET, ");
+		printk("EXEC_HRT_GET, ");
 		break;
 	case I2O_CMD_ADAPTER_CLEAR:
-		printk(KERN_DEBUG "EXEC_IOP_CLEAR, ");
+		printk("EXEC_IOP_CLEAR, ");
 		break;
 	case I2O_CMD_ADAPTER_CONNECT:
-		printk(KERN_DEBUG "EXEC_IOP_CONNECT, ");
+		printk("EXEC_IOP_CONNECT, ");
 		break;
 	case I2O_CMD_ADAPTER_RESET:
-		printk(KERN_DEBUG "EXEC_IOP_RESET, ");
+		printk("EXEC_IOP_RESET, ");
 		break;
 	case I2O_CMD_LCT_NOTIFY:
-		printk(KERN_DEBUG "EXEC_LCT_NOTIFY, ");
+		printk("EXEC_LCT_NOTIFY, ");
 		break;
 	case I2O_CMD_OUTBOUND_INIT:
-		printk(KERN_DEBUG "EXEC_OUTBOUND_INIT, ");
+		printk("EXEC_OUTBOUND_INIT, ");
 		break;
 	case I2O_CMD_PATH_ENABLE:
-		printk(KERN_DEBUG "EXEC_PATH_ENABLE, ");
+		printk("EXEC_PATH_ENABLE, ");
 		break;
 	case I2O_CMD_PATH_QUIESCE:
-		printk(KERN_DEBUG "EXEC_PATH_QUIESCE, ");
+		printk("EXEC_PATH_QUIESCE, ");
 		break;
 	case I2O_CMD_PATH_RESET:
-		printk(KERN_DEBUG "EXEC_PATH_RESET, ");
+		printk("EXEC_PATH_RESET, ");
 		break;
 	case I2O_CMD_STATIC_MF_CREATE:
-		printk(KERN_DEBUG "EXEC_STATIC_MF_CREATE, ");
+		printk("EXEC_STATIC_MF_CREATE, ");
 		break;
 	case I2O_CMD_STATIC_MF_RELEASE:
-		printk(KERN_DEBUG "EXEC_STATIC_MF_RELEASE, ");
+		printk("EXEC_STATIC_MF_RELEASE, ");
 		break;
 	case I2O_CMD_STATUS_GET:
-		printk(KERN_DEBUG "EXEC_STATUS_GET, ");
+		printk("EXEC_STATUS_GET, ");
 		break;
 	case I2O_CMD_SW_DOWNLOAD:
-		printk(KERN_DEBUG "EXEC_SW_DOWNLOAD, ");
+		printk("EXEC_SW_DOWNLOAD, ");
 		break;
 	case I2O_CMD_SW_UPLOAD:
-		printk(KERN_DEBUG "EXEC_SW_UPLOAD, ");
+		printk("EXEC_SW_UPLOAD, ");
 		break;
 	case I2O_CMD_SW_REMOVE:
-		printk(KERN_DEBUG "EXEC_SW_REMOVE, ");
+		printk("EXEC_SW_REMOVE, ");
 		break;
 	case I2O_CMD_SYS_ENABLE:
-		printk(KERN_DEBUG "EXEC_SYS_ENABLE, ");
+		printk("EXEC_SYS_ENABLE, ");
 		break;
 	case I2O_CMD_SYS_MODIFY:
-		printk(KERN_DEBUG "EXEC_SYS_MODIFY, ");
+		printk("EXEC_SYS_MODIFY, ");
 		break;
 	case I2O_CMD_SYS_QUIESCE:
-		printk(KERN_DEBUG "EXEC_SYS_QUIESCE, ");
+		printk("EXEC_SYS_QUIESCE, ");
 		break;
 	case I2O_CMD_SYS_TAB_SET:
-		printk(KERN_DEBUG "EXEC_SYS_TAB_SET, ");
+		printk("EXEC_SYS_TAB_SET, ");
 		break;
 	default:
-		printk(KERN_DEBUG "Cmd = %#02x, ", cmd);
+		printk("Cmd = %#02x, ", cmd);
 	}
 }
 
@@ -361,28 +361,28 @@
 	printk(KERN_INFO "%s: State = ", c->name);
 	switch (((i2o_status_block *) c->status_block.virt)->iop_state) {
 	case 0x01:
-		printk(KERN_DEBUG "INIT\n");
+		printk("INIT\n");
 		break;
 	case 0x02:
-		printk(KERN_DEBUG "RESET\n");
+		printk("RESET\n");
 		break;
 	case 0x04:
-		printk(KERN_DEBUG "HOLD\n");
+		printk("HOLD\n");
 		break;
 	case 0x05:
-		printk(KERN_DEBUG "READY\n");
+		printk("READY\n");
 		break;
 	case 0x08:
-		printk(KERN_DEBUG "OPERATIONAL\n");
+		printk("OPERATIONAL\n");
 		break;
 	case 0x10:
-		printk(KERN_DEBUG "FAILED\n");
+		printk("FAILED\n");
 		break;
 	case 0x11:
-		printk(KERN_DEBUG "FAULTED\n");
+		printk("FAULTED\n");
 		break;
 	default:
-		printk(KERN_DEBUG "%x (unknown !!)\n",
+		printk("%x (unknown !!)\n",
 		       ((i2o_status_block *) c->status_block.virt)->iop_state);
 	}
 };
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 611adc3..489d7c5 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -62,7 +62,7 @@
 {
 	int rc = 0;
 
-	down(&dev->lock);
+	mutex_lock(&dev->lock);
 
 	rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
 	if (!rc)
@@ -72,7 +72,7 @@
 		pr_debug("i2o: claim of device %d failed %d\n",
 			 dev->lct_data.tid, rc);
 
-	up(&dev->lock);
+	mutex_unlock(&dev->lock);
 
 	return rc;
 }
@@ -96,7 +96,7 @@
 	int tries;
 	int rc = 0;
 
-	down(&dev->lock);
+	mutex_lock(&dev->lock);
 
 	/*
 	 *      If the controller takes a nonblocking approach to
@@ -118,7 +118,7 @@
 		pr_debug("i2o: claim release of device %d failed %d\n",
 			 dev->lct_data.tid, rc);
 
-	up(&dev->lock);
+	mutex_unlock(&dev->lock);
 
 	return rc;
 }
@@ -198,7 +198,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&dev->list);
-	init_MUTEX(&dev->lock);
+	mutex_init(&dev->lock);
 
 	dev->device.bus = &i2o_bus_type;
 	dev->device.release = &i2o_device_release;
@@ -326,7 +326,7 @@
 	u16 table_size;
 	u32 buf;
 
-	down(&c->lct_lock);
+	mutex_lock(&c->lct_lock);
 
 	kfree(c->lct);
 
@@ -335,7 +335,7 @@
 
 	lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
 	if (!lct) {
-		up(&c->lct_lock);
+		mutex_unlock(&c->lct_lock);
 		return -ENOMEM;
 	}
 
@@ -408,7 +408,7 @@
 			i2o_device_remove(dev);
 	}
 
-	up(&c->lct_lock);
+	mutex_unlock(&c->lct_lock);
 
 	return 0;
 }
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 5278aad..8c83ee3 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -131,8 +131,10 @@
 	int rc = 0;
 
 	wait = i2o_exec_wait_alloc();
-	if (!wait)
+	if (!wait) {
+		i2o_msg_nop(c, msg);
 		return -ENOMEM;
+	}
 
 	if (tcntxt == 0xffffffff)
 		tcntxt = 0x80000000;
@@ -337,6 +339,8 @@
 	rc = device_create_file(dev, &dev_attr_product_id);
 	if (rc) goto err_vid;
 
+	i2o_dev->iop->exec = i2o_dev;
+
 	return 0;
 
 err_vid:
@@ -537,7 +541,7 @@
 	struct device *dev;
 	struct i2o_message *msg;
 
-	down(&c->lct_lock);
+	mutex_lock(&c->lct_lock);
 
 	dev = &c->pdev->dev;
 
@@ -561,7 +565,7 @@
 
 	i2o_msg_post(c, msg);
 
-	up(&c->lct_lock);
+	mutex_unlock(&c->lct_lock);
 
 	return 0;
 };
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index b17c4b2..64a52bd 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -215,7 +215,7 @@
 	struct i2o_message *msg;
 
 	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
-	if (IS_ERR(msg) == I2O_QUEUE_EMPTY)
+	if (IS_ERR(msg))
 		return PTR_ERR(msg);
 
 	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 8ba275a..84e046e 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -554,8 +554,6 @@
 		return -ENXIO;
 	}
 
-	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
-
 	sb = c->status_block.virt;
 
 	if (get_user(size, &user_msg[0])) {
@@ -573,24 +571,30 @@
 
 	size <<= 2;		// Convert to bytes
 
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
+
+	rcode = -EFAULT;
 	/* Copy in the user's I2O command */
 	if (copy_from_user(msg, user_msg, size)) {
 		osm_warn("unable to copy user message\n");
-		return -EFAULT;
+		goto out;
 	}
 	i2o_dump_message(msg);
 
 	if (get_user(reply_size, &user_reply[0]) < 0)
-		return -EFAULT;
+		goto out;
 
 	reply_size >>= 16;
 	reply_size <<= 2;
 
+	rcode = -ENOMEM;
 	reply = kzalloc(reply_size, GFP_KERNEL);
 	if (!reply) {
 		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
 		       c->name);
-		return -ENOMEM;
+		goto out;
 	}
 
 	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -661,13 +665,14 @@
 	}
 
 	rcode = i2o_msg_post_wait(c, msg, 60);
+	msg = NULL;
 	if (rcode) {
 		reply[4] = ((u32) rcode) << 24;
 		goto sg_list_cleanup;
 	}
 
 	if (sg_offset) {
-		u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
+		u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
 		/* Copy back the Scatter Gather buffers back to user space */
 		u32 j;
 		// TODO 64bit fix
@@ -675,7 +680,7 @@
 		int sg_size;
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
+		memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
@@ -684,7 +689,7 @@
 		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
-		if (copy_from_user(msg, user_msg, size)) {
+		if (copy_from_user(rmsg, user_msg, size)) {
 			rcode = -EFAULT;
 			goto sg_list_cleanup;
 		}
@@ -692,7 +697,7 @@
 		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 
 		// TODO 64bit fix
-		sg = (struct sg_simple_element *)(msg + sg_offset);
+		sg = (struct sg_simple_element *)(rmsg + sg_offset);
 		for (j = 0; j < sg_count; j++) {
 			/* Copy out the SG list to user's buffer if necessary */
 			if (!
@@ -714,7 +719,7 @@
 		}
 	}
 
-      sg_list_cleanup:
+sg_list_cleanup:
 	/* Copy back the reply to user space */
 	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
@@ -723,7 +728,6 @@
 			       "%s: Could not copy message context FROM user\n",
 			       c->name);
 			rcode = -EFAULT;
-			goto sg_list_cleanup;
 		}
 		if (copy_to_user(user_reply, reply, reply_size)) {
 			printk(KERN_WARNING
@@ -731,12 +735,14 @@
 			rcode = -EFAULT;
 		}
 	}
-
 	for (i = 0; i < sg_index; i++)
 		i2o_dma_free(&c->pdev->dev, &sg_list[i]);
 
-      cleanup:
+cleanup:
 	kfree(reply);
+out:
+	if (msg)
+		i2o_msg_nop(c, msg);
 	return rcode;
 }
 
@@ -793,8 +799,6 @@
 		return -ENXIO;
 	}
 
-	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
-
 	sb = c->status_block.virt;
 
 	if (get_user(size, &user_msg[0]))
@@ -810,12 +814,17 @@
 
 	size <<= 2;		// Convert to bytes
 
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
+
+	rcode = -EFAULT;
 	/* Copy in the user's I2O command */
 	if (copy_from_user(msg, user_msg, size))
-		return -EFAULT;
+		goto out;
 
 	if (get_user(reply_size, &user_reply[0]) < 0)
-		return -EFAULT;
+		goto out;
 
 	reply_size >>= 16;
 	reply_size <<= 2;
@@ -824,7 +833,8 @@
 	if (!reply) {
 		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
 		       c->name);
-		return -ENOMEM;
+		rcode = -ENOMEM;
+		goto out;
 	}
 
 	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -891,13 +901,14 @@
 	}
 
 	rcode = i2o_msg_post_wait(c, msg, 60);
+	msg = NULL;
 	if (rcode) {
 		reply[4] = ((u32) rcode) << 24;
 		goto sg_list_cleanup;
 	}
 
 	if (sg_offset) {
-		u32 msg[128];
+		u32 rmsg[128];
 		/* Copy back the Scatter Gather buffers back to user space */
 		u32 j;
 		// TODO 64bit fix
@@ -905,7 +916,7 @@
 		int sg_size;
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
+		memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
@@ -914,7 +925,7 @@
 		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
-		if (copy_from_user(msg, user_msg, size)) {
+		if (copy_from_user(rmsg, user_msg, size)) {
 			rcode = -EFAULT;
 			goto sg_list_cleanup;
 		}
@@ -922,7 +933,7 @@
 		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 
 		// TODO 64bit fix
-		sg = (struct sg_simple_element *)(msg + sg_offset);
+		sg = (struct sg_simple_element *)(rmsg + sg_offset);
 		for (j = 0; j < sg_count; j++) {
 			/* Copy out the SG list to user's buffer if necessary */
 			if (!
@@ -944,7 +955,7 @@
 		}
 	}
 
-      sg_list_cleanup:
+sg_list_cleanup:
 	/* Copy back the reply to user space */
 	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
@@ -964,8 +975,11 @@
 	for (i = 0; i < sg_index; i++)
 		kfree(sg_list[i]);
 
-      cleanup:
+cleanup:
 	kfree(reply);
+out:
+	if (msg)
+		i2o_msg_nop(c, msg);
 	return rcode;
 }
 #endif
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 3305c12..a1ec16a 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -1067,7 +1067,7 @@
 
 	INIT_LIST_HEAD(&c->devices);
 	spin_lock_init(&c->lock);
-	init_MUTEX(&c->lct_lock);
+	mutex_init(&c->lct_lock);
 
 	device_initialize(&c->device);
 
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 38e815a..fdbaa77 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -209,6 +209,7 @@
 	DECLARE_WAITQUEUE(wait, tsk);
 	int valid = 0;
 
+	set_freezable();
 	add_wait_queue(&ts->irq_wait, &wait);
 	while (!kthread_should_stop()) {
 		unsigned int x, y, p;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index bd601ef..1d516f2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -2,11 +2,15 @@
 # Misc strange devices
 #
 
-menu "Misc devices"
+menuconfig MISC_DEVICES
+	bool "Misc devices"
+	default y
+
+if MISC_DEVICES
 
 config IBM_ASM
 	tristate "Device driver for IBM RSA service processor"
-	depends on X86 && PCI && EXPERIMENTAL
+	depends on X86 && PCI && INPUT && EXPERIMENTAL
 	---help---
 	  This option enables device driver support for in-band access to the
 	  IBM RSA (Condor) service processor in eServer xSeries systems.
@@ -192,4 +196,4 @@
 
 	  If you are not sure, say Y here.
 
-endmenu
+endif # MISC_DEVICES
diff --git a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c
index 07a085c..b5df347 100644
--- a/drivers/misc/ibmasm/command.c
+++ b/drivers/misc/ibmasm/command.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -72,7 +72,7 @@
 static void free_command(struct kobject *kobj)
 {
 	struct command *cmd = to_command(kobj);
- 
+
 	list_del(&cmd->queue_node);
 	atomic_dec(&command_count);
 	dbg("command count: %d\n", atomic_read(&command_count));
@@ -113,14 +113,14 @@
 		exec_next_command(sp);
 	}
 }
-	
+
 /**
  * exec_command
  * send a command to a service processor
  * Commands are executed sequentially. One command (sp->current_command)
  * is sent to the service processor. Once the interrupt handler gets a
  * message of type command_response, the message is copied into
- * the current commands buffer, 
+ * the current commands buffer,
  */
 void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
 {
@@ -160,7 +160,7 @@
 	}
 }
 
-/** 
+/**
  * Sleep until a command has failed or a response has been received
  * and the command status been updated by the interrupt handler.
  * (see receive_response).
@@ -182,8 +182,8 @@
 {
 	struct command *cmd = sp->current_command;
 
-	if (!sp->current_command) 
-		return; 
+	if (!sp->current_command)
+		return;
 
 	memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
 	cmd->status = IBMASM_CMD_COMPLETE;
diff --git a/drivers/misc/ibmasm/dot_command.c b/drivers/misc/ibmasm/dot_command.c
index 13c52f8..3dd2dfb 100644
--- a/drivers/misc/ibmasm/dot_command.c
+++ b/drivers/misc/ibmasm/dot_command.c
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -44,11 +44,11 @@
 		size = message_size;
 
 	switch (header->type) {
-	case sp_event: 
+	case sp_event:
 		ibmasm_receive_event(sp, message, size);
 		break;
 	case sp_command_response:
-		ibmasm_receive_command_response(sp, message, size); 
+		ibmasm_receive_command_response(sp, message, size);
 		break;
 	case sp_heartbeat:
 		ibmasm_receive_heartbeat(sp, message, size);
@@ -95,7 +95,7 @@
 	strcat(vpd_data, IBMASM_DRIVER_VPD);
 	vpd_data[10] = 0;
 	vpd_data[15] = 0;
-	
+
 	ibmasm_exec_command(sp, command);
 	ibmasm_wait_for_response(command, IBMASM_CMD_TIMEOUT_NORMAL);
 
@@ -118,7 +118,7 @@
  * During driver init this function is called with os state "up".
  * This causes the service processor to start sending heartbeats the
  * driver.
- * During driver exit the function is called with os state "down", 
+ * During driver exit the function is called with os state "down",
  * causing the service processor to stop the heartbeats.
  */
 int ibmasm_send_os_state(struct service_processor *sp, int os_state)
diff --git a/drivers/misc/ibmasm/dot_command.h b/drivers/misc/ibmasm/dot_command.h
index 2d21c27..6cbba1a 100644
--- a/drivers/misc/ibmasm/dot_command.h
+++ b/drivers/misc/ibmasm/dot_command.h
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c
index fe1e819..fda6a4d 100644
--- a/drivers/misc/ibmasm/event.c
+++ b/drivers/misc/ibmasm/event.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -51,7 +51,7 @@
  * event readers.
  * There is no reader marker in the buffer, therefore readers are
  * responsible for keeping up with the writer, or they will loose events.
- */ 
+ */
 void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size)
 {
 	struct event_buffer *buffer = sp->event_buffer;
@@ -77,13 +77,13 @@
 
 static inline int event_available(struct event_buffer *b, struct event_reader *r)
 {
-	return 	(r->next_serial_number < b->next_serial_number);
+	return (r->next_serial_number < b->next_serial_number);
 }
 
 /**
  * get_next_event
  * Called by event readers (initiated from user space through the file
- * system). 
+ * system).
  * Sleeps until a new event is available.
  */
 int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader)
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
index 7fd7a43..3036e78 100644
--- a/drivers/misc/ibmasm/heartbeat.c
+++ b/drivers/misc/ibmasm/heartbeat.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/ibmasm/i2o.h b/drivers/misc/ibmasm/i2o.h
index 958c957..bf2c738 100644
--- a/drivers/misc/ibmasm/i2o.h
+++ b/drivers/misc/ibmasm/i2o.h
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -26,9 +26,9 @@
 	u8	version;
 	u8	message_flags;
 	u16	message_size;
-	u8	target;           
+	u8	target;
 	u8	initiator_and_target;
-	u8	initiator;        
+	u8	initiator;
 	u8	function;
 	u32	initiator_context;
 };
@@ -64,12 +64,12 @@
 	size = sizeof(struct i2o_header) + data_size;
 
 	i2o_size = size / sizeof(u32);
-	
+
 	if (size % sizeof(u32))
 	       i2o_size++;
 
 	return i2o_size;
-}	
+}
 
 static inline u32 incoming_data_size(struct i2o_message *i2o_message)
 {
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index 48d5abe..de860bc 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -58,8 +58,8 @@
 	return buf;
 }
 
-#define IBMASM_CMD_PENDING	0	
-#define IBMASM_CMD_COMPLETE	1	
+#define IBMASM_CMD_PENDING	0
+#define IBMASM_CMD_COMPLETE	1
 #define IBMASM_CMD_FAILED	2
 
 #define IBMASM_CMD_TIMEOUT_NORMAL	45
@@ -163,55 +163,55 @@
 };
 
 /* command processing */
-extern struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
-extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
-extern void ibmasm_wait_for_response(struct command *cmd, int timeout);
-extern void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
+struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
+void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
+void ibmasm_wait_for_response(struct command *cmd, int timeout);
+void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
 
 /* event processing */
-extern int ibmasm_event_buffer_init(struct service_processor *sp);
-extern void ibmasm_event_buffer_exit(struct service_processor *sp);
-extern void ibmasm_receive_event(struct service_processor *sp, void *data,  unsigned int data_size);
-extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
-extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
-extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
-extern void ibmasm_cancel_next_event(struct event_reader *reader);
+int ibmasm_event_buffer_init(struct service_processor *sp);
+void ibmasm_event_buffer_exit(struct service_processor *sp);
+void ibmasm_receive_event(struct service_processor *sp, void *data,  unsigned int data_size);
+void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
+void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
+int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
+void ibmasm_cancel_next_event(struct event_reader *reader);
 
 /* heartbeat - from SP to OS */
-extern void ibmasm_register_panic_notifier(void);
-extern void ibmasm_unregister_panic_notifier(void);
-extern int ibmasm_heartbeat_init(struct service_processor *sp);
-extern void ibmasm_heartbeat_exit(struct service_processor *sp);
-extern void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size);
+void ibmasm_register_panic_notifier(void);
+void ibmasm_unregister_panic_notifier(void);
+int ibmasm_heartbeat_init(struct service_processor *sp);
+void ibmasm_heartbeat_exit(struct service_processor *sp);
+void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size);
 
 /* reverse heartbeat - from OS to SP */
-extern void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
-extern int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
-extern void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
+void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
+int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
+void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
 
 /* dot commands */
-extern void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
-extern int ibmasm_send_driver_vpd(struct service_processor *sp);
-extern int ibmasm_send_os_state(struct service_processor *sp, int os_state);
+void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
+int ibmasm_send_driver_vpd(struct service_processor *sp);
+int ibmasm_send_os_state(struct service_processor *sp, int os_state);
 
 /* low level message processing */
-extern int ibmasm_send_i2o_message(struct service_processor *sp);
-extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
+int ibmasm_send_i2o_message(struct service_processor *sp);
+irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
 
 /* remote console */
-extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
-extern int ibmasm_init_remote_input_dev(struct service_processor *sp);
-extern void ibmasm_free_remote_input_dev(struct service_processor *sp);
+void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
+int ibmasm_init_remote_input_dev(struct service_processor *sp);
+void ibmasm_free_remote_input_dev(struct service_processor *sp);
 
 /* file system */
-extern int ibmasmfs_register(void);
-extern void ibmasmfs_unregister(void);
-extern void ibmasmfs_add_sp(struct service_processor *sp);
+int ibmasmfs_register(void);
+void ibmasmfs_unregister(void);
+void ibmasmfs_add_sp(struct service_processor *sp);
 
 /* uart */
 #ifdef CONFIG_SERIAL_8250
-extern void ibmasm_register_uart(struct service_processor *sp);
-extern void ibmasm_unregister_uart(struct service_processor *sp);
+void ibmasm_register_uart(struct service_processor *sp);
+void ibmasm_unregister_uart(struct service_processor *sp);
 #else
 #define ibmasm_register_uart(sp)	do { } while(0)
 #define ibmasm_unregister_uart(sp)	do { } while(0)
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index c436d3d..eb7b073 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -17,12 +17,12 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
 /*
- * Parts of this code are based on an article by Jonathan Corbet 
+ * Parts of this code are based on an article by Jonathan Corbet
  * that appeared in Linux Weekly News.
  */
 
@@ -55,22 +55,22 @@
  * For each service processor the following files are created:
  *
  * command: execute dot commands
- * 	write: execute a dot command on the service processor
- * 	read: return the result of a previously executed dot command
+ *	write: execute a dot command on the service processor
+ *	read: return the result of a previously executed dot command
  *
  * events: listen for service processor events
- * 	read: sleep (interruptible) until an event occurs
+ *	read: sleep (interruptible) until an event occurs
  *      write: wakeup sleeping event listener
  *
  * reverse_heartbeat: send a heartbeat to the service processor
- * 	read: sleep (interruptible) until the reverse heartbeat fails
+ *	read: sleep (interruptible) until the reverse heartbeat fails
  *      write: wakeup sleeping heartbeat listener
  *
  * remote_video/width
  * remote_video/height
  * remote_video/width: control remote display settings
- * 	write: set value
- * 	read: read value
+ *	write: set value
+ *	read: read value
  */
 
 #include <linux/fs.h>
@@ -155,7 +155,7 @@
 
 static struct dentry *ibmasmfs_create_file (struct super_block *sb,
 			struct dentry *parent,
-		       	const char *name,
+			const char *name,
 			const struct file_operations *fops,
 			void *data,
 			int mode)
@@ -261,7 +261,7 @@
 	struct ibmasmfs_command_data *command_data = file->private_data;
 
 	if (command_data->command)
-		command_put(command_data->command);	
+		command_put(command_data->command);
 
 	kfree(command_data);
 	return 0;
@@ -348,7 +348,7 @@
 static int event_file_open(struct inode *inode, struct file *file)
 {
 	struct ibmasmfs_event_data *event_data;
-	struct service_processor *sp; 
+	struct service_processor *sp;
 
 	if (!inode->i_private)
 		return -ENODEV;
@@ -573,7 +573,7 @@
 		kfree(buff);
 		return -EFAULT;
 	}
-	
+
 	value = simple_strtoul(buff, NULL, 10);
 	writel(value, address);
 	kfree(buff);
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index a3c589b..4b2398e 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/ibmasm/lowlevel.h b/drivers/misc/ibmasm/lowlevel.h
index e5ed59c..7667665 100644
--- a/drivers/misc/ibmasm/lowlevel.h
+++ b/drivers/misc/ibmasm/lowlevel.h
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -48,9 +48,9 @@
 #define INTR_CONTROL_REGISTER  0x13A4
 
 #define SCOUT_COM_A_BASE         0x0000
-#define SCOUT_COM_B_BASE         0x0100   
-#define SCOUT_COM_C_BASE         0x0200   
-#define SCOUT_COM_D_BASE         0x0300   
+#define SCOUT_COM_B_BASE         0x0100
+#define SCOUT_COM_C_BASE         0x0200
+#define SCOUT_COM_D_BASE         0x0300
 
 static inline int sp_interrupt_pending(void __iomem *base_address)
 {
@@ -86,12 +86,12 @@
 
 static inline void enable_uart_interrupts(void __iomem *base_address)
 {
-	ibmasm_enable_interrupts(base_address, UART_INTR_MASK); 
+	ibmasm_enable_interrupts(base_address, UART_INTR_MASK);
 }
 
 static inline void disable_uart_interrupts(void __iomem *base_address)
 {
-	ibmasm_disable_interrupts(base_address, UART_INTR_MASK); 
+	ibmasm_disable_interrupts(base_address, UART_INTR_MASK);
 }
 
 #define valid_mfa(mfa)	( (mfa) != NO_MFAS_AVAILABLE )
@@ -111,7 +111,7 @@
 
 static inline void set_mfa_outbound(void __iomem *base_address, u32 mfa)
 {
-   	writel(mfa, base_address + OUTBOUND_QUEUE_PORT);
+	writel(mfa, base_address + OUTBOUND_QUEUE_PORT);
 }
 
 static inline u32 get_mfa_inbound(void __iomem *base_address)
@@ -126,7 +126,7 @@
 
 static inline void set_mfa_inbound(void __iomem *base_address, u32 mfa)
 {
-   	writel(mfa, base_address + INBOUND_QUEUE_PORT);
+	writel(mfa, base_address + INBOUND_QUEUE_PORT);
 }
 
 static inline struct i2o_message *get_i2o_message(void __iomem *base_address, u32 mfa)
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 2f3bddf..fb03a85 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -18,9 +18,9 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
- * This driver is based on code originally written by Pete Reynolds 
+ * This driver is based on code originally written by Pete Reynolds
  * and others.
  *
  */
@@ -30,13 +30,13 @@
  *
  * 1) When loaded it sends a message to the service processor,
  * indicating that an OS is * running. This causes the service processor
- * to send periodic heartbeats to the OS. 
+ * to send periodic heartbeats to the OS.
  *
  * 2) Answers the periodic heartbeats sent by the service processor.
  * Failure to do so would result in system reboot.
  *
  * 3) Acts as a pass through for dot commands sent from user applications.
- * The interface for this is the ibmasmfs file system. 
+ * The interface for this is the ibmasmfs file system.
  *
  * 4) Allows user applications to register for event notification. Events
  * are sent to the driver through interrupts. They can be read from user
@@ -105,7 +105,7 @@
 	}
 
 	sp->irq = pdev->irq;
-	sp->base_address = ioremap(pci_resource_start(pdev, 0), 
+	sp->base_address = ioremap(pci_resource_start(pdev, 0),
 					pci_resource_len(pdev, 0));
 	if (sp->base_address == 0) {
 		dev_err(sp->dev, "Failed to ioremap pci memory\n");
diff --git a/drivers/misc/ibmasm/r_heartbeat.c b/drivers/misc/ibmasm/r_heartbeat.c
index f8fdb2d..bec9e2c 100644
--- a/drivers/misc/ibmasm/r_heartbeat.c
+++ b/drivers/misc/ibmasm/r_heartbeat.c
@@ -16,7 +16,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -36,10 +36,10 @@
 	unsigned char			command[3];
 } rhb_dot_cmd = {
 	.header = {
-		.type = 	sp_read,
+		.type =		sp_read,
 		.command_size = 3,
 		.data_size =	0,
-		.status = 	0
+		.status =	0
 	},
 	.command = { 4, 3, 6 }
 };
@@ -76,9 +76,9 @@
 		if (cmd->status != IBMASM_CMD_COMPLETE)
 			times_failed++;
 
-		wait_event_interruptible_timeout(rhb->wait, 
+		wait_event_interruptible_timeout(rhb->wait,
 			rhb->stopped,
-			REVERSE_HEARTBEAT_TIMEOUT * HZ); 	
+			REVERSE_HEARTBEAT_TIMEOUT * HZ);
 
 		if (signal_pending(current) || rhb->stopped) {
 			result = -EINTR;
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index a40fda6..0550ce0 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -28,11 +28,10 @@
 #include "ibmasm.h"
 #include "remote.h"
 
-static int xmax = 1600;
-static int ymax = 1200;
+#define MOUSE_X_MAX	1600
+#define MOUSE_Y_MAX	1200
 
-
-static unsigned short xlate_high[XLATE_SIZE] = {
+static const unsigned short xlate_high[XLATE_SIZE] = {
 	[KEY_SYM_ENTER & 0xff] = KEY_ENTER,
 	[KEY_SYM_KPSLASH & 0xff] = KEY_KPSLASH,
 	[KEY_SYM_KPSTAR & 0xff] = KEY_KPASTERISK,
@@ -81,7 +80,8 @@
 	[KEY_SYM_NUM_LOCK & 0xff] = KEY_NUMLOCK,
 	[KEY_SYM_SCR_LOCK & 0xff] = KEY_SCROLLLOCK,
 };
-static unsigned short xlate[XLATE_SIZE] = {
+
+static const unsigned short xlate[XLATE_SIZE] = {
 	[NO_KEYCODE] = KEY_RESERVED,
 	[KEY_SYM_SPACE] = KEY_SPACE,
 	[KEY_SYM_TILDE] = KEY_GRAVE,        [KEY_SYM_BKTIC] = KEY_GRAVE,
@@ -133,19 +133,16 @@
 	[KEY_SYM_Z] = KEY_Z,                [KEY_SYM_z] = KEY_Z,
 };
 
-static char remote_mouse_name[] = "ibmasm RSA I remote mouse";
-static char remote_keybd_name[] = "ibmasm RSA I remote keyboard";
-
 static void print_input(struct remote_input *input)
 {
 	if (input->type == INPUT_TYPE_MOUSE) {
 		unsigned char buttons = input->mouse_buttons;
 		dbg("remote mouse movement: (x,y)=(%d,%d)%s%s%s%s\n",
 			input->data.mouse.x, input->data.mouse.y,
-			(buttons)?" -- buttons:":"",
-			(buttons & REMOTE_BUTTON_LEFT)?"left ":"",
-			(buttons & REMOTE_BUTTON_MIDDLE)?"middle ":"",
-			(buttons & REMOTE_BUTTON_RIGHT)?"right":""
+			(buttons) ? " -- buttons:" : "",
+			(buttons & REMOTE_BUTTON_LEFT) ? "left " : "",
+			(buttons & REMOTE_BUTTON_MIDDLE) ? "middle " : "",
+			(buttons & REMOTE_BUTTON_RIGHT) ? "right" : ""
 		      );
 	} else {
 		dbg("remote keypress (code, flag, down):"
@@ -180,7 +177,7 @@
 		key = xlate_high[code & 0xff];
 	else
 		key = xlate[code];
-	input_report_key(dev, key, (input->data.keyboard.key_down) ? 1 : 0);
+	input_report_key(dev, key, input->data.keyboard.key_down);
 	input_sync(dev);
 }
 
@@ -228,20 +225,22 @@
 	mouse_dev->id.vendor = pdev->vendor;
 	mouse_dev->id.product = pdev->device;
 	mouse_dev->id.version = 1;
+	mouse_dev->dev.parent = sp->dev;
 	mouse_dev->evbit[0]  = BIT(EV_KEY) | BIT(EV_ABS);
 	mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
 		BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
 	set_bit(BTN_TOUCH, mouse_dev->keybit);
-	mouse_dev->name = remote_mouse_name;
-	input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
-	input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
+	mouse_dev->name = "ibmasm RSA I remote mouse";
+	input_set_abs_params(mouse_dev, ABS_X, 0, MOUSE_X_MAX, 0, 0);
+	input_set_abs_params(mouse_dev, ABS_Y, 0, MOUSE_Y_MAX, 0, 0);
 
-	mouse_dev->id.bustype = BUS_PCI;
+	keybd_dev->id.bustype = BUS_PCI;
 	keybd_dev->id.vendor = pdev->vendor;
 	keybd_dev->id.product = pdev->device;
-	mouse_dev->id.version = 2;
+	keybd_dev->id.version = 2;
+	keybd_dev->dev.parent = sp->dev;
 	keybd_dev->evbit[0]  = BIT(EV_KEY);
-	keybd_dev->name = remote_keybd_name;
+	keybd_dev->name = "ibmasm RSA I remote keyboard";
 
 	for (i = 0; i < XLATE_SIZE; i++) {
 		if (xlate_high[i])
diff --git a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h
index b7076a8..72acf5a 100644
--- a/drivers/misc/ibmasm/remote.h
+++ b/drivers/misc/ibmasm/remote.h
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  * Orignally written by Pete Reynolds
  */
@@ -73,7 +73,7 @@
 
 
 
-struct remote_input { 
+struct remote_input {
 	union {
 		struct mouse_input	mouse;
 		struct keyboard_input	keyboard;
@@ -85,7 +85,7 @@
 	unsigned char	pad3;
 };
 
-#define mouse_addr(sp) 		(sp->base_address + CONDOR_MOUSE_DATA)
+#define mouse_addr(sp)		(sp->base_address + CONDOR_MOUSE_DATA)
 #define display_width(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX)
 #define display_height(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY)
 #define display_depth(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS)
@@ -93,7 +93,7 @@
 #define vnc_status(sp)		(mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS)
 #define isr_control(sp)		(mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
 
-#define mouse_interrupt_pending(sp) 	readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
+#define mouse_interrupt_pending(sp)	readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
 #define clear_mouse_interrupt(sp)	writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
 #define enable_mouse_interrupts(sp)	writel(1, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
 #define disable_mouse_interrupts(sp)	writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 9783caf..93baa35 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 8ee0321..9623eaf 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1917,7 +1917,8 @@
  */
 static int sony_pic_disable(struct acpi_device *device)
 {
-	if (ACPI_FAILURE(acpi_evaluate_object(device->handle, "_DIS", 0, NULL)))
+	if (ACPI_FAILURE(acpi_evaluate_object(device->handle,
+			"_DIS", NULL, NULL)))
 		return -ENXIO;
 
 	dprintk("Device disabled\n");
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 4fb2089..b53dac8 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -11,6 +11,7 @@
  */
 #include <linux/module.h>
 #include <linux/blkdev.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 
 #include <linux/mmc/card.h>
@@ -44,11 +45,7 @@
 	struct mmc_queue *mq = d;
 	struct request_queue *q = mq->queue;
 
-	/*
-	 * Set iothread to ensure that we aren't put to sleep by
-	 * the process freezing.  We handle suspension ourselves.
-	 */
-	current->flags |= PF_MEMALLOC|PF_NOFREEZE;
+	current->flags |= PF_MEMALLOC;
 
 	down(&mq->thread_sem);
 	do {
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 51bc7e2..ef89780 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -16,6 +16,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
+#include <linux/freezer.h>
 #include <linux/spinlock.h>
 #include <linux/hdreg.h>
 #include <linux/init.h>
@@ -80,7 +81,7 @@
 	struct request_queue *rq = tr->blkcore_priv->rq;
 
 	/* we might get involved when memory gets low, so use PF_MEMALLOC */
-	current->flags |= PF_MEMALLOC | PF_NOFREEZE;
+	current->flags |= PF_MEMALLOC;
 
 	spin_lock_irq(rq->queue_lock);
 	while (!kthread_should_stop()) {
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 9ecaf77..ab2174a 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1346,6 +1346,7 @@
 	ubi_msg("background thread \"%s\" started, PID %d",
 		ubi->bgt_name, current->pid);
 
+	set_freezable();
 	for (;;) {
 		int err;
 
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 807e699..e970e64 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -26,7 +26,6 @@
 
 	TODO:
 	* Test Tx checksumming thoroughly
-	* Implement dev->tx_timeout
 
 	Low priority TODO:
 	* Complete reset on PciErr
@@ -1218,6 +1217,30 @@
 	return 0;
 }
 
+static void cp_tx_timeout(struct net_device *dev)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
+	int rc;
+
+	printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n",
+	       dev->name, cpr8(Cmd), cpr16(CpCmd),
+	       cpr16(IntrStatus), cpr16(IntrMask));
+
+	spin_lock_irqsave(&cp->lock, flags);
+
+	cp_stop_hw(cp);
+	cp_clean_rings(cp);
+	rc = cp_init_rings(cp);
+	cp_start_hw(cp);
+
+	netif_wake_queue(dev);
+
+	spin_unlock_irqrestore(&cp->lock, flags);
+
+	return;
+}
+
 #ifdef BROKEN
 static int cp_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -1920,10 +1943,8 @@
 	dev->change_mtu = cp_change_mtu;
 #endif
 	dev->ethtool_ops = &cp_ethtool_ops;
-#if 0
 	dev->tx_timeout = cp_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
-#endif
 
 #if CP_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d17d64e..43d0317 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -205,7 +205,7 @@
 config MACB
 	tristate "Atmel MACB support"
 	depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
-	select MII
+	select PHYLIB
 	help
 	  The Atmel MACB ethernet interface is found on many AT32 and AT91
 	  parts. Say Y to include support for the MACB chip.
@@ -405,22 +405,6 @@
 	  on the AMD Lance chipset: RieblCard (with or without battery), or
 	  PAMCard VME (also the version by Rhotron, with different addresses).
 
-config ATARI_BIONET
-	tristate "BioNet-100 support"
-	depends on ATARI && ATARI_ACSI && BROKEN
-	help
-	  Say Y to include support for BioData's BioNet-100 Ethernet adapter
-	  for the ACSI port. The driver works (has to work...) with a polled
-	  I/O scheme, so it's rather slow :-(
-
-config ATARI_PAMSNET
-	tristate "PAMsNet support"
-	depends on ATARI && ATARI_ACSI && BROKEN
-	help
-	  Say Y to include support for the PAMsNet Ethernet adapter for the
-	  ACSI port ("ACSI node"). The driver works (has to work...) with a
-	  polled I/O scheme, so it's rather slow :-(
-
 config SUN3LANCE
 	tristate "Sun3/Sun3x on-board LANCE support"
 	depends on SUN3 || SUN3X
@@ -604,6 +588,12 @@
 	  Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
 	  <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
 
+config SUNVNET
+	tristate "Sun Virtual Network support"
+	depends on SUN_LDOMS
+	help
+	  Support for virtual network devices under Sun Logical Domains.
+
 config NET_VENDOR_3COM
 	bool "3COM cards"
 	depends on ISA || EISA || MCA || PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c26b867..eb41676 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
 obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
 obj-$(CONFIG_CASSINI) += cassini.o
+obj-$(CONFIG_SUNVNET) += sunvnet.o
 
 obj-$(CONFIG_MACE) += mace.o
 obj-$(CONFIG_BMAC) += bmac.o
@@ -180,8 +181,6 @@
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
-obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
-obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
 obj-$(CONFIG_A2065) += a2065.o
 obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 1c3e293..3b79c6c 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -75,8 +75,6 @@
 extern struct net_device *sun3lance_probe(int unit);
 extern struct net_device *sun3_82586_probe(int unit);
 extern struct net_device *apne_probe(int unit);
-extern struct net_device *bionet_probe(int unit);
-extern struct net_device *pamsnet_probe(int unit);
 extern struct net_device *cs89x0_probe(int unit);
 extern struct net_device *hplance_probe(int unit);
 extern struct net_device *bagetlance_probe(int unit);
@@ -264,12 +262,6 @@
 #ifdef CONFIG_APNE		/* A1200 PCMCIA NE2000 */
 	{apne_probe, 0},
 #endif
-#ifdef CONFIG_ATARI_BIONET	/* Atari Bionet Ethernet board */
-	{bionet_probe, 0},
-#endif
-#ifdef CONFIG_ATARI_PAMSNET	/* Atari PAMsNet Ethernet board */
-	{pamsnet_probe, 0},
-#endif
 #ifdef CONFIG_MVME147_NET	/* MVME147 internal Ethernet */
 	{mvme147lance_probe, 0},
 #endif
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 5bf2d33..f9cc2b6 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -43,6 +43,7 @@
 config EP93XX_ETH
 	tristate "EP93xx Ethernet support"
 	depends on ARM && ARCH_EP93XX
+	select MII
 	help
 	  This is a driver for the ethernet hardware included in EP93xx CPUs.
 	  Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
deleted file mode 100644
index 3d87bd2..0000000
--- a/drivers/net/atari_bionet.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/* bionet.c     BioNet-100 device driver for linux68k.
- *
- * Version:	@(#)bionet.c	1.0	02/06/96
- *
- * Author:	Hartmut Laue <laue@ifk-mp.uni-kiel.de>
- * and		Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
- *
- * Little adaptions for integration into pl7 by Roman Hodek
- *
- * Some changes in bionet_poll_rx by Karl-Heinz Lohner
- *
-	What is it ?
-	------------
-	This driver controls the BIONET-100 LAN-Adapter which connects
-	an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
-
-	This version can be compiled as a loadable module (See the
-	compile command at the bottom of this file).
-	At load time, you can optionally set the debugging level and the
-	fastest response time on the command line of 'insmod'.
-
-	'bionet_debug'
-		controls the amount of diagnostic messages:
-	  0  : no messages
-	  >0 : see code for meaning of printed messages
-
-	'bionet_min_poll_time' (always >=1)
-		gives the time (in jiffies) between polls. Low values
-		increase the system load (beware!)
-
-	When loaded, a net device with the name 'bio0' becomes available,
-	which can be controlled with the usual 'ifconfig' command.
-
-	It is possible to compile this driver into the kernel like other
-	(net) drivers. For this purpose, some source files (e.g. config-files
-	makefiles, Space.c) must be changed accordingly. (You may refer to
-	other drivers how to do it.) In this case, the device will be detected
-	at boot time and (probably) appear as 'eth0'.
-
-	This code is based on several sources:
-	- The driver code for a parallel port ethernet adapter by
-	  Donald Becker (see file 'atp.c' from the PC linux distribution)
-	- The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support
-	  and DMA handling.
-	- Very limited information about moving packets in and out of the
-	  BIONET-adapter from the TCP package for TOS by BioData GmbH.
-
-	Theory of Operation
-	-------------------
-	Because the ATARI DMA port is usually shared between several
-	devices (eg. harddisk, floppy) we cannot block the ACSI bus
-	while waiting for interrupts. Therefore we use a polling mechanism
-	to fetch packets from the adapter. For the same reason, we send
-	packets without checking that the previous packet has been sent to
-	the LAN. We rely on the higher levels of the networking code to detect
-	missing packets and resend them.
-
-	Before we access the ATARI DMA controller, we check if another
-	process is using the DMA. If not, we lock the DMA, perform one or
-	more packet transfers and unlock the DMA before returning.
-	We do not use 'stdma_lock' unconditionally because it is unclear
-	if the networking code can be set to sleep, which will happen if
-	another (possibly slow) device is using the DMA controller.
-
-	The polling is done via timer interrupts which periodically
-	'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
-	between polls varies depending on an estimate of the net activity.
-	The allowed range is given by the variable 'bionet_min_poll_time'
-	for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
-	for the higher (slowest) limit.
-
-	Whenever a packet arrives, we switch to fastest response by setting
-	the polling time to its lowest limit. If the following poll fails,
-	because no packets have arrived, we increase the time for the next
-	poll. When the net activity is low, the polling time effectively
-	stays at its maximum value, resulting in the lowest load for the
-	machine.
- */
-
-#define MAX_POLL_TIME	10
-
-static char version[] =
-	"bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n";
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-
-
-/* use 0 for production, 1 for verification, >2 for debug
- */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-/*
- * Global variable 'bionet_debug'. Can be set at load time by 'insmod'
- */
-unsigned int bionet_debug = NET_DEBUG;
-module_param(bionet_debug, int, 0);
-MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
-MODULE_LICENSE("GPL");
-
-static unsigned int bionet_min_poll_time = 2;
-
-
-/* Information that need to be kept for each board.
- */
-struct net_local {
-	struct net_device_stats stats;
-	long open_time;			/* for debugging */
-	int  poll_time;			/* polling time varies with net load */
-};
-
-static struct nic_pkt_s {		/* packet format */
-	unsigned char	status;
-	unsigned char	dummy;
-	unsigned char	l_lo, l_hi;
-	unsigned char	buffer[3000];
-} *nic_packet;
-unsigned char *phys_nic_packet;
-
-/* Index to functions, as function prototypes.
- */
-static int bionet_open(struct net_device *dev);
-static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void bionet_poll_rx(struct net_device *);
-static int bionet_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void bionet_tick(unsigned long);
-
-static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0);
-
-#define STRAM_ADDR(a)	(((a) & 0xff000000) == 0)
-
-/* The following routines access the ethernet board connected to the
- * ACSI port via the st_dma chip.
- */
-#define NODE_ADR 0x60
-
-#define C_READ 8
-#define C_WRITE 0x0a
-#define C_GETEA 0x0f
-#define C_SETCR 0x0e
-
-static int
-sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) {
-	unsigned int c;
-
-	dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88);
-	dma_wd.fdc_acces_seccount = cmd;
-	dma_wd.dma_mode_status = (mod | 0x8a);
-
-	if( !acsi_wait_for_IRQ(HZ/2) )	/* wait for cmd ack */
-		return -1;		/* timeout */
-
-	c = dma_wd.fdc_acces_seccount;
-	return (c & 0xff);
-}
-
-
-static void
-set_status(int cr) {
-	sendcmd(0,0x100,NODE_ADR | C_SETCR);    /* CMD: SET CR */
-	sendcmd(1,0x100,cr);
-
-	dma_wd.dma_mode_status = 0x80;
-}
-
-static int
-get_status(unsigned char *adr) {
-	int i,c;
-
-	DISABLE_IRQ();
-	c = sendcmd(0,0x00,NODE_ADR | C_GETEA);  /* CMD: GET ETH ADR*/
-	if( c < 0 ) goto gsend;
-
-	/* now read status bytes */
-
-	for (i=0; i<6; i++) {
-		dma_wd.fdc_acces_seccount = 0;	/* request next byte */
-
-    		if( !acsi_wait_for_IRQ(HZ/2) ) {	/* wait for cmd ack */
-			c = -1;
-			goto gsend;		/* timeout */
-		}
-		c = dma_wd.fdc_acces_seccount;
-		*adr++ = (unsigned char)c;
-	}
-	c = 1;
-gsend:
-  	dma_wd.dma_mode_status = 0x80;
-	return c;
-}
-
-static irqreturn_t
-bionet_intr(int irq, void *data) {
-	return IRQ_HANDLED;
-}
-
-
-static int
-get_frame(unsigned long paddr, int odd) {
-	int c;
-	unsigned long flags;
-
-	DISABLE_IRQ();
-	local_irq_save(flags);
-
-	dma_wd.dma_mode_status		= 0x9a;
-	dma_wd.dma_mode_status		= 0x19a;
-	dma_wd.dma_mode_status		= 0x9a;
-	dma_wd.fdc_acces_seccount	= 0x04;		/* sector count (was 5) */
-	dma_wd.dma_lo			= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_md			= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_hi			= (unsigned char)paddr;
-	local_irq_restore(flags);
-
-	c = sendcmd(0,0x00,NODE_ADR | C_READ);	/* CMD: READ */
-	if( c < 128 ) goto rend;
-
-	/* now read block */
-
-	c = sendcmd(1,0x00,odd);	/* odd flag for address shift */
-	dma_wd.dma_mode_status	= 0x0a;
-
-	if( !acsi_wait_for_IRQ(100) ) {	/* wait for DMA to complete */
-		c = -1;
-		goto rend;
-	}
-	dma_wd.dma_mode_status	= 0x8a;
-	dma_wd.dma_mode_status	= 0x18a;
-	dma_wd.dma_mode_status	= 0x8a;
-	c = dma_wd.fdc_acces_seccount;
-
-	dma_wd.dma_mode_status	= 0x88;
-	c = dma_wd.fdc_acces_seccount;
-	c = 1;
-
-rend:
-	dma_wd.dma_mode_status	= 0x80;
-	udelay(40);
-	acsi_wait_for_noIRQ(20);
-	return c;
-}
-
-
-static int
-hardware_send_packet(unsigned long paddr, int cnt) {
-	unsigned int c;
-	unsigned long flags;
-
-	DISABLE_IRQ();
-	local_irq_save(flags);
-
-	dma_wd.dma_mode_status	= 0x19a;
-	dma_wd.dma_mode_status	= 0x9a;
-	dma_wd.dma_mode_status	= 0x19a;
-	dma_wd.dma_lo		= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_md		= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_hi		= (unsigned char)paddr;
-
-	dma_wd.fdc_acces_seccount	= 0x4;		/* sector count */
-	local_irq_restore(flags);
-
-	c = sendcmd(0,0x100,NODE_ADR | C_WRITE);	/* CMD: WRITE */
-	c = sendcmd(1,0x100,cnt&0xff);
-	c = sendcmd(1,0x100,cnt>>8);
-
-	/* now write block */
-
-	dma_wd.dma_mode_status	= 0x10a;	/* DMA enable */
-	if( !acsi_wait_for_IRQ(100) )		/* wait for DMA to complete */
-		goto end;
-
-	dma_wd.dma_mode_status	= 0x19a;	/* DMA disable ! */
-	c = dma_wd.fdc_acces_seccount;
-
-end:
-	c = sendcmd(1,0x100,0);
-	c = sendcmd(1,0x100,0);
-
-	dma_wd.dma_mode_status	= 0x180;
-	udelay(40);
-	acsi_wait_for_noIRQ(20);
-	return( c & 0x02);
-}
-
-
-/* Check for a network adaptor of this type, and return '0' if one exists.
- */
-struct net_device * __init bionet_probe(int unit)
-{
-	struct net_device *dev;
-	unsigned char station_addr[6];
-	static unsigned version_printed;
-	static int no_more_found;	/* avoid "Probing for..." printed 4 times */
-	int i;
-	int err;
-
-	if (!MACH_IS_ATARI || no_more_found)
-		return ERR_PTR(-ENODEV);
-
-	dev = alloc_etherdev(sizeof(struct net_local));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-	SET_MODULE_OWNER(dev);
-
-	printk("Probing for BioNet 100 Adapter...\n");
-
-	stdma_lock(bionet_intr, NULL);
-	i = get_status(station_addr);	/* Read the station address PROM.  */
-	ENABLE_IRQ();
-	stdma_release();
-
-	/* Check the first three octets of the S.A. for the manufactor's code.
-	 */
-
-	if( i < 0
-	||  station_addr[0] != 'B'
-	||  station_addr[1] != 'I'
-	||  station_addr[2] != 'O' ) {
-		no_more_found = 1;
-		printk( "No BioNet 100 found.\n" );
-		free_netdev(dev);
-		return ERR_PTR(-ENODEV);
-	}
-
-	if (bionet_debug > 0 && version_printed++ == 0)
-		printk(version);
-
-	printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n",
-		dev->name, "BioNet 100",
-		station_addr[0], station_addr[1], station_addr[2],
-		station_addr[3], station_addr[4], station_addr[5]);
-
-	/* Initialize the device structure. */
-
-	nic_packet = (struct nic_pkt_s *)acsi_buffer;
-	phys_nic_packet = (unsigned char *)phys_acsi_buffer;
-	if (bionet_debug > 0) {
-		printk("nic_packet at 0x%p, phys at 0x%p\n",
-			nic_packet, phys_nic_packet );
-	}
-
-	dev->open		= bionet_open;
-	dev->stop		= bionet_close;
-	dev->hard_start_xmit	= bionet_send_packet;
-	dev->get_stats		= net_get_stats;
-
-	/* Fill in the fields of the device structure with ethernet-generic
-	 * values. This should be in a common file instead of per-driver.
-	 */
-
-	for (i = 0; i < ETH_ALEN; i++) {
-#if 0
-		dev->broadcast[i] = 0xff;
-#endif
-		dev->dev_addr[i]  = station_addr[i];
-	}
-	err = register_netdev(dev);
-	if (!err)
-		return dev;
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
- */
-static int
-bionet_open(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-
-	if (bionet_debug > 0)
-		printk("bionet_open\n");
-	stdma_lock(bionet_intr, NULL);
-
-	/* Reset the hardware here.
-	 */
-	set_status(4);
-	lp->open_time = 0;	/*jiffies*/
-	lp->poll_time = MAX_POLL_TIME;
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	stdma_release();
-	bionet_timer.data = (long)dev;
-	bionet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&bionet_timer);
-	return 0;
-}
-
-static int
-bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	 */
-	local_irq_save(flags);
-
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		lp->stats.tx_errors++;
-	}
-	else {
-		int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-		unsigned long buf = virt_to_phys(skb->data);
-		int stat;
-
-		stdma_lock(bionet_intr, NULL);
-		local_irq_restore(flags);
-		if( !STRAM_ADDR(buf+length-1) ) {
-			skb_copy_from_linear_data(skb, nic_packet->buffer,
-						  length);
-			buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
-		}
-
-		if (bionet_debug >1) {
-			u_char *data = nic_packet->buffer, *p;
-			int i;
-
-			printk( "%s: TX pkt type 0x%4x from ", dev->name,
-				  ((u_short *)data)[6]);
-
-			for( p = &data[6], i = 0; i < 6; i++ )
-				printk("%02x%s", *p++,i != 5 ? ":" : "" );
-			printk(" to ");
-
-			for( p = data, i = 0; i < 6; i++ )
-				printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
-
-			printk( "%s: ", dev->name );
-			printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
-			       " %02x%02x%02x%02x len %d\n",
-				  data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
-				  data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
-				  data[28], data[29], data[30], data[31], data[32], data[33],
-				  length );
-		}
-		dma_cache_maintenance(buf, length, 1);
-
-		stat = hardware_send_packet(buf, length);
-		ENABLE_IRQ();
-		stdma_release();
-
-		dev->trans_start = jiffies;
-		dev->tbusy	 = 0;
-		lp->stats.tx_packets++;
-		lp->stats.tx_bytes+=length;
-	}
-	dev_kfree_skb(skb);
-
-	return 0;
-}
-
-/* We have a good packet(s), get it/them out of the buffers.
- */
-static void
-bionet_poll_rx(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-	int boguscount = 10;
-	int pkt_len, status;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	/* ++roman: Take care at locking the ST-DMA... This must be done with ints
-	 * off, since otherwise an int could slip in between the question and the
-	 * locking itself, and then we'd go to sleep... And locking itself is
-	 * necessary to keep the floppy_change timer from working with ST-DMA
-	 * registers. */
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		return;
-	}
-	stdma_lock(bionet_intr, NULL);
-	DISABLE_IRQ();
-	local_irq_restore(flags);
-
-	if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
-
-	while(boguscount--) {
-		status = get_frame((unsigned long)phys_nic_packet, 0);
-
-		if( status == 0 ) break;
-
-		/* Good packet... */
-
-		dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0);
-
-		pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo;
-
-		lp->poll_time = bionet_min_poll_time;    /* fast poll */
-		if( pkt_len >= 60 && pkt_len <= 1520 ) {
-					/*	^^^^ war 1514  KHL */
-			/* Malloc up new buffer.
-			 */
-			struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 );
-			if (skb == NULL) {
-				printk("%s: Memory squeeze, dropping packet.\n",
-					dev->name);
-				lp->stats.rx_dropped++;
-				break;
-			}
-
-			skb_reserve( skb, 2 );		/* 16 Byte align  */
-			skb_put( skb, pkt_len );	/* make room */
-
-			/* 'skb->data' points to the start of sk_buff data area.
-			 */
-			skb_copy_to_linear_data(skb, nic_packet->buffer,
-						pkt_len);
-			skb->protocol = eth_type_trans( skb, dev );
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			lp->stats.rx_packets++;
-			lp->stats.rx_bytes+=pkt_len;
-
-	/* If any worth-while packets have been received, dev_rint()
-	   has done a mark_bh(INET_BH) for us and will work on them
-	   when we get to the bottom-half routine.
-	 */
-
- 			if (bionet_debug >1) {
- 				u_char *data = nic_packet->buffer, *p;
- 				int i;
-
- 				printk( "%s: RX pkt type 0x%4x from ", dev->name,
- 					  ((u_short *)data)[6]);
-
-
- 				for( p = &data[6], i = 0; i < 6; i++ )
- 					printk("%02x%s", *p++,i != 5 ? ":" : "" );
- 				printk(" to ");
- 				for( p = data, i = 0; i < 6; i++ )
- 					printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
-
- 				printk( "%s: ", dev->name );
- 				printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
- 				       " %02x%02x%02x%02x len %d\n",
- 					  data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
- 					  data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
- 					  data[28], data[29], data[30], data[31], data[32], data[33],
- 						  pkt_len );
- 			}
- 		}
- 		else {
- 			printk(" Packet has wrong length: %04d bytes\n", pkt_len);
- 			lp->stats.rx_errors++;
- 		}
- 	}
-	stdma_release();
-	ENABLE_IRQ();
-	return;
-}
-
-/* bionet_tick: called by bionet_timer. Reads packets from the adapter,
- * passes them to the higher layers and restarts the timer.
- */
-static void
-bionet_tick(unsigned long data) {
-	struct net_device	 *dev = (struct net_device *)data;
-	struct net_local *lp = netdev_priv(dev);
-
-	if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
-		printk("bionet_tick: %ld\n", lp->open_time);
-
-	if( !stdma_islocked() ) bionet_poll_rx(dev);
-
-	bionet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&bionet_timer);
-}
-
-/* The inverse routine to bionet_open().
- */
-static int
-bionet_close(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-
-	if (bionet_debug > 0)
-		printk("bionet_close, open_time=%ld\n", lp->open_time);
-	del_timer(&bionet_timer);
-	stdma_lock(bionet_intr, NULL);
-
-	set_status(0);
-	lp->open_time = 0;
-
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	stdma_release();
-	return 0;
-}
-
-/* Get the current statistics.
-   This may be called with the card open or closed.
- */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	return &lp->stats;
-}
-
-
-#ifdef MODULE
-
-static struct net_device *bio_dev;
-
-int init_module(void)
-{
-	bio_dev = bionet_probe(-1);
-	if (IS_ERR(bio_dev))
-		return PTR_ERR(bio_dev);
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	unregister_netdev(bio_dev);
-	free_netdev(bio_dev);
-}
-
-#endif /* MODULE */
-
-/* Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
-	-b m68k-linuxaout -Wall -Wstrict-prototypes -O2
-	-fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
deleted file mode 100644
index f735637..0000000
--- a/drivers/net/atari_pamsnet.c
+++ /dev/null
@@ -1,878 +0,0 @@
-/* atari_pamsnet.c     PAMsNet device driver for linux68k.
- *
- * Version:	@(#)PAMsNet.c	0.2ß	03/31/96
- *
- * Author:  Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de>
- *                       <Torsten.Lang@jung.de>
- *
- * This driver is based on my driver PAMSDMA.c for MiNT-Net and
- * on the driver bionet.c written by
- *          Hartmut Laue <laue@ifk-mp.uni-kiel.de>
- * and      Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
- *
- * Little adaptions for integration into pl7 by Roman Hodek
- *
-	What is it ?
-	------------
-	This driver controls the PAMsNet LAN-Adapter which connects
-	an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
-
-	This version can be compiled as a loadable module (See the
-	compile command at the bottom of this file).
-	At load time, you can optionally set the debugging level and the
-	fastest response time on the command line of 'insmod'.
-
-	'pamsnet_debug'
-		controls the amount of diagnostic messages:
-	  0  : no messages
-	  >0 : see code for meaning of printed messages
-
-	'pamsnet_min_poll_time' (always >=1)
-		gives the time (in jiffies) between polls. Low values
-		increase the system load (beware!)
-
-	When loaded, a net device with the name 'eth?' becomes available,
-	which can be controlled with the usual 'ifconfig' command.
-
-	It is possible to compile this driver into the kernel like other
-	(net) drivers. For this purpose, some source files (e.g. config-files
-	makefiles, Space.c) must be changed accordingly. (You may refer to
-	other drivers how to do it.) In this case, the device will be detected
-	at boot time and (probably) appear as 'eth0'.
-
-	Theory of Operation
-	-------------------
-	Because the ATARI DMA port is usually shared between several
-	devices (eg. harddisk, floppy) we cannot block the ACSI bus
-	while waiting for interrupts. Therefore we use a polling mechanism
-	to fetch packets from the adapter. For the same reason, we send
-	packets without checking that the previous packet has been sent to
-	the LAN. We rely on the higher levels of the networking code to detect
-	missing packets and resend them.
-
-	Before we access the ATARI DMA controller, we check if another
-	process is using the DMA. If not, we lock the DMA, perform one or
-	more packet transfers and unlock the DMA before returning.
-	We do not use 'stdma_lock' unconditionally because it is unclear
-	if the networking code can be set to sleep, which will happen if
-	another (possibly slow) device is using the DMA controller.
-
-	The polling is done via timer interrupts which periodically
-	'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
-	between polls varies depending on an estimate of the net activity.
-	The allowed range is given by the variable 'bionet_min_poll_time'
-	for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
-	for the higher (slowest) limit.
-
-	Whenever a packet arrives, we switch to fastest response by setting
-	the polling time to its lowest limit. If the following poll fails,
-	because no packets have arrived, we increase the time for the next
-	poll. When the net activity is low, the polling time effectively
-	stays at its maximum value, resulting in the lowest load for the
-	machine.
- */
-
-#define MAX_POLL_TIME	10
-
-static char *version =
-	"pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n";
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/errno.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_acsi.h>
-
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#undef READ
-#undef WRITE
-
-/* use 0 for production, 1 for verification, >2 for debug
- */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-/*
- * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod'
- */
-unsigned int pamsnet_debug = NET_DEBUG;
-module_param(pamsnet_debug, int, 0);
-MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)");
-MODULE_LICENSE("GPL");
-
-static unsigned int pamsnet_min_poll_time = 2;
-
-
-/* Information that need to be kept for each board.
- */
-struct net_local {
-	struct net_device_stats stats;
-	long open_time;			/* for debugging */
-	int  poll_time;			/* polling time varies with net load */
-};
-
-static struct nic_pkt_s {		/* packet format */
-	unsigned char	buffer[2048];
-} *nic_packet = 0;
-unsigned char *phys_nic_packet;
-
-typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */
-
-/* Index to functions, as function prototypes.
- */
-static void	start (int target);
-static int	stop (int target);
-static int	testpkt (int target);
-static int	sendpkt (int target, unsigned char *buffer, int length);
-static int	receivepkt (int target, unsigned char *buffer);
-static int	inquiry (int target, unsigned char *buffer);
-static HADDR	*read_hw_addr(int target, unsigned char *buffer);
-static void	setup_dma (void *address, unsigned rw_flag, int num_blocks);
-static int	send_first (int target, unsigned char byte);
-static int	send_1_5 (int lun, unsigned char *command, int dma);
-static int	get_status (void);
-static int	calc_received (void *start_address);
-
-static int pamsnet_open(struct net_device *dev);
-static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void pamsnet_poll_rx(struct net_device *);
-static int pamsnet_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void pamsnet_tick(unsigned long);
-
-static irqreturn_t pamsnet_intr(int irq, void *data);
-
-static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0);
-
-#define STRAM_ADDR(a)	(((a) & 0xff000000) == 0)
-
-typedef struct
-{
-	unsigned char reserved1[0x38];
-	HADDR  hwaddr;
-	unsigned char reserved2[0x1c2];
-} DMAHWADDR;
-
-/*
- * Definitions of commands understood by the PAMs DMA adaptor.
- *
- * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable
- * by the PAM's Net software.
- *
- * LUN 0 works as a harddisk. You can boot the PAM's Net driver there.
- * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW
- *       area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address
- *       of the adaptor.
- * LUN 6 works as a harddisk and lets you access the firmware ROM.
- * LUN 7 lets you send and receive packets.
- *
- * Some commands like the INQUIRY command work identical on all used LUNs.
- *
- * UNKNOWN1 seems to read some data.
- *          Command length is 6 bytes.
- * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The
- *          following bytes seem to be something like an allocation length.
- *          Command length is 6 bytes.
- * READPKT  reads a packet received by the DMA adaptor.
- *          Command length is 6 bytes.
- * WRITEPKT sends a packet transferred by the following DMA phase. The length
- *          of the packet is transferred in command bytes 3 and 4.
- *          The adaptor automatically replaces the src hw address in an ethernet
- *          packet by its own hw address.
- *          Command length is 6 bytes.
- * INQUIRY  has the same function as the INQUIRY command supported by harddisks
- *          and other SCSI devices. It lets you detect which device you found
- *          at a given address.
- *          Command length is 6 bytes.
- * START    initializes the DMA adaptor. After this command it is able to send
- *          and receive packets. There is no status byte returned!
- *          Command length is 1 byte.
- * NUMPKTS  gives back the number of received packets waiting in the queue in
- *          the status byte.
- *          Command length is 1 byte.
- * UNKNOWN3
- * UNKNOWN4 Function of these three commands is unknown.
- * UNKNOWN5 The command length of these three commands is 1 byte.
- * DESELECT immediately deselects the DMA adaptor. May important with interrupt
- *          driven operation.
- *          Command length is 1 byte.
- * STOP     resets the DMA adaptor. After this command packets can no longer
- *          be received or transferred.
- *          Command length is 6 byte.
- */
-
-enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START,
-      NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP};
-
-#define READSECTOR  READPKT
-#define WRITESECTOR WRITEPKT
-
-u_char *inquire8="MV      PAM's NET/GK";
-
-#define DMALOW   dma_wd.dma_lo
-#define DMAMID   dma_wd.dma_md
-#define DMAHIGH  dma_wd.dma_hi
-#define DACCESS  dma_wd.fdc_acces_seccount
-
-#define MFP_GPIP mfp.par_dt_reg
-
-/* Some useful functions */
-
-#define INT      (!(MFP_GPIP & 0x20))
-#define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;})
-#define WRITEMODE(value)					\
-	({	u_short dummy = value;				\
-		__asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy));	\
-		DELAY;						\
-	})
-#define WRITEBOTH(value1, value2)				\
-	({	u_long dummy = (u_long)(value1)<<16 | (u_short)(value2);	\
-		__asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy));	\
-		DELAY;						\
-	})
-
-/* Definitions for DMODE */
-
-#define READ        0x000
-#define WRITE       0x100
-
-#define DMA_FDC     0x080
-#define DMA_ACSI    0x000
-
-#define DMA_DISABLE 0x040
-
-#define SEC_COUNT   0x010
-#define DMA_WINDOW  0x000
-
-#define REG_ACSI    0x008
-#define REG_FDC     0x000
-
-#define A1          0x002
-
-/* Timeout constants */
-
-#define TIMEOUTCMD HZ/2   /* ca. 500ms */
-#define TIMEOUTDMA HZ     /* ca. 1s */
-#define COMMAND_DELAY 500 /* ca. 0.5ms */
-
-unsigned rw;
-int lance_target = -1;
-int if_up = 0;
-
-/* The following routines access the ethernet board connected to the
- * ACSI port via the st_dma chip.
- */
-
-/* The following lowlevel routines work on physical addresses only and assume
- * that eventually needed buffers are
- * - completely located in ST RAM
- * - are contigous in the physical address space
- */
-
-/* Setup the DMA counter */
-
-static void
-setup_dma (void *address, unsigned rw_flag, int num_blocks)
-{
-	WRITEMODE((unsigned) rw_flag          | DMA_FDC | SEC_COUNT | REG_ACSI |
-		  A1);
-	WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI |
-		  A1);
-	WRITEMODE((unsigned) rw_flag          | DMA_FDC | SEC_COUNT | REG_ACSI |
-		  A1);
-	DMALOW  = (unsigned char)((unsigned long)address & 0xFF);
-	DMAMID  = (unsigned char)(((unsigned long)address >>  8) & 0xFF);
-	DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF);
-	WRITEBOTH((unsigned)num_blocks & 0xFF,
-		  rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
-	rw = rw_flag;
-}
-
-/* Send the first byte of an command block */
-
-static int
-send_first (int target, unsigned char byte)
-{
-	rw = READ;
-	acsi_delay_end(COMMAND_DELAY);
-	/*
-	 * wake up ACSI
-	 */
-	WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI);
-	/*
-	 * write command byte
-	 */
-	WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC |
-	          DMA_WINDOW | REG_ACSI | A1);
-	return (!acsi_wait_for_IRQ(TIMEOUTCMD));
-}
-
-/* Send the rest of an command block */
-
-static int
-send_1_5 (int lun, unsigned char *command, int dma)
-{
-	int i, j;
-
-	for (i=0; i<5; i++) {
-		WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F))
-			      : command[i]),
-			  rw | REG_ACSI | DMA_WINDOW |
-			   ((i < 4) ? DMA_FDC
-				    : (dma ? DMA_ACSI
-					   : DMA_FDC)) | A1);
-		if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD)))
-			return (j);
-	}
-	return (0);
-}
-
-/* Read a status byte */
-
-static int
-get_status (void)
-{
-	WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
-	acsi_delay_start();
-	return ((int)(DACCESS & 0xFF));
-}
-
-/* Calculate the number of received bytes */
-
-static int
-calc_received (void *start_address)
-{
-	return (int)(
-		(((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW)
-	      - (unsigned long)start_address);
-}
-
-/* The following midlevel routines still work on physical addresses ... */
-
-/* start() starts the PAM's DMA adaptor */
-
-static void
-start (int target)
-{
-	send_first(target, START);
-}
-
-/* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
-
-static int
-stop (int target)
-{
-	int ret = -1;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, STOP))
-		goto bad;
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] =
-	cmd_buffer[3] = cmd_buffer[4] = 0;
-	if (send_1_5(7, cmd_buffer, 0) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = 0;
-bad:
-	return (ret);
-}
-
-/* testpkt() returns the number of received packets waiting in the queue */
-
-static int
-testpkt(int target)
-{
-	int ret = -1;
-
-	if (send_first(target, NUMPKTS))
-		goto bad;
-	ret = get_status();
-bad:
-	return (ret);
-}
-
-/* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */
-/* Please note: The buffer is for internal use only but must be defined!   */
-
-static int
-inquiry (int target, unsigned char *buffer)
-{
-	int ret = -1;
-	unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, INQUIRY))
-		goto bad;
-	setup_dma(buffer, READ, 1);
-	vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
-	cmd_buffer[3] = 48;
-	if (send_1_5(5, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status() ||
-	    (calc_received(buffer) < 32))
-		goto bad;
-	dma_cache_maintenance((unsigned long)(buffer+8), 20, 0);
-	if (memcmp(inquire8, vbuffer+8, 20))
-		goto bad;
-	ret = 0;
-bad:
-	if (!!NET_DEBUG) {
-		vbuffer[8+20]=0;
-		printk("inquiry of target %d: %s\n", target, vbuffer+8);
-	}
-	return (ret);
-}
-
-/*
- * read_hw_addr() reads the sector containing the hwaddr and returns
- * a pointer to it (virtual address!) or 0 in case of an error
- */
-
-static HADDR
-*read_hw_addr(int target, unsigned char *buffer)
-{
-	HADDR *ret = 0;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, READSECTOR))
-		goto bad;
-	setup_dma(buffer, READ, 1);
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
-	cmd_buffer[3] = 1;
-	if (send_1_5(5, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr));
-	dma_cache_maintenance((unsigned long)buffer, 512, 0);
-bad:
-	return (ret);
-}
-
-static irqreturn_t
-pamsnet_intr(int irq, void *data)
-{
-	return IRQ_HANDLED;
-}
-
-/* receivepkt() loads a packet to a given buffer and returns its length */
-
-static int
-receivepkt (int target, unsigned char *buffer)
-{
-	int ret = -1;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, READPKT))
-		goto bad;
-	setup_dma(buffer, READ, 3);
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
-	cmd_buffer[3] = 3;
-	if (send_1_5(7, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = calc_received(buffer);
-bad:
-	return (ret);
-}
-
-/* sendpkt() sends a packet and returns a value of zero when the packet was sent
-             successfully */
-
-static int
-sendpkt (int target, unsigned char *buffer, int length)
-{
-	int ret = -1;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, WRITEPKT))
-		goto bad;
-	setup_dma(buffer, WRITE, 3);
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0;
-	cmd_buffer[2] = length >> 8;
-	cmd_buffer[3] = length & 0xFF;
-	if (send_1_5(7, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = 0;
-bad:
-	return (ret);
-}
-
-/* The following higher level routines work on virtual addresses and convert them to
- * physical addresses when passed to the lowlevel routines. It's up to the higher level
- * routines to copy data from Alternate RAM to ST RAM if neccesary!
- */
-
-/* Check for a network adaptor of this type, and return '0' if one exists.
- */
-
-struct net_device * __init pamsnet_probe (int unit)
-{
-	struct net_device *dev;
-	int i;
-	HADDR *hwaddr;
-	int err;
-
-	unsigned char station_addr[6];
-	static unsigned version_printed;
-	/* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */
-	static int no_more_found;
-
-	if (no_more_found)
-		return ERR_PTR(-ENODEV);
-	no_more_found = 1;
-
-	dev = alloc_etherdev(sizeof(struct net_local));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-	SET_MODULE_OWNER(dev);
-
-	printk("Probing for PAM's Net/GK Adapter...\n");
-
-	/* Allocate the DMA buffer here since we need it for probing! */
-
-	nic_packet = (struct nic_pkt_s *)acsi_buffer;
-	phys_nic_packet = (unsigned char *)phys_acsi_buffer;
-	if (pamsnet_debug > 0) {
-		printk("nic_packet at 0x%p, phys at 0x%p\n",
-			   nic_packet, phys_nic_packet );
-	}
-
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-
-	for (i=0; i<8; i++) {
-		/* Do two inquiries to cover cases with strange equipment on previous ID */
-		/* blocking the ACSI bus (like the SLMC804 laser printer controller...   */
-		inquiry(i, phys_nic_packet);
-		if (!inquiry(i, phys_nic_packet)) {
-			lance_target = i;
-			break;
-		}
-	}
-
-	if (!!NET_DEBUG)
-		printk("ID: %d\n",i);
-
-	if (lance_target >= 0) {
-		if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet)))
-			lance_target = -1;
-		else
-			memcpy (station_addr, hwaddr, ETH_ALEN);
-	}
-
-	ENABLE_IRQ();
-	stdma_release();
-
-	if (lance_target < 0) {
-		printk("No PAM's Net/GK found.\n");
-		free_netdev(dev);
-		return ERR_PTR(-ENODEV);
-	}
-
-	if (pamsnet_debug > 0 && version_printed++ == 0)
-		printk(version);
-
-	printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n",
-		dev->name, "PAM's Net/GK", lance_target,
-		station_addr[0], station_addr[1], station_addr[2],
-		station_addr[3], station_addr[4], station_addr[5]);
-
-	/* Initialize the device structure. */
-	dev->open		= pamsnet_open;
-	dev->stop		= pamsnet_close;
-	dev->hard_start_xmit	= pamsnet_send_packet;
-	dev->get_stats		= net_get_stats;
-
-	/* Fill in the fields of the device structure with ethernet-generic
-	 * values. This should be in a common file instead of per-driver.
-	 */
-
-	for (i = 0; i < ETH_ALEN; i++) {
-#if 0
-		dev->broadcast[i] = 0xff;
-#endif
-		dev->dev_addr[i]  = station_addr[i];
-	}
-	err = register_netdev(dev);
-	if (!err)
-		return dev;
-
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
- */
-static int
-pamsnet_open(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (pamsnet_debug > 0)
-		printk("pamsnet_open\n");
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-
-	/* Reset the hardware here.
-	 */
-	if (!if_up)
-		start(lance_target);
-	if_up = 1;
-	lp->open_time = 0;	/*jiffies*/
-	lp->poll_time = MAX_POLL_TIME;
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	ENABLE_IRQ();
-	stdma_release();
-	pamsnet_timer.data = (long)dev;
-	pamsnet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&pamsnet_timer);
-	return 0;
-}
-
-static int
-pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	 */
-	local_irq_save(flags);
-
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		lp->stats.tx_errors++;
-	}
-	else {
-		int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-		unsigned long buf = virt_to_phys(skb->data);
-		int stat;
-
-		stdma_lock(pamsnet_intr, NULL);
-		DISABLE_IRQ();
-
-		local_irq_restore(flags);
-		if( !STRAM_ADDR(buf+length-1) ) {
-			skb_copy_from_linear_data(skb, nic_packet->buffer,
-						  length);
-			buf = (unsigned long)phys_nic_packet;
-		}
-
-		dma_cache_maintenance(buf, length, 1);
-
-		stat = sendpkt(lance_target, (unsigned char *)buf, length);
-		ENABLE_IRQ();
-		stdma_release();
-
-		dev->trans_start = jiffies;
-		dev->tbusy	 = 0;
-		lp->stats.tx_packets++;
-		lp->stats.tx_bytes+=length;
-	}
-	dev_kfree_skb(skb);
-
-	return 0;
-}
-
-/* We have a good packet(s), get it/them out of the buffers.
- */
-static void
-pamsnet_poll_rx(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int boguscount;
-	int pkt_len;
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	/* ++roman: Take care at locking the ST-DMA... This must be done with ints
-	 * off, since otherwise an int could slip in between the question and the
-	 * locking itself, and then we'd go to sleep... And locking itself is
-	 * necessary to keep the floppy_change timer from working with ST-DMA
-	 * registers. */
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		return;
-	}
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-	local_irq_restore(flags);
-
-	boguscount = testpkt(lance_target);
-	if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
-
-	while(boguscount--) {
-		pkt_len = receivepkt(lance_target, phys_nic_packet);
-
-		if( pkt_len < 60 ) break;
-
-		/* Good packet... */
-
-		dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0);
-
-		lp->poll_time = pamsnet_min_poll_time;    /* fast poll */
-		if( pkt_len >= 60 && pkt_len <= 2048 ) {
-			if (pkt_len > 1514)
-				pkt_len = 1514;
-
-			/* Malloc up new buffer.
-			 */
-			skb = alloc_skb(pkt_len, GFP_ATOMIC);
-			if (skb == NULL) {
-				printk("%s: Memory squeeze, dropping packet.\n",
-					dev->name);
-				lp->stats.rx_dropped++;
-				break;
-			}
-			skb->len = pkt_len;
-			skb->dev = dev;
-
-			/* 'skb->data' points to the start of sk_buff data area.
-			 */
-			skb_copy_to_linear_data(skb, nic_packet->buffer,
-						pkt_len);
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			lp->stats.rx_packets++;
-			lp->stats.rx_bytes+=pkt_len;
-		}
-	}
-
-	/* If any worth-while packets have been received, dev_rint()
-	   has done a mark_bh(INET_BH) for us and will work on them
-	   when we get to the bottom-half routine.
-	 */
-
-	ENABLE_IRQ();
-	stdma_release();
-	return;
-}
-
-/* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter,
- * passes them to the higher layers and restarts the timer.
- */
-static void
-pamsnet_tick(unsigned long data)
-{
-	struct net_device	 *dev = (struct net_device *)data;
-	struct net_local *lp = netdev_priv(dev);
-
-	if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 )
-		printk("pamsnet_tick: %ld\n", lp->open_time);
-
-	pamsnet_poll_rx(dev);
-
-	pamsnet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&pamsnet_timer);
-}
-
-/* The inverse routine to pamsnet_open().
- */
-static int
-pamsnet_close(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (pamsnet_debug > 0)
-		printk("pamsnet_close, open_time=%ld\n", lp->open_time);
-	del_timer(&pamsnet_timer);
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-
-	if (if_up)
-		stop(lance_target);
-	if_up = 0;
-
-	lp->open_time = 0;
-
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	ENABLE_IRQ();
-	stdma_release();
-	return 0;
-}
-
-/* Get the current statistics.
-   This may be called with the card open or closed.
- */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	return &lp->stats;
-}
-
-
-#ifdef MODULE
-
-static struct net_device *pam_dev;
-
-int init_module(void)
-{
-	pam_dev = pamsnet_probe(-1);
-	if (IS_ERR(pam_dev))
-		return PTR_ERR(pam_dev);
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	unregister_netdev(pam_dev);
-	free_netdev(pam_dev);
-}
-
-#endif /* MODULE */
-
-/* Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
-	-b m68k-linuxaout -Wall -Wstrict-prototypes -O2
-	-fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
index df4c1a0..ff4765f6 100644
--- a/drivers/net/atl1/atl1.h
+++ b/drivers/net/atl1/atl1.h
@@ -43,6 +43,7 @@
 struct atl1_adapter;
 
 #define ATL1_MAX_INTR		3
+#define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */
 
 #define ATL1_DEFAULT_TPD	256
 #define ATL1_MAX_TPD		1024
@@ -57,29 +58,45 @@
 #define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
 
 /*
+ * This detached comment is preserved for documentation purposes only.
+ * It was originally attached to some code that got deleted, but seems
+ * important enough to keep around...
+ *
+ * <begin detached comment>
  * Some workarounds require millisecond delays and are run during interrupt
  * context.  Most notably, when establishing link, the phy may need tweaking
  * but cannot process phy register reads/writes faster than millisecond
  * intervals...and we establish link due to a "link status change" interrupt.
+ * <end detached comment>
  */
 
 /*
- * wrapper around a pointer to a socket buffer,
- * so a DMA handle can be stored along with the buffer
+ * atl1_ring_header represents a single, contiguous block of DMA space
+ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+ * message blocks (cmb, smb) described below
+ */
+struct atl1_ring_header {
+	void *desc;		/* virtual address */
+	dma_addr_t dma;		/* physical address*/
+	unsigned int size;	/* length in bytes */
+};
+
+/*
+ * atl1_buffer is wrapper around a pointer to a socket buffer
+ * so a DMA handle can be stored along with the skb
  */
 struct atl1_buffer {
-	struct sk_buff *skb;
-	u16 length;
-	u16 alloced;
+	struct sk_buff *skb;	/* socket buffer */
+	u16 length;		/* rx buffer length */
+	u16 alloced;		/* 1 if skb allocated */
 	dma_addr_t dma;
 };
 
-#define MAX_TX_BUF_LEN		0x3000	/* 12KB */
-
+/* transmit packet descriptor (tpd) ring */
 struct atl1_tpd_ring {
-	void *desc;		/* pointer to the descriptor ring memory */
-	dma_addr_t dma;		/* physical adress of the descriptor ring */
-	u16 size;		/* length of descriptor ring in bytes */
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
 	u16 count;		/* number of descriptors in the ring */
 	u16 hw_idx;		/* hardware index */
 	atomic_t next_to_clean;
@@ -87,36 +104,34 @@
 	struct atl1_buffer *buffer_info;
 };
 
+/* receive free descriptor (rfd) ring */
 struct atl1_rfd_ring {
-	void *desc;
-	dma_addr_t dma;
-	u16 size;
-	u16 count;
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
 	atomic_t next_to_use;
 	u16 next_to_clean;
 	struct atl1_buffer *buffer_info;
 };
 
+/* receive return descriptor (rrd) ring */
 struct atl1_rrd_ring {
-	void *desc;
-	dma_addr_t dma;
-	unsigned int size;
-	u16 count;
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	unsigned int size;	/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
 	u16 next_to_use;
 	atomic_t next_to_clean;
 };
 
-struct atl1_ring_header {
-	void *desc;		/* pointer to the descriptor ring memory */
-	dma_addr_t dma;		/* physical adress of the descriptor ring */
-	unsigned int size;	/* length of descriptor ring in bytes */
-};
-
+/* coalescing message block (cmb) */
 struct atl1_cmb {
 	struct coals_msg_block *cmb;
 	dma_addr_t dma;
 };
 
+/* statistics message block (smb) */
 struct atl1_smb {
 	struct stats_msg_block *smb;
 	dma_addr_t dma;
@@ -141,24 +156,26 @@
 	u64 tx_aborted_errors;
 	u64 tx_window_errors;
 	u64 tx_carrier_errors;
-
-	u64 tx_pause;		/* num Pause packet transmitted. */
-	u64 excecol;		/* num tx packets aborted due to excessive collisions. */
-	u64 deffer;		/* num deferred tx packets */
-	u64 scc;		/* num packets subsequently transmitted successfully w/ single prior collision. */
-	u64 mcc;		/* num packets subsequently transmitted successfully w/ multiple prior collisions. */
+	u64 tx_pause;		/* num pause packets transmitted. */
+	u64 excecol;		/* num tx packets w/ excessive collisions. */
+	u64 deffer;		/* num tx packets deferred */
+	u64 scc;		/* num packets subsequently transmitted
+				 * successfully w/ single prior collision. */
+	u64 mcc;		/* num packets subsequently transmitted
+				 * successfully w/ multiple prior collisions. */
 	u64 latecol;		/* num tx packets  w/ late collisions. */
-	u64 tx_underun;		/* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
-	u64 tx_trunc;		/* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */
+	u64 tx_underun;		/* num tx packets aborted due to transmit
+				 * FIFO underrun, or TRD FIFO underrun */
+	u64 tx_trunc;		/* num tx packets truncated due to size
+				 * exceeding MTU, regardless whether truncated
+				 * by the chip or not. (The name doesn't really
+				 * reflect the meaning in this case.) */
 	u64 rx_pause;		/* num Pause packets received. */
 	u64 rx_rrd_ov;
 	u64 rx_trunc;
 };
 
-/* board specific private data structure */
-#define ATL1_REGS_LEN	8
-
-/* Structure containing variables used by the shared code */
+/* hardware structure */
 struct atl1_hw {
 	u8 __iomem *hw_addr;
 	struct atl1_adapter *back;
@@ -167,24 +184,35 @@
 	enum atl1_dma_req_block dmar_block;
 	enum atl1_dma_req_block dmaw_block;
 	u8 preamble_len;
-	u8 max_retry;		/* Retransmission maximum, after which the packet will be discarded */
-	u8 jam_ipg;		/* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */
-	u8 ipgt;		/* Desired back to back inter-packet gap. The default is 96-bit time */
-	u8 min_ifg;		/* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */
+	u8 max_retry;		/* Retransmission maximum, after which the
+				 * packet will be discarded */
+	u8 jam_ipg;		/* IPG to start JAM for collision based flow
+				 * control in half-duplex mode. In units of
+				 * 8-bit time */
+	u8 ipgt;		/* Desired back to back inter-packet gap.
+				 * The default is 96-bit time */
+	u8 min_ifg;		/* Minimum number of IFG to enforce in between
+				 * receive frames. Frame gap below such IFP
+				 * is dropped */
 	u8 ipgr1;		/* 64bit Carrier-Sense window */
 	u8 ipgr2;		/* 96-bit IPG window */
-	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */
-	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */
+	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
+				 * burst. Each TPD is 16 bytes long */
+	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
+				 * burst. Each RFD is 12 bytes long */
 	u8 rfd_fetch_gap;
-	u8 rrd_burst;		/* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */
+	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
+				 * in a burst. Each RRD is 16 bytes long */
 	u8 tpd_fetch_th;
 	u8 tpd_fetch_gap;
 	u16 tx_jumbo_task_th;
-	u16 txf_burst;		/* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is
-				   8 bytes long */
-	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */
+	u16 txf_burst;		/* Number of data bytes to read in a cache-
+				 * aligned burst. Each SRAM entry is 8 bytes */
+	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
+				 * packets should add 4 bytes */
 	u16 rx_jumbo_lkah;
-	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after every 512ns passes. */
+	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
+				 * every 512ns passes. */
 	u16 lcol;		/* Collision Window */
 
 	u16 cmb_tpd;
@@ -194,48 +222,35 @@
 	u32 smb_timer;
 	u16 media_type;
 	u16 autoneg_advertised;
-	u16 pci_cmd_word;
 
 	u16 mii_autoneg_adv_reg;
 	u16 mii_1000t_ctrl_reg;
 
-	u32 mem_rang;
-	u32 txcw;
 	u32 max_frame_size;
 	u32 min_frame_size;
-	u32 mc_filter_type;
-	u32 num_mc_addrs;
-	u32 collision_delta;
-	u32 tx_packet_delta;
-	u16 phy_spd_default;
 
 	u16 dev_rev;
 
 	/* spi flash */
 	u8 flash_vendor;
 
-	u8 dma_fairness;
 	u8 mac_addr[ETH_ALEN];
 	u8 perm_mac_addr[ETH_ALEN];
 
-	/* bool phy_preamble_sup; */
 	bool phy_configured;
 };
 
 struct atl1_adapter {
-	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
 	struct net_device_stats net_stats;
 	struct atl1_sft_stats soft_stats;
-
 	struct vlan_group *vlgrp;
 	u32 rx_buffer_len;
 	u32 wol;
 	u16 link_speed;
 	u16 link_duplex;
 	spinlock_t lock;
-	atomic_t irq_sem;
 	struct work_struct tx_timeout_task;
 	struct work_struct link_chg_task;
 	struct work_struct pcie_dma_to_rst_task;
@@ -243,9 +258,7 @@
 	struct timer_list phy_config_timer;
 	bool phy_timer_pending;
 
-	bool mac_disabled;
-
-	/* All descriptor rings' memory */
+	/* all descriptor rings' memory */
 	struct atl1_ring_header ring_header;
 
 	/* TX */
@@ -258,25 +271,16 @@
 	u64 hw_csum_err;
 	u64 hw_csum_good;
 
-	u32 gorcl;
-	u64 gorcl_old;
-
-	/* Interrupt Moderator timer ( 2us resolution) */
-	u16 imt;
-	/* Interrupt Clear timer (2us resolution) */
-	u16 ict;
-
-	/* MII interface info */
-	struct mii_if_info mii;
+	u16 imt;	/* interrupt moderator timer (2us resolution */
+	u16 ict;	/* interrupt clear timer (2us resolution */
+	struct mii_if_info mii;		/* MII interface info */
 
 	/* structs defined in atl1_hw.h */
-	u32 bd_number;		/* board number */
+	u32 bd_number;			/* board number */
 	bool pci_using_64;
 	struct atl1_hw hw;
 	struct atl1_smb smb;
 	struct atl1_cmb cmb;
-
-	u32 pci_state[16];
 };
 
 #endif	/* _ATL1_H_ */
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 501919e..fd1e156 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -38,7 +38,7 @@
  * TODO:
  * Fix TSO; tx performance is horrible with TSO enabled.
  * Wake on LAN.
- * Add more ethtool functions, including set ring parameters.
+ * Add more ethtool functions.
  * Fix abstruse irq enable/disable condition described here:
  *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
  *
@@ -75,6 +75,7 @@
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/mii.h>
+#include <linux/interrupt.h>
 #include <net/checksum.h>
 
 #include <asm/atomic.h>
@@ -158,13 +159,70 @@
 	hw->cmb_tx_timer = 1;	/* about 2us */
 	hw->smb_timer = 100000;	/* about 200ms */
 
-	atomic_set(&adapter->irq_sem, 0);
 	spin_lock_init(&adapter->lock);
 	spin_lock_init(&adapter->mb_lock);
 
 	return 0;
 }
 
+static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+
+	return result;
+}
+
+static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
+	int val)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	atl1_write_phy_reg(&adapter->hw, reg_num, val);
+}
+
+/*
+ * atl1_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	int retval;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+
+	return retval;
+}
+
+/*
+ * atl1_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atl1_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 /*
  * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
  * @adapter: board private structure
@@ -188,19 +246,22 @@
 		goto err_nomem;
 	}
 	rfd_ring->buffer_info =
-	    (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+		(struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
 
-	/* real ring DMA buffer */
-	ring_header->size = size = sizeof(struct tx_packet_desc) *
-					tpd_ring->count
-	    + sizeof(struct rx_free_desc) * rfd_ring->count
-	    + sizeof(struct rx_return_desc) * rrd_ring->count
-	    + sizeof(struct coals_msg_block)
-	    + sizeof(struct stats_msg_block)
-	    + 40;		/* "40: for 8 bytes align" huh? -- CHS */
+	/* real ring DMA buffer
+	 * each ring/block may need up to 8 bytes for alignment, hence the
+	 * additional 40 bytes tacked onto the end.
+	 */
+	ring_header->size = size =
+		sizeof(struct tx_packet_desc) * tpd_ring->count
+		+ sizeof(struct rx_free_desc) * rfd_ring->count
+		+ sizeof(struct rx_return_desc) * rrd_ring->count
+		+ sizeof(struct coals_msg_block)
+		+ sizeof(struct stats_msg_block)
+		+ 40;
 
 	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
-						&ring_header->dma);
+		&ring_header->dma);
 	if (unlikely(!ring_header->desc)) {
 		dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
 		goto err_nomem;
@@ -214,8 +275,6 @@
 	tpd_ring->dma += offset;
 	tpd_ring->desc = (u8 *) ring_header->desc + offset;
 	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
 
 	/* init RFD ring */
 	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
@@ -223,9 +282,7 @@
 	rfd_ring->dma += offset;
 	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
 	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
-	rfd_ring->next_to_clean = 0;
-	/* rfd_ring->next_to_use = rfd_ring->count - 1; */
-	atomic_set(&rfd_ring->next_to_use, 0);
+
 
 	/* init RRD ring */
 	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
@@ -233,23 +290,22 @@
 	rrd_ring->dma += offset;
 	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
 	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
+
 
 	/* init CMB */
 	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
 	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
 	adapter->cmb.dma += offset;
-	adapter->cmb.cmb =
-	    (struct coals_msg_block *) ((u8 *) rrd_ring->desc +
-				   (rrd_ring->size + offset));
+	adapter->cmb.cmb = (struct coals_msg_block *)
+		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
 
 	/* init SMB */
 	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
 	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
 	adapter->smb.dma += offset;
 	adapter->smb.smb = (struct stats_msg_block *)
-	    ((u8 *) adapter->cmb.cmb + (sizeof(struct coals_msg_block) + offset));
+		((u8 *) adapter->cmb.cmb +
+		(sizeof(struct coals_msg_block) + offset));
 
 	return ATL1_SUCCESS;
 
@@ -258,14 +314,682 @@
 	return -ENOMEM;
 }
 
+void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+
+	rfd_ring->next_to_clean = 0;
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_rx_ring - Free RFD Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Rx ring sk_buffs */
+	for (i = 0; i < rfd_ring->count; i++) {
+		buffer_info = &rfd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_FROMDEVICE);
+			buffer_info->dma = 0;
+		}
+		if (buffer_info->skb) {
+			dev_kfree_skb(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * rfd_ring->count;
+	memset(rfd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(rfd_ring->desc, 0, rfd_ring->size);
+
+	rfd_ring->next_to_clean = 0;
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Tx ring sk_buffs */
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = 0;
+		}
+	}
+
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->skb) {
+			dev_kfree_skb_any(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * tpd_ring->count;
+	memset(tpd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(tpd_ring->desc, 0, tpd_ring->size);
+
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+void atl1_free_ring_resources(struct atl1_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_ring_header *ring_header = &adapter->ring_header;
+
+	atl1_clean_tx_ring(adapter);
+	atl1_clean_rx_ring(adapter);
+
+	kfree(tpd_ring->buffer_info);
+	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+		ring_header->dma);
+
+	tpd_ring->buffer_info = NULL;
+	tpd_ring->desc = NULL;
+	tpd_ring->dma = 0;
+
+	rfd_ring->buffer_info = NULL;
+	rfd_ring->desc = NULL;
+	rfd_ring->dma = 0;
+
+	rrd_ring->desc = NULL;
+	rrd_ring->dma = 0;
+}
+
+static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+{
+	u32 value;
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	/* Config MAC CTRL Register */
+	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+	/* duplex */
+	if (FULL_DUPLEX == adapter->link_duplex)
+		value |= MAC_CTRL_DUPLX;
+	/* speed */
+	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+		  MAC_CTRL_SPEED_SHIFT);
+	/* flow control */
+	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+	/* PAD & CRC */
+	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+	/* preamble length */
+	value |= (((u32) adapter->hw.preamble_len
+		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+	/* vlan */
+	if (adapter->vlgrp)
+		value |= MAC_CTRL_RMV_VLAN;
+	/* rx checksum
+	   if (adapter->rx_csum)
+	   value |= MAC_CTRL_RX_CHKSUM_EN;
+	 */
+	/* filter mode */
+	value |= MAC_CTRL_BC_EN;
+	if (netdev->flags & IFF_PROMISC)
+		value |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI)
+		value |= MAC_CTRL_MC_ALL_EN;
+	/* value |= MAC_CTRL_LOOPBACK; */
+	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+}
+
+/*
+ * atl1_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_set_mac(struct net_device *netdev, void *p)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atl1_set_mac_addr(&adapter->hw);
+	return 0;
+}
+
+static u32 atl1_check_link(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	u32 ret_val;
+	u16 speed, duplex, phy_data;
+	int reconfig = 0;
+
+	/* MII_BMSR must read twice */
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */
+		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+			dev_info(&adapter->pdev->dev, "link is down\n");
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+		return ATL1_SUCCESS;
+	}
+
+	/* Link Up */
+	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+	if (ret_val)
+		return ret_val;
+
+	switch (hw->media_type) {
+	case MEDIA_TYPE_1000M_FULL:
+		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_FULL:
+		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_HALF:
+		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_FULL:
+		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_HALF:
+		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	}
+
+	/* link result is our setting */
+	if (!reconfig) {
+		if (adapter->link_speed != speed
+		    || adapter->link_duplex != duplex) {
+			adapter->link_speed = speed;
+			adapter->link_duplex = duplex;
+			atl1_setup_mac_ctrl(adapter);
+			dev_info(&adapter->pdev->dev,
+				"%s link is up %d Mbps %s\n",
+				netdev->name, adapter->link_speed,
+				adapter->link_duplex == FULL_DUPLEX ?
+				"full duplex" : "half duplex");
+		}
+		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+		return ATL1_SUCCESS;
+	}
+
+	/* change orignal link status */
+	if (netif_carrier_ok(netdev)) {
+		adapter->link_speed = SPEED_0;
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+	}
+
+	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			           MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:	/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+		return ATL1_SUCCESS;
+	}
+
+	/* auto-neg, insert timer to re-config phy */
+	if (!adapter->phy_timer_pending) {
+		adapter->phy_timer_pending = true;
+		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+	}
+
+	return ATL1_SUCCESS;
+}
+
+static void atl1_check_for_link(struct atl1_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	u16 phy_data = 0;
+
+	spin_lock(&adapter->lock);
+	adapter->phy_timer_pending = false;
+	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->lock);
+
+	/* notify upper layer link down ASAP */
+	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */
+		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+			dev_info(&adapter->pdev->dev, "%s link is down\n",
+				netdev->name);
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	}
+	schedule_work(&adapter->link_chg_task);
+}
+
+/*
+ * atl1_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1_set_multi(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr;
+	u32 rctl;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+	if (netdev->flags & IFF_PROMISC)
+		rctl |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI) {
+		rctl |= MAC_CTRL_MC_ALL_EN;
+		rctl &= ~MAC_CTRL_PROMIS_EN;
+	} else
+		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+
+	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+
+	/* clear the old settings from the multicast hash table */
+	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+	/* compute mc addresses' hash value ,and put it into hash table */
+	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
+		atl1_hash_set(hw, hash_value);
+	}
+}
+
+/*
+ * atl1_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int old_mtu = netdev->mtu;
+	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+
+	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+		return -EINVAL;
+	}
+
+	adapter->hw.max_frame_size = max_frame;
+	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+	adapter->rx_buffer_len = (max_frame + 7) & ~7;
+	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+
+	netdev->mtu = new_mtu;
+	if ((old_mtu != new_mtu) && netif_running(netdev)) {
+		atl1_down(adapter);
+		atl1_up(adapter);
+	}
+
+	return 0;
+}
+
+static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+{
+	u32 hi, lo, value;
+
+	/* RFD Flow Control */
+	value = adapter->rfd_ring.count;
+	hi = value / 16;
+	if (hi < 2)
+		hi = 2;
+	lo = value * 7 / 8;
+
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = adapter->rrd_ring.count;
+	lo = value / 16;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+static void set_flow_ctrl_new(struct atl1_hw *hw)
+{
+	u32 hi, lo, value;
+
+	/* RXF Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+	lo = value / 16;
+	if (lo < 192)
+		lo = 192;
+	hi = value * 7 / 8;
+	if (hi < lo)
+		hi = lo + 16;
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+	lo = value / 8;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	if (hi < lo)
+		hi = lo + 3;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+/*
+ * atl1_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static u32 atl1_configure(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	u32 value;
+
+	/* clear interrupt status */
+	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+
+	/* set MAC Address */
+	value = (((u32) hw->mac_addr[2]) << 24) |
+		(((u32) hw->mac_addr[3]) << 16) |
+		(((u32) hw->mac_addr[4]) << 8) |
+		(((u32) hw->mac_addr[5]));
+	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+
+	/* tx / rx ring */
+
+	/* HI base address */
+	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+	/* LO base address */
+	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+
+	/* element count */
+	value = adapter->rrd_ring.count;
+	value <<= 16;
+	value += adapter->rfd_ring.count;
+	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
+		REG_DESC_TPD_RING_SIZE);
+
+	/* Load Ptr */
+	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+
+	/* config Mailbox */
+	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+		((atomic_read(&adapter->rrd_ring.next_to_clean)
+		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+		((atomic_read(&adapter->rfd_ring.next_to_use)
+		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAILBOX);
+
+	/* config IPG/IFG */
+	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+		 << MAC_IPG_IFG_IPGT_SHIFT) |
+		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+		<< MAC_IPG_IFG_MIFG_SHIFT) |
+		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+		<< MAC_IPG_IFG_IPGR1_SHIFT) |
+		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+		<< MAC_IPG_IFG_IPGR2_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+
+	/* config  Half-Duplex Control */
+	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+
+	/* set Interrupt Moderator Timer */
+	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+
+	/* set Interrupt Clear Timer */
+	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+
+	/* set MTU, 4 : VLAN */
+	iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU);
+
+	/* jumbo size & rrd retirement timer */
+	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+		 << RXQ_JMBOSZ_TH_SHIFT) |
+		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+		<< RXQ_JMBO_LKAH_SHIFT) |
+		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+		<< RXQ_RRD_TIMER_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+
+	/* Flow Control */
+	switch (hw->dev_rev) {
+	case 0x8001:
+	case 0x9001:
+	case 0x9002:
+	case 0x9003:
+		set_flow_ctrl_old(adapter);
+		break;
+	default:
+		set_flow_ctrl_new(hw);
+		break;
+	}
+
+	/* config TXQ */
+	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
+		TXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+
+	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+		<< TX_JUMBO_TASK_TH_SHIFT) |
+		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+		<< TX_TPD_MIN_IPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+
+	/* config RXQ */
+	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
+		RXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+
+	/* config DMA Engine */
+	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+		((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
+		DMA_CTRL_DMAW_EN;
+	value |= (u32) hw->dma_ord;
+	if (atl1_rcb_128 == hw->rcb_value)
+		value |= DMA_CTRL_RCB_VALUE;
+	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+
+	/* config CMB / SMB */
+	value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16);
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+
+	/* --- enable CMB / SMB */
+	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+
+	value = ioread32(adapter->hw.hw_addr + REG_ISR);
+	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+		value = 1;	/* config failed */
+	else
+		value = 0;
+
+	/* clear all interrupt status */
+	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+	return value;
+}
+
+/*
+ * atl1_pcie_patch - Patch for PCIE module
+ */
+static void atl1_pcie_patch(struct atl1_adapter *adapter)
+{
+	u32 value;
+
+	/* much vendor magic here */
+	value = 0x6500;
+	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+	/* pcie flow control mode change */
+	value = ioread32(adapter->hw.hw_addr + 0x1008);
+	value |= 0x8000;
+	iowrite32(value, adapter->hw.hw_addr + 0x1008);
+}
+
+/*
+ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+ * on PCI Command register is disable.
+ * The function enable this bit.
+ * Brackett, 2006/03/15
+ */
+static void atl1_via_workaround(struct atl1_adapter *adapter)
+{
+	unsigned long value;
+
+	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+	if (value & PCI_COMMAND_INTX_DISABLE)
+		value &= ~PCI_COMMAND_INTX_DISABLE;
+	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+}
+
 /*
  * atl1_irq_enable - Enable default interrupt generation settings
  * @adapter: board private structure
  */
 static void atl1_irq_enable(struct atl1_adapter *adapter)
 {
-	if (likely(!atomic_dec_and_test(&adapter->irq_sem)))
-		iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+	ioread32(adapter->hw.hw_addr + REG_IMR);
+}
+
+/*
+ * atl1_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static void atl1_irq_disable(struct atl1_adapter *adapter)
+{
+	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+	ioread32(adapter->hw.hw_addr + REG_IMR);
+	synchronize_irq(adapter->pdev->irq);
 }
 
 static void atl1_clear_phy_int(struct atl1_adapter *adapter)
@@ -288,25 +1012,19 @@
 	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
 	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
 	adapter->soft_stats.multicast += smb->rx_mcast;
-	adapter->soft_stats.collisions += (smb->tx_1_col +
-					   smb->tx_2_col * 2 +
-					   smb->tx_late_col +
-					   smb->tx_abort_col *
-					   adapter->hw.max_retry);
+	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
+		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
 
 	/* Rx Errors */
-	adapter->soft_stats.rx_errors += (smb->rx_frag +
-					  smb->rx_fcs_err +
-					  smb->rx_len_err +
-					  smb->rx_sz_ov +
-					  smb->rx_rxf_ov +
-					  smb->rx_rrd_ov + smb->rx_align_err);
+	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
+		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
+		smb->rx_rrd_ov + smb->rx_align_err);
 	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
 	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
 	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
 	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
 	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
-						 smb->rx_rxf_ov);
+		smb->rx_rxf_ov);
 
 	adapter->soft_stats.rx_pause += smb->rx_pause;
 	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
@@ -314,8 +1032,7 @@
 
 	/* Tx Errors */
 	adapter->soft_stats.tx_errors += (smb->tx_late_col +
-					  smb->tx_abort_col +
-					  smb->tx_underrun + smb->tx_trunc);
+		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
 	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
 	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
 	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
@@ -337,36 +1054,101 @@
 	adapter->net_stats.collisions = adapter->soft_stats.collisions;
 	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
 	adapter->net_stats.rx_over_errors =
-	    adapter->soft_stats.rx_missed_errors;
+		adapter->soft_stats.rx_missed_errors;
 	adapter->net_stats.rx_length_errors =
-	    adapter->soft_stats.rx_length_errors;
+		adapter->soft_stats.rx_length_errors;
 	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
 	adapter->net_stats.rx_frame_errors =
-	    adapter->soft_stats.rx_frame_errors;
+		adapter->soft_stats.rx_frame_errors;
 	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
 	adapter->net_stats.rx_missed_errors =
-	    adapter->soft_stats.rx_missed_errors;
+		adapter->soft_stats.rx_missed_errors;
 	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
 	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
 	adapter->net_stats.tx_aborted_errors =
-	    adapter->soft_stats.tx_aborted_errors;
+		adapter->soft_stats.tx_aborted_errors;
 	adapter->net_stats.tx_window_errors =
-	    adapter->soft_stats.tx_window_errors;
+		adapter->soft_stats.tx_window_errors;
 	adapter->net_stats.tx_carrier_errors =
-	    adapter->soft_stats.tx_carrier_errors;
+		adapter->soft_stats.tx_carrier_errors;
+}
+
+/*
+ * atl1_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	return &adapter->net_stats;
+}
+
+static void atl1_update_mailbox(struct atl1_adapter *adapter)
+{
+	unsigned long flags;
+	u32 tpd_next_to_use;
+	u32 rfd_next_to_use;
+	u32 rrd_next_to_clean;
+	u32 value;
+
+	spin_lock_irqsave(&adapter->mb_lock, flags);
+
+	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+
+	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+		MB_RFD_PROD_INDX_SHIFT) |
+		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+		MB_RRD_CONS_INDX_SHIFT) |
+		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+		MB_TPD_PROD_INDX_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+
+	spin_unlock_irqrestore(&adapter->mb_lock, flags);
+}
+
+static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
+	struct rx_return_desc *rrd, u16 offset)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+
+	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
+		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
+		if (++rfd_ring->next_to_clean == rfd_ring->count) {
+			rfd_ring->next_to_clean = 0;
+		}
+	}
+}
+
+static void atl1_update_rfd_index(struct atl1_adapter *adapter,
+	struct rx_return_desc *rrd)
+{
+	u16 num_buf;
+
+	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
+		adapter->rx_buffer_len;
+	if (rrd->num_buf == num_buf)
+		/* clean alloc flag for bad rrd */
+		atl1_clean_alloc_flag(adapter, rrd, num_buf);
 }
 
 static void atl1_rx_checksum(struct atl1_adapter *adapter,
-					struct rx_return_desc *rrd,
-					struct sk_buff *skb)
+	struct rx_return_desc *rrd, struct sk_buff *skb)
 {
+	struct pci_dev *pdev = adapter->pdev;
+
 	skb->ip_summed = CHECKSUM_NONE;
 
 	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
 		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
 					ERR_FLAG_CODE | ERR_FLAG_OV)) {
 			adapter->hw_csum_err++;
-			dev_dbg(&adapter->pdev->dev, "rx checksum error\n");
+			dev_printk(KERN_DEBUG, &pdev->dev,
+				"rx checksum error\n");
 			return;
 		}
 	}
@@ -385,7 +1167,7 @@
 	}
 
 	/* IPv4, but hardware thinks its checksum is wrong */
-	dev_dbg(&adapter->pdev->dev,
+	dev_printk(KERN_DEBUG, &pdev->dev,
 		"hw csum wrong, pkt_flag:%x, err_flag:%x\n",
 		rrd->pkt_flg, rrd->err_flg);
 	skb->ip_summed = CHECKSUM_COMPLETE;
@@ -500,34 +1282,17 @@
 			/* rrd seems to be bad */
 			if (unlikely(i-- > 0)) {
 				/* rrd may not be DMAed completely */
-				dev_dbg(&adapter->pdev->dev,
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
 					"incomplete RRD DMA transfer\n");
 				udelay(1);
 				goto chk_rrd;
 			}
 			/* bad rrd */
-			dev_dbg(&adapter->pdev->dev, "bad RRD\n");
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"bad RRD\n");
 			/* see if update RFD index */
-			if (rrd->num_buf > 1) {
-				u16 num_buf;
-				num_buf =
-				    (rrd->xsz.xsum_sz.pkt_size +
-				     adapter->rx_buffer_len -
-				     1) / adapter->rx_buffer_len;
-				if (rrd->num_buf == num_buf) {
-					/* clean alloc flag for bad rrd */
-					while (rfd_ring->next_to_clean !=
-					       (rrd->buf_indx + num_buf)) {
-						rfd_ring->buffer_info[rfd_ring->
-								      next_to_clean].alloced = 0;
-						if (++rfd_ring->next_to_clean ==
-						    rfd_ring->count) {
-							rfd_ring->
-							    next_to_clean = 0;
-						}
-					}
-				}
-			}
+			if (rrd->num_buf > 1)
+				atl1_update_rfd_index(adapter, rrd);
 
 			/* update rrd */
 			rrd->xsz.valid = 0;
@@ -541,12 +1306,7 @@
 		}
 rrd_ok:
 		/* clean alloc flag for bad rrd */
-		while (rfd_ring->next_to_clean != rrd->buf_indx) {
-			rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced =
-			    0;
-			if (++rfd_ring->next_to_clean == rfd_ring->count)
-				rfd_ring->next_to_clean = 0;
-		}
+		atl1_clean_alloc_flag(adapter, rrd, 0);
 
 		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
 		if (++rfd_ring->next_to_clean == rfd_ring->count)
@@ -662,580 +1422,13 @@
 		netif_wake_queue(adapter->netdev);
 }
 
-static void atl1_check_for_link(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u16 phy_data = 0;
-
-	spin_lock(&adapter->lock);
-	adapter->phy_timer_pending = false;
-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	spin_unlock(&adapter->lock);
-
-	/* notify upper layer link down ASAP */
-	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */
-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
-			dev_info(&adapter->pdev->dev, "%s link is down\n",
-				netdev->name);
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-	}
-	schedule_work(&adapter->link_chg_task);
-}
-
-/*
- * atl1_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl1_intr(int irq, void *data)
-{
-	/*struct atl1_adapter *adapter = ((struct net_device *)data)->priv;*/
-	struct atl1_adapter *adapter = netdev_priv(data);
-	u32 status;
-	u8 update_rx;
-	int max_ints = 10;
-
-	status = adapter->cmb.cmb->int_stats;
-	if (!status)
-		return IRQ_NONE;
-
-	update_rx = 0;
-
-	do {
-		/* clear CMB interrupt status at once */
-		adapter->cmb.cmb->int_stats = 0;
-
-		if (status & ISR_GPHY)	/* clear phy status */
-			atl1_clear_phy_int(adapter);
-
-		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
-		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
-
-		/* check if SMB intr */
-		if (status & ISR_SMB)
-			atl1_inc_smb(adapter);
-
-		/* check if PCIE PHY Link down */
-		if (status & ISR_PHY_LINKDOWN) {
-			dev_dbg(&adapter->pdev->dev, "pcie phy link down %x\n",
-				status);
-			if (netif_running(adapter->netdev)) {	/* reset MAC */
-				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-				schedule_work(&adapter->pcie_dma_to_rst_task);
-				return IRQ_HANDLED;
-			}
-		}
-
-		/* check if DMA read/write error ? */
-		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-			dev_dbg(&adapter->pdev->dev,
-				"pcie DMA r/w error (status = 0x%x)\n",
-				status);
-			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-			schedule_work(&adapter->pcie_dma_to_rst_task);
-			return IRQ_HANDLED;
-		}
-
-		/* link event */
-		if (status & ISR_GPHY) {
-			adapter->soft_stats.tx_carrier_errors++;
-			atl1_check_for_link(adapter);
-		}
-
-		/* transmit event */
-		if (status & ISR_CMB_TX)
-			atl1_intr_tx(adapter);
-
-		/* rx exception */
-		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
-			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-				ISR_HOST_RRD_OV))
-				dev_dbg(&adapter->pdev->dev,
-					"rx exception, ISR = 0x%x\n", status);
-			atl1_intr_rx(adapter);
-		}
-
-		if (--max_ints < 0)
-			break;
-
-	} while ((status = adapter->cmb.cmb->int_stats));
-
-	/* re-enable Interrupt */
-	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
-	return IRQ_HANDLED;
-}
-
-/*
- * atl1_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- */
-static void atl1_set_multi(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	struct dev_mc_list *mc_ptr;
-	u32 rctl;
-	u32 hash_value;
-
-	/* Check for Promiscuous and All Multicast modes */
-	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
-	if (netdev->flags & IFF_PROMISC)
-		rctl |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI) {
-		rctl |= MAC_CTRL_MC_ALL_EN;
-		rctl &= ~MAC_CTRL_PROMIS_EN;
-	} else
-		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
-
-	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
-
-	/* clear the old settings from the multicast hash table */
-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
-
-	/* compute mc addresses' hash value ,and put it into hash table */
-	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
-		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
-		atl1_hash_set(hw, hash_value);
-	}
-}
-
-static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
-{
-	u32 value;
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	/* Config MAC CTRL Register */
-	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
-	/* duplex */
-	if (FULL_DUPLEX == adapter->link_duplex)
-		value |= MAC_CTRL_DUPLX;
-	/* speed */
-	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
-			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
-		  MAC_CTRL_SPEED_SHIFT);
-	/* flow control */
-	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-	/* PAD & CRC */
-	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-	/* preamble length */
-	value |= (((u32) adapter->hw.preamble_len
-		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-	/* vlan */
-	if (adapter->vlgrp)
-		value |= MAC_CTRL_RMV_VLAN;
-	/* rx checksum
-	   if (adapter->rx_csum)
-	   value |= MAC_CTRL_RX_CHKSUM_EN;
-	 */
-	/* filter mode */
-	value |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		value |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI)
-		value |= MAC_CTRL_MC_ALL_EN;
-	/* value |= MAC_CTRL_LOOPBACK; */
-	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
-}
-
-static u32 atl1_check_link(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 ret_val;
-	u16 speed, duplex, phy_data;
-	int reconfig = 0;
-
-	/* MII_BMSR must read twice */
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */
-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
-			dev_info(&adapter->pdev->dev, "link is down\n");
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-		return ATL1_SUCCESS;
-	}
-
-	/* Link Up */
-	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
-	if (ret_val)
-		return ret_val;
-
-	switch (hw->media_type) {
-	case MEDIA_TYPE_1000M_FULL:
-		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_FULL:
-		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_HALF:
-		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_FULL:
-		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_HALF:
-		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	}
-
-	/* link result is our setting */
-	if (!reconfig) {
-		if (adapter->link_speed != speed
-		    || adapter->link_duplex != duplex) {
-			adapter->link_speed = speed;
-			adapter->link_duplex = duplex;
-			atl1_setup_mac_ctrl(adapter);
-			dev_info(&adapter->pdev->dev,
-				"%s link is up %d Mbps %s\n",
-				netdev->name, adapter->link_speed,
-				adapter->link_duplex == FULL_DUPLEX ?
-				"full duplex" : "half duplex");
-		}
-		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */
-			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
-		}
-		return ATL1_SUCCESS;
-	}
-
-	/* change orignal link status */
-	if (netif_carrier_ok(netdev)) {
-		adapter->link_speed = SPEED_0;
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-	}
-
-	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
-	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			           MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:	/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-		return ATL1_SUCCESS;
-	}
-
-	/* auto-neg, insert timer to re-config phy */
-	if (!adapter->phy_timer_pending) {
-		adapter->phy_timer_pending = true;
-		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
-	}
-
-	return ATL1_SUCCESS;
-}
-
-static void set_flow_ctrl_old(struct atl1_adapter *adapter)
-{
-	u32 hi, lo, value;
-
-	/* RFD Flow Control */
-	value = adapter->rfd_ring.count;
-	hi = value / 16;
-	if (hi < 2)
-		hi = 2;
-	lo = value * 7 / 8;
-
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = adapter->rrd_ring.count;
-	lo = value / 16;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-static void set_flow_ctrl_new(struct atl1_hw *hw)
-{
-	u32 hi, lo, value;
-
-	/* RXF Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
-	lo = value / 16;
-	if (lo < 192)
-		lo = 192;
-	hi = value * 7 / 8;
-	if (hi < lo)
-		hi = lo + 16;
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
-	lo = value / 8;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	if (hi < lo)
-		hi = lo + 3;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-/*
- * atl1_configure - Configure Transmit&Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx /Rx unit of the MAC after a reset.
- */
-static u32 atl1_configure(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	u32 value;
-
-	/* clear interrupt status */
-	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
-
-	/* set MAC Address */
-	value = (((u32) hw->mac_addr[2]) << 24) |
-		(((u32) hw->mac_addr[3]) << 16) |
-		(((u32) hw->mac_addr[4]) << 8) |
-		(((u32) hw->mac_addr[5]));
-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
-	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
-
-	/* tx / rx ring */
-
-	/* HI base address */
-	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
-		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
-	/* LO base address */
-	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
-	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
-	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
-	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
-	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
-
-	/* element count */
-	value = adapter->rrd_ring.count;
-	value <<= 16;
-	value += adapter->rfd_ring.count;
-	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
-	iowrite32(adapter->tpd_ring.count, hw->hw_addr + REG_DESC_TPD_RING_SIZE);
-
-	/* Load Ptr */
-	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
-
-	/* config Mailbox */
-	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
-		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
-	    ((atomic_read(&adapter->rrd_ring.next_to_clean)
-	      & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
-	    ((atomic_read(&adapter->rfd_ring.next_to_use)
-	      & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAILBOX);
-
-	/* config IPG/IFG */
-	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
-		 << MAC_IPG_IFG_IPGT_SHIFT) |
-	    (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
-	     << MAC_IPG_IFG_MIFG_SHIFT) |
-	    (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
-	     << MAC_IPG_IFG_IPGR1_SHIFT) |
-	    (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
-	     << MAC_IPG_IFG_IPGR2_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
-
-	/* config  Half-Duplex Control */
-	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
-	    (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
-	     << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
-	    MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
-	    (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
-	    (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
-	     << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
-
-	/* set Interrupt Moderator Timer */
-	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
-	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
-
-	/* set Interrupt Clear Timer */
-	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
-
-	/* set MTU, 4 : VLAN */
-	iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU);
-
-	/* jumbo size & rrd retirement timer */
-	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
-		 << RXQ_JMBOSZ_TH_SHIFT) |
-	    (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
-	     << RXQ_JMBO_LKAH_SHIFT) |
-	    (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
-	     << RXQ_RRD_TIMER_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
-
-	/* Flow Control */
-	switch (hw->dev_rev) {
-	case 0x8001:
-	case 0x9001:
-	case 0x9002:
-	case 0x9003:
-		set_flow_ctrl_old(adapter);
-		break;
-	default:
-		set_flow_ctrl_new(hw);
-		break;
-	}
-
-	/* config TXQ */
-	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
-		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
-	    (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
-	     << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
-	    (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
-	     << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
-
-	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
-	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
-		 << TX_JUMBO_TASK_TH_SHIFT) |
-	    (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
-	     << TX_TPD_MIN_IPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
-
-	/* config RXQ */
-	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
-		 << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
-	    (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
-	     << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
-	    (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
-	     << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) |
-	    RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
-
-	/* config DMA Engine */
-	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-		 << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
-	    ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-	     << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
-	    DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN;
-	value |= (u32) hw->dma_ord;
-	if (atl1_rcb_128 == hw->rcb_value)
-		value |= DMA_CTRL_RCB_VALUE;
-	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
-
-	/* config CMB / SMB */
-	value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16);
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
-	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
-	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
-
-	/* --- enable CMB / SMB */
-	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
-	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
-
-	value = ioread32(adapter->hw.hw_addr + REG_ISR);
-	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
-		value = 1;	/* config failed */
-	else
-		value = 0;
-
-	/* clear all interrupt status */
-	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
-	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
-	return value;
-}
-
-/*
- * atl1_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- */
-static void atl1_irq_disable(struct atl1_adapter *adapter)
-{
-	atomic_inc(&adapter->irq_sem);
-	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-	ioread32(adapter->hw.hw_addr + REG_IMR);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-static void atl1_vlan_rx_register(struct net_device *netdev,
-				struct vlan_group *grp)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	u32 ctrl;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	/* atl1_irq_disable(adapter); */
-	adapter->vlgrp = grp;
-
-	if (grp) {
-		/* enable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl |= MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	} else {
-		/* disable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	}
-
-	/* atl1_irq_enable(adapter); */
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static void atl1_restore_vlan(struct atl1_adapter *adapter)
-{
-	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
-}
-
 static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring)
 {
 	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
 	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
-	return ((next_to_clean >
-		 next_to_use) ? next_to_clean - next_to_use -
-		1 : tpd_ring->count + next_to_clean - next_to_use - 1);
+	return ((next_to_clean > next_to_use) ?
+		next_to_clean - next_to_use - 1 :
+		tpd_ring->count + next_to_clean - next_to_use - 1);
 }
 
 static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
@@ -1258,9 +1451,7 @@
 			iph->tot_len = 0;
 			iph->check = 0;
 			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-								 iph->daddr, 0,
-								 IPPROTO_TCP,
-								 0);
+				iph->daddr, 0, IPPROTO_TCP, 0);
 			ipofst = skb_network_offset(skb);
 			if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */
 				tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
@@ -1268,7 +1459,8 @@
 			tso->tsopl |= (iph->ihl &
 				CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
 			tso->tsopl |= (tcp_hdrlen(skb) &
-				TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT;
+				TSO_PARAM_TCPHDRLEN_MASK) <<
+				TSO_PARAM_TCPHDRLEN_SHIFT;
 			tso->tsopl |= (skb_shinfo(skb)->gso_size &
 				TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
 			tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
@@ -1281,7 +1473,7 @@
 }
 
 static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
-			struct csum_param *csum)
+	struct csum_param *csum)
 {
 	u8 css, cso;
 
@@ -1289,7 +1481,7 @@
 		cso = skb_transport_offset(skb);
 		css = cso + skb->csum_offset;
 		if (unlikely(cso & 0x1)) {
-			dev_dbg(&adapter->pdev->dev,
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
 				"payload offset not an even number\n");
 			return -1;
 		}
@@ -1304,8 +1496,8 @@
 	return true;
 }
 
-static void atl1_tx_map(struct atl1_adapter *adapter,
-				struct sk_buff *skb, bool tcp_seg)
+static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+	bool tcp_seg)
 {
 	/* We enter this function holding a spinlock. */
 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -1342,26 +1534,25 @@
 
 		if (first_buf_len > proto_hdr_len) {
 			len12 = first_buf_len - proto_hdr_len;
-			m = (len12 + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+			m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) /
+				ATL1_MAX_TX_BUF_LEN;
 			for (i = 0; i < m; i++) {
 				buffer_info =
 				    &tpd_ring->buffer_info[tpd_next_to_use];
 				buffer_info->skb = NULL;
 				buffer_info->length =
-				    (MAX_TX_BUF_LEN >=
-				     len12) ? MAX_TX_BUF_LEN : len12;
+				    (ATL1_MAX_TX_BUF_LEN >=
+				     len12) ? ATL1_MAX_TX_BUF_LEN : len12;
 				len12 -= buffer_info->length;
 				page = virt_to_page(skb->data +
-						 (proto_hdr_len +
-						  i * MAX_TX_BUF_LEN));
+					(proto_hdr_len +
+					i * ATL1_MAX_TX_BUF_LEN));
 				offset = (unsigned long)(skb->data +
-							(proto_hdr_len +
-							i * MAX_TX_BUF_LEN)) &
-							~PAGE_MASK;
-				buffer_info->dma =
-				    pci_map_page(adapter->pdev, page, offset,
-						 buffer_info->length,
-						 PCI_DMA_TODEVICE);
+					(proto_hdr_len +
+					i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK;
+				buffer_info->dma = pci_map_page(adapter->pdev,
+					page, offset, buffer_info->length,
+					PCI_DMA_TODEVICE);
 				if (++tpd_next_to_use == tpd_ring->count)
 					tpd_next_to_use = 0;
 			}
@@ -1372,8 +1563,7 @@
 		page = virt_to_page(skb->data);
 		offset = (unsigned long)skb->data & ~PAGE_MASK;
 		buffer_info->dma = pci_map_page(adapter->pdev, page,
-						offset, first_buf_len,
-						PCI_DMA_TODEVICE);
+			offset, first_buf_len, PCI_DMA_TODEVICE);
 		if (++tpd_next_to_use == tpd_ring->count)
 			tpd_next_to_use = 0;
 	}
@@ -1385,19 +1575,19 @@
 		frag = &skb_shinfo(skb)->frags[f];
 		lenf = frag->size;
 
-		m = (lenf + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+		m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN;
 		for (i = 0; i < m; i++) {
 			buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
 			if (unlikely(buffer_info->skb))
 				BUG();
 			buffer_info->skb = NULL;
-			buffer_info->length =
-			    (lenf > MAX_TX_BUF_LEN) ? MAX_TX_BUF_LEN : lenf;
+			buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ?
+				ATL1_MAX_TX_BUF_LEN : lenf;
 			lenf -= buffer_info->length;
-			buffer_info->dma =
-			    pci_map_page(adapter->pdev, frag->page,
-					 frag->page_offset + i * MAX_TX_BUF_LEN,
-					 buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = pci_map_page(adapter->pdev,
+				frag->page,
+				frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
+				buffer_info->length, PCI_DMA_TODEVICE);
 
 			if (++tpd_next_to_use == tpd_ring->count)
 				tpd_next_to_use = 0;
@@ -1409,7 +1599,7 @@
 }
 
 static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
-			       union tpd_descr *descr)
+       union tpd_descr *descr)
 {
 	/* We enter this function holding a spinlock. */
 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -1453,31 +1643,6 @@
 	atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
 }
 
-static void atl1_update_mailbox(struct atl1_adapter *adapter)
-{
-	unsigned long flags;
-	u32 tpd_next_to_use;
-	u32 rfd_next_to_use;
-	u32 rrd_next_to_clean;
-	u32 value;
-
-	spin_lock_irqsave(&adapter->mb_lock, flags);
-
-	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
-	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
-	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
-
-	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
-		MB_RFD_PROD_INDX_SHIFT) |
-		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
-		MB_RRD_CONS_INDX_SHIFT) |
-		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
-		MB_TPD_PROD_INDX_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
-
-	spin_unlock_irqrestore(&adapter->mb_lock, flags);
-}
-
 static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct atl1_adapter *adapter = netdev_priv(netdev);
@@ -1513,8 +1678,8 @@
 	for (f = 0; f < nr_frags; f++) {
 		frag_size = skb_shinfo(skb)->frags[f].size;
 		if (frag_size)
-			count +=
-			    (frag_size + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+			count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
+				ATL1_MAX_TX_BUF_LEN;
 	}
 
 	/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
@@ -1530,7 +1695,8 @@
 			/* need additional TPD ? */
 			if (proto_hdr_len != len)
 				count += (len - proto_hdr_len +
-					MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+					ATL1_MAX_TX_BUF_LEN - 1) /
+					ATL1_MAX_TX_BUF_LEN;
 		}
 	}
 
@@ -1538,7 +1704,7 @@
 	if (!spin_trylock(&adapter->lock)) {
 		/* Can't get lock - tell upper layer to requeue */
 		local_irq_restore(flags);
-		dev_dbg(&adapter->pdev->dev, "tx locked\n");
+		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n");
 		return NETDEV_TX_LOCKED;
 	}
 
@@ -1546,7 +1712,7 @@
 		/* not enough descriptors */
 		netif_stop_queue(netdev);
 		spin_unlock_irqrestore(&adapter->lock, flags);
-		dev_dbg(&adapter->pdev->dev, "tx busy\n");
+		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n");
 		return NETDEV_TX_BUSY;
 	}
 
@@ -1588,131 +1754,208 @@
 }
 
 /*
- * atl1_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
+ * atl1_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
  */
-static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+static irqreturn_t atl1_intr(int irq, void *data)
+{
+	struct atl1_adapter *adapter = netdev_priv(data);
+	u32 status;
+	u8 update_rx;
+	int max_ints = 10;
+
+	status = adapter->cmb.cmb->int_stats;
+	if (!status)
+		return IRQ_NONE;
+
+	update_rx = 0;
+
+	do {
+		/* clear CMB interrupt status at once */
+		adapter->cmb.cmb->int_stats = 0;
+
+		if (status & ISR_GPHY)	/* clear phy status */
+			atl1_clear_phy_int(adapter);
+
+		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+
+		/* check if SMB intr */
+		if (status & ISR_SMB)
+			atl1_inc_smb(adapter);
+
+		/* check if PCIE PHY Link down */
+		if (status & ISR_PHY_LINKDOWN) {
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"pcie phy link down %x\n", status);
+			if (netif_running(adapter->netdev)) {	/* reset MAC */
+				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+				schedule_work(&adapter->pcie_dma_to_rst_task);
+				return IRQ_HANDLED;
+			}
+		}
+
+		/* check if DMA read/write error ? */
+		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"pcie DMA r/w error (status = 0x%x)\n",
+				status);
+			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+			schedule_work(&adapter->pcie_dma_to_rst_task);
+			return IRQ_HANDLED;
+		}
+
+		/* link event */
+		if (status & ISR_GPHY) {
+			adapter->soft_stats.tx_carrier_errors++;
+			atl1_check_for_link(adapter);
+		}
+
+		/* transmit event */
+		if (status & ISR_CMB_TX)
+			atl1_intr_tx(adapter);
+
+		/* rx exception */
+		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+				ISR_HOST_RRD_OV))
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"rx exception, ISR = 0x%x\n", status);
+			atl1_intr_rx(adapter);
+		}
+
+		if (--max_ints < 0)
+			break;
+
+	} while ((status = adapter->cmb.cmb->int_stats));
+
+	/* re-enable Interrupt */
+	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+	return IRQ_HANDLED;
+}
+
+/*
+ * atl1_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_watchdog(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+/*
+ * atl1_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_phy_config(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+	struct atl1_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	adapter->phy_timer_pending = false;
+	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
+	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/*
+ * atl1_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1_tx_timeout(struct net_device *netdev)
 {
 	struct atl1_adapter *adapter = netdev_priv(netdev);
-	return &adapter->net_stats;
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->tx_timeout_task);
 }
 
 /*
- * atl1_clean_rx_ring - Free RFD Buffers
- * @adapter: board private structure
+ * Orphaned vendor comment left intact here:
+ * <vendor comment>
+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+ * will assert. We do soft reset <0x1400=1> according
+ * with the SPEC. BUT, it seemes that PCIE or DMA
+ * state-machine will not be reset. DMAR_TO_INT will
+ * assert again and again.
+ * </vendor comment>
  */
-static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+static void atl1_tx_timeout_task(struct work_struct *work)
 {
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
+	struct atl1_adapter *adapter =
+		container_of(work, struct atl1_adapter, tx_timeout_task);
+	struct net_device *netdev = adapter->netdev;
 
-	/* Free all the Rx ring sk_buffs */
-	for (i = 0; i < rfd_ring->count; i++) {
-		buffer_info = &rfd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev,
-					buffer_info->dma,
-					buffer_info->length,
-					PCI_DMA_FROMDEVICE);
-			buffer_info->dma = 0;
-		}
-		if (buffer_info->skb) {
-			dev_kfree_skb(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * rfd_ring->count;
-	memset(rfd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(rfd_ring->desc, 0, rfd_ring->size);
-
-	rfd_ring->next_to_clean = 0;
-	atomic_set(&rfd_ring->next_to_use, 0);
-
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
+	netif_device_detach(netdev);
+	atl1_down(adapter);
+	atl1_up(adapter);
+	netif_device_attach(netdev);
 }
 
 /*
- * atl1_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
+ * atl1_link_chg_task - deal with link change event Out of interrupt context
  */
-static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+static void atl1_link_chg_task(struct work_struct *work)
 {
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
+	struct atl1_adapter *adapter =
+               container_of(work, struct atl1_adapter, link_chg_task);
+	unsigned long flags;
 
-	/* Free all the Tx ring sk_buffs */
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev, buffer_info->dma,
-				       buffer_info->length, PCI_DMA_TODEVICE);
-			buffer_info->dma = 0;
-		}
-	}
-
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->skb) {
-			dev_kfree_skb_any(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * tpd_ring->count;
-	memset(tpd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(tpd_ring->desc, 0, tpd_ring->size);
-
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
+	spin_lock_irqsave(&adapter->lock, flags);
+	atl1_check_link(adapter);
+	spin_unlock_irqrestore(&adapter->lock, flags);
 }
 
-/*
- * atl1_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-void atl1_free_ring_resources(struct atl1_adapter *adapter)
+static void atl1_vlan_rx_register(struct net_device *netdev,
+	struct vlan_group *grp)
 {
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_ring_header *ring_header = &adapter->ring_header;
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	u32 ctrl;
 
-	atl1_clean_tx_ring(adapter);
-	atl1_clean_rx_ring(adapter);
+	spin_lock_irqsave(&adapter->lock, flags);
+	/* atl1_irq_disable(adapter); */
+	adapter->vlgrp = grp;
 
-	kfree(tpd_ring->buffer_info);
-	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
-			    ring_header->dma);
+	if (grp) {
+		/* enable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl |= MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	} else {
+		/* disable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	}
 
-	tpd_ring->buffer_info = NULL;
-	tpd_ring->desc = NULL;
-	tpd_ring->dma = 0;
+	/* atl1_irq_enable(adapter); */
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
 
-	rfd_ring->buffer_info = NULL;
-	rfd_ring->desc = NULL;
-	rfd_ring->dma = 0;
+static void atl1_restore_vlan(struct atl1_adapter *adapter)
+{
+	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
 
-	rrd_ring->desc = NULL;
-	rrd_ring->dma = 0;
+int atl1_reset(struct atl1_adapter *adapter)
+{
+	int ret;
+
+	ret = atl1_reset_hw(&adapter->hw);
+	if (ret != ATL1_SUCCESS)
+		return ret;
+	return atl1_init_hw(&adapter->hw);
 }
 
 s32 atl1_up(struct atl1_adapter *adapter)
@@ -1723,6 +1966,7 @@
 
 	/* hardware has been reset, we need to reload some things */
 	atl1_set_multi(netdev);
+	atl1_init_ring_ptrs(adapter);
 	atl1_restore_vlan(adapter);
 	err = atl1_alloc_rx_buffers(adapter);
 	if (unlikely(!err))		/* no RX BUFFER allocated */
@@ -1750,11 +1994,6 @@
 	atl1_check_link(adapter);
 	return 0;
 
-	/* FIXME: unreachable code! -- CHS */
-	/* free irq disable any interrupt */
-	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-	free_irq(adapter->pdev->irq, netdev);
-
 err_up:
 	pci_disable_msi(adapter->pdev);
 	/* free rx_buffers */
@@ -1786,172 +2025,6 @@
 }
 
 /*
- * atl1_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int old_mtu = netdev->mtu;
-	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-
-	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-		return -EINVAL;
-	}
-
-	adapter->hw.max_frame_size = max_frame;
-	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
-	adapter->rx_buffer_len = (max_frame + 7) & ~7;
-	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
-
-	netdev->mtu = new_mtu;
-	if ((old_mtu != new_mtu) && netif_running(netdev)) {
-		atl1_down(adapter);
-		atl1_up(adapter);
-	}
-
-	return 0;
-}
-
-/*
- * atl1_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_set_mac(struct net_device *netdev, void *p)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
-	atl1_set_mac_addr(&adapter->hw);
-	return 0;
-}
-
-/*
- * atl1_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_watchdog(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-
-	/* Reset the timer */
-	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-}
-
-static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u16 result;
-
-	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
-
-	return result;
-}
-
-static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, int val)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	atl1_write_phy_reg(&adapter->hw, reg_num, val);
-}
-
-/*
- * atl1_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	int retval;
-
-	if (!netif_running(netdev))
-		return -EINVAL;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-
-	return retval;
-}
-
-/*
- * atl1_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return atl1_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/*
- * atl1_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atl1_tx_timeout(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->tx_timeout_task);
-}
-
-/*
- * atl1_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_phy_config(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-	struct atl1_hw *hw = &adapter->hw;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	adapter->phy_timer_pending = false;
-	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
-	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
-	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-int atl1_reset(struct atl1_adapter *adapter)
-{
-	int ret;
-
-	ret = atl1_reset_hw(&adapter->hw);
-	if (ret != ATL1_SUCCESS)
-		return ret;
-	return atl1_init_hw(&adapter->hw);
-}
-
-/*
  * atl1_open - Called when a network interface is made active
  * @netdev: network interface device structure
  *
@@ -2003,6 +2076,105 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	u32 ctrl = 0;
+	u32 wufc = adapter->wol;
+
+	netif_device_detach(netdev);
+	if (netif_running(netdev))
+		atl1_down(adapter);
+
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	if (ctrl & BMSR_LSTATUS)
+		wufc &= ~ATL1_WUFC_LNKC;
+
+	/* reduce speed to 10/100M */
+	if (wufc) {
+		atl1_phy_enter_power_saving(hw);
+		/* if resume, let driver to re- setup link */
+		hw->phy_configured = false;
+		atl1_set_mac_addr(hw);
+		atl1_set_multi(netdev);
+
+		ctrl = 0;
+		/* turn on magic packet wol */
+		if (wufc & ATL1_WUFC_MAG)
+			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+		/* turn on Link change WOL */
+		if (wufc & ATL1_WUFC_LNKC)
+			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+
+		/* turn on all-multi mode if wake on multicast is enabled */
+		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_DBG;
+		ctrl &= ~MAC_CTRL_PROMIS_EN;
+		if (wufc & ATL1_WUFC_MC)
+			ctrl |= MAC_CTRL_MC_ALL_EN;
+		else
+			ctrl &= ~MAC_CTRL_MC_ALL_EN;
+
+		/* turn on broadcast mode if wake on-BC is enabled */
+		if (wufc & ATL1_WUFC_BC)
+			ctrl |= MAC_CTRL_BC_EN;
+		else
+			ctrl &= ~MAC_CTRL_BC_EN;
+
+		/* enable RX */
+		ctrl |= MAC_CTRL_RX_EN;
+		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_enable_wake(pdev, PCI_D3cold, 1);
+	} else {
+		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_enable_wake(pdev, PCI_D3cold, 0);
+	}
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int atl1_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u32 ret_val;
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev);
+
+	ret_val = pci_enable_device(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+	atl1_reset(adapter);
+
+	if (netif_running(netdev))
+		atl1_up(adapter);
+	netif_device_attach(netdev);
+
+	atl1_via_workaround(adapter);
+
+	return 0;
+}
+#else
+#define atl1_suspend NULL
+#define atl1_resume NULL
+#endif
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void atl1_poll_controller(struct net_device *netdev)
 {
@@ -2013,69 +2185,6 @@
 #endif
 
 /*
- * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
- * will assert. We do soft reset <0x1400=1> according
- * with the SPEC. BUT, it seemes that PCIE or DMA
- * state-machine will not be reset. DMAR_TO_INT will
- * assert again and again.
- */
-static void atl1_tx_timeout_task(struct work_struct *work)
-{
-	struct atl1_adapter *adapter =
-		container_of(work, struct atl1_adapter, tx_timeout_task);
-	struct net_device *netdev = adapter->netdev;
-
-	netif_device_detach(netdev);
-	atl1_down(adapter);
-	atl1_up(adapter);
-	netif_device_attach(netdev);
-}
-
-/*
- * atl1_link_chg_task - deal with link change event Out of interrupt context
- */
-static void atl1_link_chg_task(struct work_struct *work)
-{
-	struct atl1_adapter *adapter =
-               container_of(work, struct atl1_adapter, link_chg_task);
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	atl1_check_link(adapter);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-/*
- * atl1_pcie_patch - Patch for PCIE module
- */
-static void atl1_pcie_patch(struct atl1_adapter *adapter)
-{
-	u32 value;
-	value = 0x6500;
-	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
-	/* pcie flow control mode change */
-	value = ioread32(adapter->hw.hw_addr + 0x1008);
-	value |= 0x8000;
-	iowrite32(value, adapter->hw.hw_addr + 0x1008);
-}
-
-/*
- * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
- * on PCI Command register is disable.
- * The function enable this bit.
- * Brackett, 2006/03/15
- */
-static void atl1_via_workaround(struct atl1_adapter *adapter)
-{
-	unsigned long value;
-
-	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
-	if (value & PCI_COMMAND_INTX_DISABLE)
-		value &= ~PCI_COMMAND_INTX_DISABLE;
-	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
-}
-
-/*
  * atl1_probe - Device Initialization Routine
  * @pdev: PCI device information struct
  * @ent: entry in atl1_pci_tbl
@@ -2087,7 +2196,7 @@
  * and a hardware reset occur.
  */
 static int __devinit atl1_probe(struct pci_dev *pdev,
-			      const struct pci_device_id *ent)
+	const struct pci_device_id *ent)
 {
 	struct net_device *netdev;
 	struct atl1_adapter *adapter;
@@ -2141,7 +2250,7 @@
 	}
 	/* get device revision number */
 	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
-					(REG_MASTER_CTRL + 2));
+		(REG_MASTER_CTRL + 2));
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
 	/* set default ring resource counts */
@@ -2294,7 +2403,8 @@
 	 * address, we need to save the permanent one.
 	 */
 	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
-		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN);
+		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
+			ETH_ALEN);
 		atl1_set_mac_addr(&adapter->hw);
 	}
 
@@ -2306,112 +2416,11 @@
 	pci_disable_device(pdev);
 }
 
-#ifdef CONFIG_PM
-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	u32 ctrl = 0;
-	u32 wufc = adapter->wol;
-
-	netif_device_detach(netdev);
-	if (netif_running(netdev))
-		atl1_down(adapter);
-
-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
-	if (ctrl & BMSR_LSTATUS)
-		wufc &= ~ATL1_WUFC_LNKC;
-
-	/* reduce speed to 10/100M */
-	if (wufc) {
-		atl1_phy_enter_power_saving(hw);
-		/* if resume, let driver to re- setup link */
-		hw->phy_configured = false;
-		atl1_set_mac_addr(hw);
-		atl1_set_multi(netdev);
-
-		ctrl = 0;
-		/* turn on magic packet wol */
-		if (wufc & ATL1_WUFC_MAG)
-			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-
-		/* turn on Link change WOL */
-		if (wufc & ATL1_WUFC_LNKC)
-			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
-		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
-
-		/* turn on all-multi mode if wake on multicast is enabled */
-		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_DBG;
-		ctrl &= ~MAC_CTRL_PROMIS_EN;
-		if (wufc & ATL1_WUFC_MC)
-			ctrl |= MAC_CTRL_MC_ALL_EN;
-		else
-			ctrl &= ~MAC_CTRL_MC_ALL_EN;
-
-		/* turn on broadcast mode if wake on-BC is enabled */
-		if (wufc & ATL1_WUFC_BC)
-			ctrl |= MAC_CTRL_BC_EN;
-		else
-			ctrl &= ~MAC_CTRL_BC_EN;
-
-		/* enable RX */
-		ctrl |= MAC_CTRL_RX_EN;
-		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
-		pci_enable_wake(pdev, PCI_D3hot, 1);
-		pci_enable_wake(pdev, PCI_D3cold, 1);	/* 4 == D3 cold */
-	} else {
-		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_enable_wake(pdev, PCI_D3cold, 0);	/* 4 == D3 cold */
-	}
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int atl1_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u32 ret_val;
-
-	pci_set_power_state(pdev, 0);
-	pci_restore_state(pdev);
-
-	ret_val = pci_enable_device(pdev);
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
-	atl1_reset(adapter);
-
-	if (netif_running(netdev))
-		atl1_up(adapter);
-	netif_device_attach(netdev);
-
-	atl1_via_workaround(adapter);
-
-	return 0;
-}
-#else
-#define atl1_suspend NULL
-#define atl1_resume NULL
-#endif
-
 static struct pci_driver atl1_driver = {
 	.name = atl1_driver_name,
 	.id_table = atl1_pci_tbl,
 	.probe = atl1_probe,
 	.remove = __devexit_p(atl1_remove),
-	/* Power Managment Hooks */
-	/* probably broken right now -- CHS */
 	.suspend = atl1_suspend,
 	.resume = atl1_resume
 };
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index f03f070..6628fa6 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,13 +39,13 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0067"
+#define DRV_VERSION	"EHEA_0070"
 
-/* EHEA capability flags */
+/* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
-#define DLPAR_MEM_ADD 2
-#define DLPAR_MEM_REM 4
-#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
+#define DLPAR_MEM_ADD      2
+#define DLPAR_MEM_REM      4
+#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM)
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
 	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -113,6 +113,8 @@
 /* Memory Regions */
 #define EHEA_MR_ACC_CTRL       0x00800000
 
+#define EHEA_BUSMAP_START      0x8000000000000000ULL
+
 #define EHEA_WATCH_DOG_TIMEOUT 10*HZ
 
 /* utility functions */
@@ -186,6 +188,12 @@
 				   set to 0 if unused */
 };
 
+struct ehea_busmap {
+	unsigned int entries;		/* total number of entries */
+	unsigned int valid_sections;	/* number of valid sections */
+	u64 *vaddr;
+};
+
 struct ehea_qp;
 struct ehea_cq;
 struct ehea_eq;
@@ -382,6 +390,8 @@
 	struct ehea_mr mr;
 	u32 pd;                    /* protection domain */
 	u64 max_mc_mac;            /* max number of multicast mac addresses */
+	int active_ports;
+	struct list_head list;
 };
 
 
@@ -431,6 +441,9 @@
 	int max_entries_rq3;
 };
 
+enum ehea_flag_bits {
+	__EHEA_STOP_XFER
+};
 
 void ehea_set_ethtool_ops(struct net_device *netdev);
 int ehea_sense_port_attr(struct ehea_port *port);
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 383144d..1d1571c 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -79,6 +79,11 @@
 MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
 
 static int port_name_cnt = 0;
+static LIST_HEAD(adapter_list);
+u64 ehea_driver_flags = 0;
+struct workqueue_struct *ehea_driver_wq;
+struct work_struct ehea_rereg_mr_task;
+
 
 static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
 					const struct of_device_id *id);
@@ -238,13 +243,17 @@
 		rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
 			    | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
 		rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
-		rwqe->sg_list[0].vaddr = (u64)skb->data;
+		rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
 		rwqe->sg_list[0].len = packet_size;
 		rwqe->data_segments = 1;
 
 		index++;
 		index &= max_index_mask;
+
+		if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
+			goto out;
 	}
+
 	q_skba->index = index;
 
 	/* Ring doorbell */
@@ -253,7 +262,7 @@
 		ehea_update_rq2a(pr->qp, i);
 	else
 		ehea_update_rq3a(pr->qp, i);
-
+out:
 	return ret;
 }
 
@@ -1321,7 +1330,7 @@
 			sg1entry->len = skb_data_size - headersize;
 
 			tmp_addr = (u64)(skb->data + headersize);
-			sg1entry->vaddr = tmp_addr;
+			sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 		}
 	} else
@@ -1352,7 +1361,7 @@
 			sg1entry->l_key = lkey;
 			sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
 			tmp_addr = (u64)(skb->data + SWQE2_MAX_IMM);
-			sg1entry->vaddr = tmp_addr;
+			sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 		}
 	} else {
@@ -1391,7 +1400,7 @@
 			sg1entry->len = frag->size;
 			tmp_addr =  (u64)(page_address(frag->page)
 					  + frag->page_offset);
-			sg1entry->vaddr = tmp_addr;
+			sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 			sg1entry_contains_frag_data = 1;
 		}
@@ -1406,7 +1415,7 @@
 
 			tmp_addr = (u64)(page_address(frag->page)
 					 + frag->page_offset);
-			sgentry->vaddr = tmp_addr;
+			sgentry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 		}
 	}
@@ -1878,6 +1887,9 @@
 		ehea_dump(swqe, 512, "swqe");
 	}
 
+	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
+		goto out;
+
 	ehea_post_swqe(pr->qp, swqe);
 	pr->tx_packets++;
 
@@ -1892,7 +1904,7 @@
 	}
 	dev->trans_start = jiffies;
 	spin_unlock(&pr->xmit_lock);
-
+out:
 	return NETDEV_TX_OK;
 }
 
@@ -2220,6 +2232,9 @@
 out_clean_pr:
 	ehea_clean_all_portres(port);
 out:
+	if (ret)
+		ehea_info("Failed starting %s. ret=%i", dev->name, ret);
+
 	return ret;
 }
 
@@ -2259,8 +2274,13 @@
 			msleep(1);
 
 	ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
-	ret = ehea_clean_all_portres(port);
 	port->state = EHEA_PORT_DOWN;
+
+	ret = ehea_clean_all_portres(port);
+	if (ret)
+		ehea_info("Failed freeing resources for %s. ret=%i",
+			  dev->name, ret);
+
 	return ret;
 }
 
@@ -2292,15 +2312,11 @@
 	netif_stop_queue(dev);
 	netif_poll_disable(dev);
 
-	ret = ehea_down(dev);
-	if (ret)
-		ehea_error("ehea_down failed. not all resources are freed");
+	ehea_down(dev);
 
 	ret = ehea_up(dev);
-	if (ret) {
-		ehea_error("Reset device %s failed: ret=%d", dev->name, ret);
+	if (ret)
 		goto out;
-	}
 
 	if (netif_msg_timer(port))
 		ehea_info("Device %s resetted successfully", dev->name);
@@ -2312,6 +2328,88 @@
 	return;
 }
 
+static void ehea_rereg_mrs(struct work_struct *work)
+{
+	int ret, i;
+	struct ehea_adapter *adapter;
+
+	ehea_info("LPAR memory enlarged - re-initializing driver");
+
+	list_for_each_entry(adapter, &adapter_list, list)
+		if (adapter->active_ports) {
+			/* Shutdown all ports */
+			for (i = 0; i < EHEA_MAX_PORTS; i++) {
+				struct ehea_port *port = adapter->port[i];
+
+				if (port) {
+					struct net_device *dev = port->netdev;
+
+					if (dev->flags & IFF_UP) {
+						ehea_info("stopping %s",
+							  dev->name);
+						down(&port->port_lock);
+						netif_stop_queue(dev);
+						netif_poll_disable(dev);
+						ehea_down(dev);
+						up(&port->port_lock);
+					}
+				}
+			}
+
+			/* Unregister old memory region */
+			ret = ehea_rem_mr(&adapter->mr);
+			if (ret) {
+				ehea_error("unregister MR failed - driver"
+					   " inoperable!");
+				goto out;
+			}
+		}
+
+	ehea_destroy_busmap();
+
+	ret = ehea_create_busmap();
+	if (ret)
+		goto out;
+
+	clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
+
+	list_for_each_entry(adapter, &adapter_list, list)
+		if (adapter->active_ports) {
+			/* Register new memory region */
+			ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
+			if (ret) {
+				ehea_error("register MR failed - driver"
+					   " inoperable!");
+				goto out;
+			}
+
+			/* Restart all ports */
+			for (i = 0; i < EHEA_MAX_PORTS; i++) {
+				struct ehea_port *port = adapter->port[i];
+
+				if (port) {
+					struct net_device *dev = port->netdev;
+
+					if (dev->flags & IFF_UP) {
+						ehea_info("restarting %s",
+							  dev->name);
+						down(&port->port_lock);
+
+						ret = ehea_up(dev);
+						if (!ret) {
+							netif_poll_enable(dev);
+							netif_wake_queue(dev);
+						}
+
+						up(&port->port_lock);
+					}
+				}
+			}
+		}
+out:
+	return;
+}
+
 static void ehea_tx_watchdog(struct net_device *dev)
 {
 	struct ehea_port *port = netdev_priv(dev);
@@ -2573,6 +2671,8 @@
 	ehea_info("%s: Jumbo frames are %sabled", dev->name,
 		  jumbo == 1 ? "en" : "dis");
 
+	adapter->active_ports++;
+
 	return port;
 
 out_unreg_port:
@@ -2596,6 +2696,7 @@
 	ehea_unregister_port(port);
 	kfree(port->mc_list);
 	free_netdev(port->netdev);
+	port->adapter->active_ports--;
 }
 
 static int ehea_setup_ports(struct ehea_adapter *adapter)
@@ -2788,6 +2889,8 @@
 		goto out;
 	}
 
+	list_add(&adapter->list, &adapter_list);
+
 	adapter->ebus_dev = dev;
 
 	adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
@@ -2891,7 +2994,10 @@
 
 	ehea_destroy_eq(adapter->neq);
 	ehea_remove_adapter_mr(adapter);
+	list_del(&adapter->list);
+
 	kfree(adapter);
+
 	return 0;
 }
 
@@ -2939,9 +3045,18 @@
 	printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
 	       DRV_VERSION);
 
+	ehea_driver_wq = create_workqueue("ehea_driver_wq");
+
+	INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
+
 	ret = check_module_parm();
 	if (ret)
 		goto out;
+
+	ret = ehea_create_busmap();
+	if (ret)
+		goto out;
+
 	ret = ibmebus_register_driver(&ehea_driver);
 	if (ret) {
 		ehea_error("failed registering eHEA device driver on ebus");
@@ -2965,6 +3080,7 @@
 {
 	driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
 	ibmebus_unregister_driver(&ehea_driver);
+	ehea_destroy_busmap();
 }
 
 module_init(ehea_module_init);
diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h
index d17a45a..89b6353 100644
--- a/drivers/net/ehea/ehea_phyp.h
+++ b/drivers/net/ehea/ehea_phyp.h
@@ -60,6 +60,9 @@
 	}
 }
 
+/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */
+#define EHEA_MAX_RPAGE 512
+
 /* Notification Event Queue (NEQ) Entry bit masks */
 #define NEQE_EVENT_CODE		EHEA_BMASK_IBM(2, 7)
 #define NEQE_PORTNUM  		EHEA_BMASK_IBM(32, 47)
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index 29eaa46..a36fa6c 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -31,6 +31,13 @@
 #include "ehea_phyp.h"
 #include "ehea_qmr.h"
 
+
+struct ehea_busmap ehea_bmap = { 0, 0, NULL };
+extern u64 ehea_driver_flags;
+extern struct workqueue_struct *ehea_driver_wq;
+extern struct work_struct ehea_rereg_mr_task;
+
+
 static void *hw_qpageit_get_inc(struct hw_queue *queue)
 {
 	void *retvalue = hw_qeit_get(queue);
@@ -547,18 +554,84 @@
 	return 0;
 }
 
+int ehea_create_busmap( void )
+{
+	u64 vaddr = EHEA_BUSMAP_START;
+	unsigned long abs_max_pfn = 0;
+	unsigned long sec_max_pfn;
+	int i;
+
+	/*
+	 * Sections are not in ascending order -> Loop over all sections and
+	 * find the highest PFN to compute the required map size.
+	*/
+	ehea_bmap.valid_sections = 0;
+
+	for (i = 0; i < NR_MEM_SECTIONS; i++)
+		if (valid_section_nr(i)) {
+			sec_max_pfn = section_nr_to_pfn(i);
+			if (sec_max_pfn > abs_max_pfn)
+				abs_max_pfn = sec_max_pfn;
+			ehea_bmap.valid_sections++;
+		}
+
+	ehea_bmap.entries = abs_max_pfn / EHEA_PAGES_PER_SECTION + 1;
+	ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr));
+
+	if (!ehea_bmap.vaddr)
+		return -ENOMEM;
+
+	for (i = 0 ; i < ehea_bmap.entries; i++) {
+		unsigned long pfn = section_nr_to_pfn(i);
+
+		if (pfn_valid(pfn)) {
+			ehea_bmap.vaddr[i] = vaddr;
+			vaddr += EHEA_SECTSIZE;
+		} else
+			ehea_bmap.vaddr[i] = 0;
+	}
+
+	return 0;
+}
+
+void ehea_destroy_busmap( void )
+{
+	vfree(ehea_bmap.vaddr);
+}
+
+u64 ehea_map_vaddr(void *caddr)
+{
+	u64 mapped_addr;
+	unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS;
+
+	if (likely(index < ehea_bmap.entries)) {
+		mapped_addr = ehea_bmap.vaddr[index];
+		if (likely(mapped_addr))
+			mapped_addr |= (((unsigned long)caddr)
+					& (EHEA_SECTSIZE - 1));
+		else
+			mapped_addr = -1;
+	} else
+		mapped_addr = -1;
+
+	if (unlikely(mapped_addr == -1))
+		if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
+			queue_work(ehea_driver_wq, &ehea_rereg_mr_task);
+
+	return mapped_addr;
+}
+
 int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
 {
-	int i, k, ret;
-	u64 hret, pt_abs, start, end, nr_pages;
-	u32 acc_ctrl = EHEA_MR_ACC_CTRL;
+	int ret;
 	u64 *pt;
+	void *pg;
+	u64 hret, pt_abs, i, j, m, mr_len;
+	u32 acc_ctrl = EHEA_MR_ACC_CTRL;
 
-	start = KERNELBASE;
-	end = (u64)high_memory;
-	nr_pages = (end - start) / EHEA_PAGESIZE;
+	mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE;
 
-	pt =  kzalloc(PAGE_SIZE, GFP_KERNEL);
+	pt =  kzalloc(EHEA_MAX_RPAGE * sizeof(u64), GFP_KERNEL);
 	if (!pt) {
 		ehea_error("no mem");
 		ret = -ENOMEM;
@@ -566,7 +639,8 @@
 	}
 	pt_abs = virt_to_abs(pt);
 
-	hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start,
+	hret = ehea_h_alloc_resource_mr(adapter->handle,
+					EHEA_BUSMAP_START, mr_len,
 					acc_ctrl, adapter->pd,
 					&mr->handle, &mr->lkey);
 	if (hret != H_SUCCESS) {
@@ -575,49 +649,43 @@
 		goto out;
 	}
 
-	mr->vaddr = KERNELBASE;
-	k = 0;
+	for (i = 0 ; i < ehea_bmap.entries; i++)
+		if (ehea_bmap.vaddr[i]) {
+			void *sectbase = __va(i << SECTION_SIZE_BITS);
+			unsigned long k = 0;
 
-	while (nr_pages > 0) {
-		if (nr_pages > 1) {
-			u64 num_pages = min(nr_pages, (u64)512);
-			for (i = 0; i < num_pages; i++)
-				pt[i] = virt_to_abs((void*)(((u64)start) +
-							    ((k++) *
-							     EHEA_PAGESIZE)));
+			for (j = 0; j < (PAGES_PER_SECTION / EHEA_MAX_RPAGE);
+			      j++) {
 
-			hret = ehea_h_register_rpage_mr(adapter->handle,
-							mr->handle, 0,
-							0, (u64)pt_abs,
-							num_pages);
-			nr_pages -= num_pages;
-		} else {
-			u64 abs_adr = virt_to_abs((void*)(((u64)start) +
-							  (k * EHEA_PAGESIZE)));
+				for (m = 0; m < EHEA_MAX_RPAGE; m++) {
+					pg = sectbase + ((k++) * EHEA_PAGESIZE);
+					pt[m] = virt_to_abs(pg);
+				}
 
-			hret = ehea_h_register_rpage_mr(adapter->handle,
-							mr->handle, 0,
-							0, abs_adr,1);
-			nr_pages--;
+				hret = ehea_h_register_rpage_mr(adapter->handle,
+								mr->handle,
+								0, 0, pt_abs,
+								EHEA_MAX_RPAGE);
+				if ((hret != H_SUCCESS)
+				    && (hret != H_PAGE_REGISTERED)) {
+					ehea_h_free_resource(adapter->handle,
+							     mr->handle,
+							     FORCE_FREE);
+					ehea_error("register_rpage_mr failed");
+					ret = -EIO;
+					goto out;
+				}
+			}
 		}
 
-		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) {
-			ehea_h_free_resource(adapter->handle,
-					     mr->handle, FORCE_FREE);
-			ehea_error("register_rpage_mr failed");
-			ret = -EIO;
-			goto out;
-		}
-	}
-
 	if (hret != H_SUCCESS) {
-		ehea_h_free_resource(adapter->handle, mr->handle,
-				     FORCE_FREE);
-		ehea_error("register_rpage failed for last page");
+		ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
+		ehea_error("registering mr failed");
 		ret = -EIO;
 		goto out;
 	}
 
+	mr->vaddr = EHEA_BUSMAP_START;
 	mr->adapter = adapter;
 	ret = 0;
 out:
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index c0eb3e0..b71f845 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -36,8 +36,14 @@
  * page size of ehea hardware queues
  */
 
-#define EHEA_PAGESHIFT  12
-#define EHEA_PAGESIZE   4096UL
+#define EHEA_PAGESHIFT         12
+#define EHEA_PAGESIZE          (1UL << EHEA_PAGESHIFT)
+#define EHEA_SECTSIZE          (1UL << 24)
+#define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> PAGE_SHIFT)
+
+#if (1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE
+#error eHEA module can't work if kernel sectionsize < ehea sectionsize
+#endif
 
 /* Some abbreviations used here:
  *
@@ -372,4 +378,8 @@
 
 void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
 
+int ehea_create_busmap( void );
+void ehea_destroy_busmap( void );
+u64 ehea_map_vaddr(void *caddr);
+
 #endif	/* __EHEA_QMR_H__ */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 67046e8..136827f 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -550,6 +550,8 @@
 /* PHY defines */
 #define PHY_OUI_MARVELL	0x5043
 #define PHY_OUI_CICADA	0x03f1
+#define PHY_OUI_VITESSE	0x01c1
+#define PHY_OUI_REALTEK	0x01c1
 #define PHYID1_OUI_MASK	0x03ff
 #define PHYID1_OUI_SHFT	6
 #define PHYID2_OUI_MASK	0xfc00
@@ -557,12 +559,36 @@
 #define PHYID2_MODEL_MASK		0x03f0
 #define PHY_MODEL_MARVELL_E3016		0x220
 #define PHY_MARVELL_E3016_INITMASK	0x0300
-#define PHY_INIT1	0x0f000
-#define PHY_INIT2	0x0e00
-#define PHY_INIT3	0x01000
-#define PHY_INIT4	0x0200
-#define PHY_INIT5	0x0004
-#define PHY_INIT6	0x02000
+#define PHY_CICADA_INIT1	0x0f000
+#define PHY_CICADA_INIT2	0x0e00
+#define PHY_CICADA_INIT3	0x01000
+#define PHY_CICADA_INIT4	0x0200
+#define PHY_CICADA_INIT5	0x0004
+#define PHY_CICADA_INIT6	0x02000
+#define PHY_VITESSE_INIT_REG1	0x1f
+#define PHY_VITESSE_INIT_REG2	0x10
+#define PHY_VITESSE_INIT_REG3	0x11
+#define PHY_VITESSE_INIT_REG4	0x12
+#define PHY_VITESSE_INIT_MSK1	0xc
+#define PHY_VITESSE_INIT_MSK2	0x0180
+#define PHY_VITESSE_INIT1	0x52b5
+#define PHY_VITESSE_INIT2	0xaf8a
+#define PHY_VITESSE_INIT3	0x8
+#define PHY_VITESSE_INIT4	0x8f8a
+#define PHY_VITESSE_INIT5	0xaf86
+#define PHY_VITESSE_INIT6	0x8f86
+#define PHY_VITESSE_INIT7	0xaf82
+#define PHY_VITESSE_INIT8	0x0100
+#define PHY_VITESSE_INIT9	0x8f82
+#define PHY_VITESSE_INIT10	0x0
+#define PHY_REALTEK_INIT_REG1	0x1f
+#define PHY_REALTEK_INIT_REG2	0x19
+#define PHY_REALTEK_INIT_REG3	0x13
+#define PHY_REALTEK_INIT1	0x0000
+#define PHY_REALTEK_INIT2	0x8e00
+#define PHY_REALTEK_INIT3	0x0001
+#define PHY_REALTEK_INIT4	0xad17
+
 #define PHY_GIGABIT	0x0100
 
 #define PHY_TIMEOUT	0x1
@@ -1096,6 +1122,28 @@
 			return PHY_ERROR;
 		}
 	}
+	if (np->phy_oui == PHY_OUI_REALTEK) {
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+	}
 
 	/* set advertise register */
 	reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
@@ -1141,14 +1189,14 @@
 	/* phy vendor specific configuration */
 	if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
 		phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
-		phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
-		phy_reserved |= (PHY_INIT3 | PHY_INIT4);
+		phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);
+		phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);
 		if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
 			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
 		phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
-		phy_reserved |= PHY_INIT5;
+		phy_reserved |= PHY_CICADA_INIT5;
 		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
 			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
 			return PHY_ERROR;
@@ -1156,12 +1204,106 @@
 	}
 	if (np->phy_oui == PHY_OUI_CICADA) {
 		phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
-		phy_reserved |= PHY_INIT6;
+		phy_reserved |= PHY_CICADA_INIT6;
 		if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
 			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
 	}
+	if (np->phy_oui == PHY_OUI_VITESSE) {
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+		phy_reserved |= PHY_VITESSE_INIT3;
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+		phy_reserved |= PHY_VITESSE_INIT3;
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+		phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
+		phy_reserved |= PHY_VITESSE_INIT8;
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+	}
+	if (np->phy_oui == PHY_OUI_REALTEK) {
+		/* reset could have cleared these out, set them back */
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+	}
+
 	/* some phys clear out pause advertisment on reset, set it back */
 	mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
 
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 5dd34a1..ac3596f 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -31,7 +31,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <asm/ocp.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0e04f7a..a4bb026 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -17,13 +17,12 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include <linux/mutex.h>
 #include <linux/dma-mapping.h>
-#include <linux/ethtool.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 
 #include "macb.h"
 
@@ -85,172 +84,202 @@
 		memcpy(bp->dev->dev_addr, addr, sizeof(addr));
 }
 
-static void macb_enable_mdio(struct macb *bp)
+static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
-	unsigned long flags;
-	u32 reg;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	reg = macb_readl(bp, NCR);
-	reg |= MACB_BIT(MPE);
-	macb_writel(bp, NCR, reg);
-	macb_writel(bp, IER, MACB_BIT(MFD));
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static void macb_disable_mdio(struct macb *bp)
-{
-	unsigned long flags;
-	u32 reg;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	reg = macb_readl(bp, NCR);
-	reg &= ~MACB_BIT(MPE);
-	macb_writel(bp, NCR, reg);
-	macb_writel(bp, IDR, MACB_BIT(MFD));
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static int macb_mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = bus->priv;
 	int value;
 
-	mutex_lock(&bp->mdio_mutex);
-
-	macb_enable_mdio(bp);
 	macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
 			      | MACB_BF(RW, MACB_MAN_READ)
-			      | MACB_BF(PHYA, phy_id)
-			      | MACB_BF(REGA, location)
+			      | MACB_BF(PHYA, mii_id)
+			      | MACB_BF(REGA, regnum)
 			      | MACB_BF(CODE, MACB_MAN_CODE)));
 
-	wait_for_completion(&bp->mdio_complete);
+	/* wait for end of transfer */
+	while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
+		cpu_relax();
 
 	value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
-	macb_disable_mdio(bp);
-	mutex_unlock(&bp->mdio_mutex);
 
 	return value;
 }
 
-static void macb_mdio_write(struct net_device *dev, int phy_id,
-			    int location, int val)
+static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+			   u16 value)
 {
-	struct macb *bp = netdev_priv(dev);
-
-	dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n",
-		phy_id, location, val);
-
-	mutex_lock(&bp->mdio_mutex);
-	macb_enable_mdio(bp);
+	struct macb *bp = bus->priv;
 
 	macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
 			      | MACB_BF(RW, MACB_MAN_WRITE)
-			      | MACB_BF(PHYA, phy_id)
-			      | MACB_BF(REGA, location)
+			      | MACB_BF(PHYA, mii_id)
+			      | MACB_BF(REGA, regnum)
 			      | MACB_BF(CODE, MACB_MAN_CODE)
-			      | MACB_BF(DATA, val)));
+			      | MACB_BF(DATA, value)));
 
-	wait_for_completion(&bp->mdio_complete);
+	/* wait for end of transfer */
+	while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
+		cpu_relax();
 
-	macb_disable_mdio(bp);
-	mutex_unlock(&bp->mdio_mutex);
-}
-
-static int macb_phy_probe(struct macb *bp)
-{
-	int phy_address;
-	u16 phyid1, phyid2;
-
-	for (phy_address = 0; phy_address < 32; phy_address++) {
-		phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1);
-		phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2);
-
-		if (phyid1 != 0xffff && phyid1 != 0x0000
-		    && phyid2 != 0xffff && phyid2 != 0x0000)
-			break;
-	}
-
-	if (phy_address == 32)
-		return -ENODEV;
-
-	dev_info(&bp->pdev->dev,
-		 "detected PHY at address %d (ID %04x:%04x)\n",
-		 phy_address, phyid1, phyid2);
-
-	bp->mii.phy_id = phy_address;
 	return 0;
 }
 
-static void macb_set_media(struct macb *bp, int media)
+static int macb_mdio_reset(struct mii_bus *bus)
 {
-	u32 reg;
-
-	spin_lock_irq(&bp->lock);
-	reg = macb_readl(bp, NCFGR);
-	reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
-	if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL))
-		reg |= MACB_BIT(SPD);
-	if (media & ADVERTISE_FULL)
-		reg |= MACB_BIT(FD);
-	macb_writel(bp, NCFGR, reg);
-	spin_unlock_irq(&bp->lock);
+	return 0;
 }
 
-static void macb_check_media(struct macb *bp, int ok_to_print, int init_media)
+static void macb_handle_link_change(struct net_device *dev)
 {
-	struct mii_if_info *mii = &bp->mii;
-	unsigned int old_carrier, new_carrier;
-	int advertise, lpa, media, duplex;
+	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
+	unsigned long flags;
 
-	/* if forced media, go no further */
-	if (mii->force_media)
-		return;
+	int status_change = 0;
 
-	/* check current and old link status */
-	old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
-	new_carrier = (unsigned int) mii_link_ok(mii);
+	spin_lock_irqsave(&bp->lock, flags);
 
-	/* if carrier state did not change, assume nothing else did */
-	if (!init_media && old_carrier == new_carrier)
-		return;
+	if (phydev->link) {
+		if ((bp->speed != phydev->speed) ||
+		    (bp->duplex != phydev->duplex)) {
+			u32 reg;
 
-	/* no carrier, nothing much to do */
-	if (!new_carrier) {
-		netif_carrier_off(mii->dev);
-		printk(KERN_INFO "%s: link down\n", mii->dev->name);
-		return;
+			reg = macb_readl(bp, NCFGR);
+			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+
+			if (phydev->duplex)
+				reg |= MACB_BIT(FD);
+			if (phydev->speed)
+				reg |= MACB_BIT(SPD);
+
+			macb_writel(bp, NCFGR, reg);
+
+			bp->speed = phydev->speed;
+			bp->duplex = phydev->duplex;
+			status_change = 1;
+		}
 	}
 
-	/*
-	 * we have carrier, see who's on the other end
-	 */
-	netif_carrier_on(mii->dev);
+	if (phydev->link != bp->link) {
+		if (phydev->link)
+			netif_schedule(dev);
+		else {
+			bp->speed = 0;
+			bp->duplex = -1;
+		}
+		bp->link = phydev->link;
 
-	/* get MII advertise and LPA values */
-	if (!init_media && mii->advertising) {
-		advertise = mii->advertising;
+		status_change = 1;
+	}
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	if (status_change) {
+		if (phydev->link)
+			printk(KERN_INFO "%s: link up (%d/%s)\n",
+			       dev->name, phydev->speed,
+			       DUPLEX_FULL == phydev->duplex ? "Full":"Half");
+		else
+			printk(KERN_INFO "%s: link down\n", dev->name);
+	}
+}
+
+/* based on au1000_eth. c*/
+static int macb_mii_probe(struct net_device *dev)
+{
+	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	struct eth_platform_data *pdata;
+	int phy_addr;
+
+	/* find the first phy */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+		if (bp->mii_bus.phy_map[phy_addr]) {
+			phydev = bp->mii_bus.phy_map[phy_addr];
+			break;
+		}
+	}
+
+	if (!phydev) {
+		printk (KERN_ERR "%s: no PHY found\n", dev->name);
+		return -1;
+	}
+
+	pdata = bp->pdev->dev.platform_data;
+	/* TODO : add pin_irq */
+
+	/* attach the mac to the phy */
+	if (pdata && pdata->is_rmii) {
+		phydev = phy_connect(dev, phydev->dev.bus_id,
+			&macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII);
 	} else {
-		advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
-		mii->advertising = advertise;
+		phydev = phy_connect(dev, phydev->dev.bus_id,
+			&macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII);
 	}
-	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
 
-	/* figure out media and duplex from advertise and LPA values */
-	media = mii_nway_result(lpa & advertise);
-	duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+	if (IS_ERR(phydev)) {
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(phydev);
+	}
 
-	if (ok_to_print)
-		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
-		       mii->dev->name,
-		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
-		       duplex ? "full" : "half", lpa);
+	/* mask with MAC supported features */
+	phydev->supported &= PHY_BASIC_FEATURES;
 
-	mii->full_duplex = duplex;
+	phydev->advertising = phydev->supported;
 
-	/* Let the MAC know about the new link state */
-	macb_set_media(bp, media);
+	bp->link = 0;
+	bp->speed = 0;
+	bp->duplex = -1;
+	bp->phy_dev = phydev;
+
+	return 0;
+}
+
+static int macb_mii_init(struct macb *bp)
+{
+	struct eth_platform_data *pdata;
+	int err = -ENXIO, i;
+
+	/* Enable managment port */
+	macb_writel(bp, NCR, MACB_BIT(MPE));
+
+	bp->mii_bus.name = "MACB_mii_bus",
+	bp->mii_bus.read = &macb_mdio_read,
+	bp->mii_bus.write = &macb_mdio_write,
+	bp->mii_bus.reset = &macb_mdio_reset,
+	bp->mii_bus.id = bp->pdev->id,
+	bp->mii_bus.priv = bp,
+	bp->mii_bus.dev = &bp->dev->dev;
+	pdata = bp->pdev->dev.platform_data;
+
+	if (pdata)
+		bp->mii_bus.phy_mask = pdata->phy_mask;
+
+	bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	if (!bp->mii_bus.irq) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		bp->mii_bus.irq[i] = PHY_POLL;
+
+	platform_set_drvdata(bp->dev, &bp->mii_bus);
+
+	if (mdiobus_register(&bp->mii_bus))
+		goto err_out_free_mdio_irq;
+
+	if (macb_mii_probe(bp->dev) != 0) {
+		goto err_out_unregister_bus;
+	}
+
+	return 0;
+
+err_out_unregister_bus:
+	mdiobus_unregister(&bp->mii_bus);
+err_out_free_mdio_irq:
+	kfree(bp->mii_bus.irq);
+err_out:
+	return err;
 }
 
 static void macb_update_stats(struct macb *bp)
@@ -265,16 +294,6 @@
 		*p += __raw_readl(reg);
 }
 
-static void macb_periodic_task(struct work_struct *work)
-{
-	struct macb *bp = container_of(work, struct macb, periodic_task.work);
-
-	macb_update_stats(bp);
-	macb_check_media(bp, 1, 0);
-
-	schedule_delayed_work(&bp->periodic_task, HZ);
-}
-
 static void macb_tx(struct macb *bp)
 {
 	unsigned int tail;
@@ -519,9 +538,6 @@
 	spin_lock(&bp->lock);
 
 	while (status) {
-		if (status & MACB_BIT(MFD))
-			complete(&bp->mdio_complete);
-
 		/* close possible race with dev_close */
 		if (unlikely(!netif_running(dev))) {
 			macb_writel(bp, IDR, ~0UL);
@@ -535,7 +551,8 @@
 				 * until we have processed the buffers
 				 */
 				macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
-				dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n");
+				dev_dbg(&bp->pdev->dev,
+					"scheduling RX softirq\n");
 				__netif_rx_schedule(dev);
 			}
 		}
@@ -765,7 +782,7 @@
 	macb_writel(bp, TBQP, bp->tx_ring_dma);
 
 	/* Enable TX and RX */
-	macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE));
+	macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
 
 	/* Enable interrupts */
 	macb_writel(bp, IER, (MACB_BIT(RCOMP)
@@ -776,18 +793,126 @@
 			      | MACB_BIT(TCOMP)
 			      | MACB_BIT(ISR_ROVR)
 			      | MACB_BIT(HRESP)));
+
 }
 
-static void macb_init_phy(struct net_device *dev)
+/*
+ * The hash address register is 64 bits long and takes up two
+ * locations in the memory map.  The least significant bits are stored
+ * in EMAC_HSL and the most significant bits in EMAC_HSH.
+ *
+ * The unicast hash enable and the multicast hash enable bits in the
+ * network configuration register enable the reception of hash matched
+ * frames. The destination address is reduced to a 6 bit index into
+ * the 64 bit hash register using the following hash function.  The
+ * hash function is an exclusive or of every sixth bit of the
+ * destination address.
+ *
+ * hi[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
+ * hi[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
+ * hi[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
+ * hi[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
+ * hi[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
+ * hi[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
+ *
+ * da[0] represents the least significant bit of the first byte
+ * received, that is, the multicast/unicast indicator, and da[47]
+ * represents the most significant bit of the last byte received.  If
+ * the hash index, hi[n], points to a bit that is set in the hash
+ * register then the frame will be matched according to whether the
+ * frame is multicast or unicast.  A multicast match will be signalled
+ * if the multicast hash enable bit is set, da[0] is 1 and the hash
+ * index points to a bit set in the hash register.  A unicast match
+ * will be signalled if the unicast hash enable bit is set, da[0] is 0
+ * and the hash index points to a bit set in the hash register.  To
+ * receive all multicast frames, the hash register should be set with
+ * all ones and the multicast hash enable bit should be set in the
+ * network configuration register.
+ */
+
+static inline int hash_bit_value(int bitnr, __u8 *addr)
 {
+	if (addr[bitnr / 8] & (1 << (bitnr % 8)))
+		return 1;
+	return 0;
+}
+
+/*
+ * Return the hash index value for the specified address.
+ */
+static int hash_get_index(__u8 *addr)
+{
+	int i, j, bitval;
+	int hash_index = 0;
+
+	for (j = 0; j < 6; j++) {
+		for (i = 0, bitval = 0; i < 8; i++)
+			bitval ^= hash_bit_value(i*6 + j, addr);
+
+		hash_index |= (bitval << j);
+	}
+
+	return hash_index;
+}
+
+/*
+ * Add multicast addresses to the internal multicast-hash table.
+ */
+static void macb_sethashtable(struct net_device *dev)
+{
+	struct dev_mc_list *curr;
+	unsigned long mc_filter[2];
+	unsigned int i, bitnr;
 	struct macb *bp = netdev_priv(dev);
 
-	/* Set some reasonable default settings */
-	macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE,
-			ADVERTISE_CSMA | ADVERTISE_ALL);
-	macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR,
-			(BMCR_SPEED100 | BMCR_ANENABLE
-			 | BMCR_ANRESTART | BMCR_FULLDPLX));
+	mc_filter[0] = mc_filter[1] = 0;
+
+	curr = dev->mc_list;
+	for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
+		if (!curr) break;	/* unexpected end of list */
+
+		bitnr = hash_get_index(curr->dmi_addr);
+		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
+	}
+
+	macb_writel(bp, HRB, mc_filter[0]);
+	macb_writel(bp, HRT, mc_filter[1]);
+}
+
+/*
+ * Enable/Disable promiscuous and multicast modes.
+ */
+static void macb_set_rx_mode(struct net_device *dev)
+{
+	unsigned long cfg;
+	struct macb *bp = netdev_priv(dev);
+
+	cfg = macb_readl(bp, NCFGR);
+
+	if (dev->flags & IFF_PROMISC)
+		/* Enable promiscuous mode */
+		cfg |= MACB_BIT(CAF);
+	else if (dev->flags & (~IFF_PROMISC))
+		 /* Disable promiscuous mode */
+		cfg &= ~MACB_BIT(CAF);
+
+	if (dev->flags & IFF_ALLMULTI) {
+		/* Enable all multicast mode */
+		macb_writel(bp, HRB, -1);
+		macb_writel(bp, HRT, -1);
+		cfg |= MACB_BIT(NCFGR_MTI);
+	} else if (dev->mc_count > 0) {
+		/* Enable specific multicasts */
+		macb_sethashtable(dev);
+		cfg |= MACB_BIT(NCFGR_MTI);
+	} else if (dev->flags & (~IFF_ALLMULTI)) {
+		/* Disable all multicast mode */
+		macb_writel(bp, HRB, 0);
+		macb_writel(bp, HRT, 0);
+		cfg &= ~MACB_BIT(NCFGR_MTI);
+	}
+
+	macb_writel(bp, NCFGR, cfg);
 }
 
 static int macb_open(struct net_device *dev)
@@ -797,6 +922,10 @@
 
 	dev_dbg(&bp->pdev->dev, "open\n");
 
+	/* if the phy is not yet register, retry later*/
+	if (!bp->phy_dev)
+		return -EAGAIN;
+
 	if (!is_valid_ether_addr(dev->dev_addr))
 		return -EADDRNOTAVAIL;
 
@@ -810,13 +939,12 @@
 
 	macb_init_rings(bp);
 	macb_init_hw(bp);
-	macb_init_phy(dev);
 
-	macb_check_media(bp, 1, 1);
+	/* schedule a link state check */
+	phy_start(bp->phy_dev);
+
 	netif_start_queue(dev);
 
-	schedule_delayed_work(&bp->periodic_task, HZ);
-
 	return 0;
 }
 
@@ -825,10 +953,11 @@
 	struct macb *bp = netdev_priv(dev);
 	unsigned long flags;
 
-	cancel_rearming_delayed_work(&bp->periodic_task);
-
 	netif_stop_queue(dev);
 
+	if (bp->phy_dev)
+		phy_stop(bp->phy_dev);
+
 	spin_lock_irqsave(&bp->lock, flags);
 	macb_reset_hw(bp);
 	netif_carrier_off(dev);
@@ -845,6 +974,9 @@
 	struct net_device_stats *nstat = &bp->stats;
 	struct macb_stats *hwstat = &bp->hw_stats;
 
+	/* read stats from hardware */
+	macb_update_stats(bp);
+
 	/* Convert HW stats into netdevice stats */
 	nstat->rx_errors = (hwstat->rx_fcs_errors +
 			    hwstat->rx_align_errors +
@@ -882,18 +1014,27 @@
 static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
 
-	return mii_ethtool_gset(&bp->mii, cmd);
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_gset(phydev, cmd);
 }
 
 static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
 
-	return mii_ethtool_sset(&bp->mii, cmd);
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, cmd);
 }
 
-static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void macb_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
 {
 	struct macb *bp = netdev_priv(dev);
 
@@ -902,104 +1043,34 @@
 	strcpy(info->bus_info, bp->pdev->dev.bus_id);
 }
 
-static int macb_nway_reset(struct net_device *dev)
-{
-	struct macb *bp = netdev_priv(dev);
-	return mii_nway_restart(&bp->mii);
-}
-
 static struct ethtool_ops macb_ethtool_ops = {
 	.get_settings		= macb_get_settings,
 	.set_settings		= macb_set_settings,
 	.get_drvinfo		= macb_get_drvinfo,
-	.nway_reset		= macb_nway_reset,
 	.get_link		= ethtool_op_get_link,
 };
 
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
 }
 
-static ssize_t macb_mii_show(const struct device *_dev, char *buf,
-			unsigned long addr)
-{
-	struct net_device *dev = to_net_dev(_dev);
-	struct macb *bp = netdev_priv(dev);
-	ssize_t ret = -EINVAL;
-
-	if (netif_running(dev)) {
-		int value;
-		value = macb_mdio_read(dev, bp->mii.phy_id, addr);
-		ret = sprintf(buf, "0x%04x\n", (uint16_t)value);
-	}
-
-	return ret;
-}
-
-#define MII_ENTRY(name, addr)					\
-static ssize_t show_##name(struct device *_dev,			\
-			   struct device_attribute *attr,	\
-			   char *buf)				\
-{								\
-	return macb_mii_show(_dev, buf, addr);			\
-}								\
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
-
-MII_ENTRY(bmcr, MII_BMCR);
-MII_ENTRY(bmsr, MII_BMSR);
-MII_ENTRY(physid1, MII_PHYSID1);
-MII_ENTRY(physid2, MII_PHYSID2);
-MII_ENTRY(advertise, MII_ADVERTISE);
-MII_ENTRY(lpa, MII_LPA);
-MII_ENTRY(expansion, MII_EXPANSION);
-
-static struct attribute *macb_mii_attrs[] = {
-	&dev_attr_bmcr.attr,
-	&dev_attr_bmsr.attr,
-	&dev_attr_physid1.attr,
-	&dev_attr_physid2.attr,
-	&dev_attr_advertise.attr,
-	&dev_attr_lpa.attr,
-	&dev_attr_expansion.attr,
-	NULL,
-};
-
-static struct attribute_group macb_mii_group = {
-	.name	= "mii",
-	.attrs	= macb_mii_attrs,
-};
-
-static void macb_unregister_sysfs(struct net_device *net)
-{
-	struct device *_dev = &net->dev;
-
-	sysfs_remove_group(&_dev->kobj, &macb_mii_group);
-}
-
-static int macb_register_sysfs(struct net_device *net)
-{
-	struct device *_dev = &net->dev;
-	int ret;
-
-	ret = sysfs_create_group(&_dev->kobj, &macb_mii_group);
-	if (ret)
-		printk(KERN_WARNING
-		       "%s: sysfs mii attribute registration failed: %d\n",
-		       net->name, ret);
-	return ret;
-}
 static int __devinit macb_probe(struct platform_device *pdev)
 {
 	struct eth_platform_data *pdata;
 	struct resource *regs;
 	struct net_device *dev;
 	struct macb *bp;
+	struct phy_device *phydev;
 	unsigned long pclk_hz;
 	u32 config;
 	int err = -ENXIO;
@@ -1073,6 +1144,7 @@
 	dev->stop = macb_close;
 	dev->hard_start_xmit = macb_start_xmit;
 	dev->get_stats = macb_get_stats;
+	dev->set_multicast_list = macb_set_rx_mode;
 	dev->do_ioctl = macb_ioctl;
 	dev->poll = macb_poll;
 	dev->weight = 64;
@@ -1080,10 +1152,6 @@
 
 	dev->base_addr = regs->start;
 
-	INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
-	mutex_init(&bp->mdio_mutex);
-	init_completion(&bp->mdio_complete);
-
 	/* Set MII management clock divider */
 	pclk_hz = clk_get_rate(bp->pclk);
 	if (pclk_hz <= 20000000)
@@ -1096,20 +1164,9 @@
 		config = MACB_BF(CLK, MACB_CLK_DIV64);
 	macb_writel(bp, NCFGR, config);
 
-	bp->mii.dev = dev;
-	bp->mii.mdio_read = macb_mdio_read;
-	bp->mii.mdio_write = macb_mdio_write;
-	bp->mii.phy_id_mask = 0x1f;
-	bp->mii.reg_num_mask = 0x1f;
-
 	macb_get_hwaddr(bp);
-	err = macb_phy_probe(bp);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n");
-		goto err_out_free_irq;
-	}
-
 	pdata = pdev->dev.platform_data;
+
 	if (pdata && pdata->is_rmii)
 #if defined(CONFIG_ARCH_AT91)
 		macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) );
@@ -1131,9 +1188,11 @@
 		goto err_out_free_irq;
 	}
 
-	platform_set_drvdata(pdev, dev);
+	if (macb_mii_init(bp) != 0) {
+		goto err_out_unregister_netdev;
+	}
 
-	macb_register_sysfs(dev);
+	platform_set_drvdata(pdev, dev);
 
 	printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
 	       "(%02x:%02x:%02x:%02x:%02x:%02x)\n",
@@ -1141,8 +1200,15 @@
 	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
 	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
+	phydev = bp->phy_dev;
+	printk(KERN_INFO "%s: attached PHY driver [%s] "
+		"(mii_bus:phy_addr=%s, irq=%d)\n",
+		dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+
 	return 0;
 
+err_out_unregister_netdev:
+	unregister_netdev(dev);
 err_out_free_irq:
 	free_irq(dev->irq, dev);
 err_out_iounmap:
@@ -1153,7 +1219,9 @@
 	clk_put(bp->hclk);
 #endif
 	clk_disable(bp->pclk);
+#ifndef CONFIG_ARCH_AT91
 err_out_put_pclk:
+#endif
 	clk_put(bp->pclk);
 err_out_free_dev:
 	free_netdev(dev);
@@ -1171,7 +1239,8 @@
 
 	if (dev) {
 		bp = netdev_priv(dev);
-		macb_unregister_sysfs(dev);
+		mdiobus_unregister(&bp->mii_bus);
+		kfree(bp->mii_bus.irq);
 		unregister_netdev(dev);
 		free_irq(dev->irq, dev);
 		iounmap(bp->regs);
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index b3bb218..4e3283e 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -383,11 +383,11 @@
 
 	unsigned int		rx_pending, tx_pending;
 
-	struct delayed_work	periodic_task;
-
-	struct mutex		mdio_mutex;
-	struct completion	mdio_complete;
-	struct mii_if_info	mii;
+	struct mii_bus		mii_bus;
+	struct phy_device	*phy_dev;
+	unsigned int 		link;
+	unsigned int 		speed;
+	unsigned int 		duplex;
 };
 
 #endif /* _MACB_H */
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index e1732c1..deca653 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1060,7 +1060,6 @@
 	struct myri10ge_tx_buf *tx = &mgp->tx;
 	struct sk_buff *skb;
 	int idx, len;
-	int limit = 0;
 
 	while (tx->pkt_done != mcp_index) {
 		idx = tx->done & tx->mask;
@@ -1091,11 +1090,6 @@
 							      bus), len,
 					       PCI_DMA_TODEVICE);
 		}
-
-		/* limit potential for livelock by only handling
-		 * 2 full tx rings per call */
-		if (unlikely(++limit > 2 * tx->mask))
-			break;
 	}
 	/* start the queue if we've stopped it */
 	if (netif_queue_stopped(mgp->dev)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 58bbfdd..afef6c0 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -796,12 +796,14 @@
 	struct mac_info *mac_control;
 	struct config_param *config;
 	int lst_size, lst_per_page;
-	struct net_device *dev = nic->dev;
+	struct net_device *dev;
 	int page_num = 0;
 
 	if (!nic)
 		return;
 
+	dev = nic->dev;
+
 	mac_control = &nic->mac_control;
 	config = &nic->config;
 
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
new file mode 100644
index 0000000..8a667c1
--- /dev/null
+++ b/drivers/net/sunvnet.c
@@ -0,0 +1,1164 @@
+/* sunvnet.c: Sun LDOM Virtual Network Driver.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#include "sunvnet.h"
+
+#define DRV_MODULE_NAME		"sunvnet"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"June 25, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual network driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+/* Ordered from largest major to lowest */
+static struct vio_version vnet_versions[] = {
+	{ .major = 1, .minor = 0 },
+};
+
+static inline u32 vnet_tx_dring_avail(struct vio_dring_state *dr)
+{
+	return vio_dring_avail(dr, VNET_TX_RING_SIZE);
+}
+
+static int vnet_handle_unknown(struct vnet_port *port, void *arg)
+{
+	struct vio_msg_tag *pkt = arg;
+
+	printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+	printk(KERN_ERR PFX "Resetting connection.\n");
+
+	ldc_disconnect(port->vio.lp);
+
+	return -ECONNRESET;
+}
+
+static int vnet_send_attr(struct vio_driver_state *vio)
+{
+	struct vnet_port *port = to_vnet_port(vio);
+	struct net_device *dev = port->vp->dev;
+	struct vio_net_attr_info pkt;
+	int i;
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.tag.type = VIO_TYPE_CTRL;
+	pkt.tag.stype = VIO_SUBTYPE_INFO;
+	pkt.tag.stype_env = VIO_ATTR_INFO;
+	pkt.tag.sid = vio_send_sid(vio);
+	pkt.xfer_mode = VIO_DRING_MODE;
+	pkt.addr_type = VNET_ADDR_ETHERMAC;
+	pkt.ack_freq = 0;
+	for (i = 0; i < 6; i++)
+		pkt.addr |= (u64)dev->dev_addr[i] << ((5 - i) * 8);
+	pkt.mtu = ETH_FRAME_LEN;
+
+	viodbg(HS, "SEND NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
+	       "ackfreq[%u] mtu[%llu]\n",
+	       pkt.xfer_mode, pkt.addr_type,
+	       (unsigned long long) pkt.addr,
+	       pkt.ack_freq,
+	       (unsigned long long) pkt.mtu);
+
+	return vio_ldc_send(vio, &pkt, sizeof(pkt));
+}
+
+static int handle_attr_info(struct vio_driver_state *vio,
+			    struct vio_net_attr_info *pkt)
+{
+	viodbg(HS, "GOT NET ATTR INFO xmode[0x%x] atype[0x%x] addr[%llx] "
+	       "ackfreq[%u] mtu[%llu]\n",
+	       pkt->xfer_mode, pkt->addr_type,
+	       (unsigned long long) pkt->addr,
+	       pkt->ack_freq,
+	       (unsigned long long) pkt->mtu);
+
+	pkt->tag.sid = vio_send_sid(vio);
+
+	if (pkt->xfer_mode != VIO_DRING_MODE ||
+	    pkt->addr_type != VNET_ADDR_ETHERMAC ||
+	    pkt->mtu != ETH_FRAME_LEN) {
+		viodbg(HS, "SEND NET ATTR NACK\n");
+
+		pkt->tag.stype = VIO_SUBTYPE_NACK;
+
+		(void) vio_ldc_send(vio, pkt, sizeof(*pkt));
+
+		return -ECONNRESET;
+	} else {
+		viodbg(HS, "SEND NET ATTR ACK\n");
+
+		pkt->tag.stype = VIO_SUBTYPE_ACK;
+
+		return vio_ldc_send(vio, pkt, sizeof(*pkt));
+	}
+
+}
+
+static int handle_attr_ack(struct vio_driver_state *vio,
+			   struct vio_net_attr_info *pkt)
+{
+	viodbg(HS, "GOT NET ATTR ACK\n");
+
+	return 0;
+}
+
+static int handle_attr_nack(struct vio_driver_state *vio,
+			    struct vio_net_attr_info *pkt)
+{
+	viodbg(HS, "GOT NET ATTR NACK\n");
+
+	return -ECONNRESET;
+}
+
+static int vnet_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+	struct vio_net_attr_info *pkt = arg;
+
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return handle_attr_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return handle_attr_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return handle_attr_nack(vio, pkt);
+
+	default:
+		return -ECONNRESET;
+	}
+}
+
+static void vnet_handshake_complete(struct vio_driver_state *vio)
+{
+	struct vio_dring_state *dr;
+
+	dr = &vio->drings[VIO_DRIVER_RX_RING];
+	dr->snd_nxt = dr->rcv_nxt = 1;
+
+	dr = &vio->drings[VIO_DRIVER_TX_RING];
+	dr->snd_nxt = dr->rcv_nxt = 1;
+}
+
+/* The hypervisor interface that implements copying to/from imported
+ * memory from another domain requires that copies are done to 8-byte
+ * aligned buffers, and that the lengths of such copies are also 8-byte
+ * multiples.
+ *
+ * So we align skb->data to an 8-byte multiple and pad-out the data
+ * area so we can round the copy length up to the next multiple of
+ * 8 for the copy.
+ *
+ * The transmitter puts the actual start of the packet 6 bytes into
+ * the buffer it sends over, so that the IP headers after the ethernet
+ * header are aligned properly.  These 6 bytes are not in the descriptor
+ * length, they are simply implied.  This offset is represented using
+ * the VNET_PACKET_SKIP macro.
+ */
+static struct sk_buff *alloc_and_align_skb(struct net_device *dev,
+					   unsigned int len)
+{
+	struct sk_buff *skb = netdev_alloc_skb(dev, len+VNET_PACKET_SKIP+8+8);
+	unsigned long addr, off;
+
+	if (unlikely(!skb))
+		return NULL;
+
+	addr = (unsigned long) skb->data;
+	off = ((addr + 7UL) & ~7UL) - addr;
+	if (off)
+		skb_reserve(skb, off);
+
+	return skb;
+}
+
+static int vnet_rx_one(struct vnet_port *port, unsigned int len,
+		       struct ldc_trans_cookie *cookies, int ncookies)
+{
+	struct net_device *dev = port->vp->dev;
+	unsigned int copy_len;
+	struct sk_buff *skb;
+	int err;
+
+	err = -EMSGSIZE;
+	if (unlikely(len < ETH_ZLEN || len > ETH_FRAME_LEN)) {
+		dev->stats.rx_length_errors++;
+		goto out_dropped;
+	}
+
+	skb = alloc_and_align_skb(dev, len);
+	err = -ENOMEM;
+	if (unlikely(!skb)) {
+		dev->stats.rx_missed_errors++;
+		goto out_dropped;
+	}
+
+	copy_len = (len + VNET_PACKET_SKIP + 7U) & ~7U;
+	skb_put(skb, copy_len);
+	err = ldc_copy(port->vio.lp, LDC_COPY_IN,
+		       skb->data, copy_len, 0,
+		       cookies, ncookies);
+	if (unlikely(err < 0)) {
+		dev->stats.rx_frame_errors++;
+		goto out_free_skb;
+	}
+
+	skb_pull(skb, VNET_PACKET_SKIP);
+	skb_trim(skb, len);
+	skb->protocol = eth_type_trans(skb, dev);
+
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += len;
+
+	netif_rx(skb);
+
+	return 0;
+
+out_free_skb:
+	kfree_skb(skb);
+
+out_dropped:
+	dev->stats.rx_dropped++;
+	return err;
+}
+
+static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
+			 u32 start, u32 end, u8 vio_dring_state)
+{
+	struct vio_dring_data hdr = {
+		.tag = {
+			.type		= VIO_TYPE_DATA,
+			.stype		= VIO_SUBTYPE_ACK,
+			.stype_env	= VIO_DRING_DATA,
+			.sid		= vio_send_sid(&port->vio),
+		},
+		.dring_ident		= dr->ident,
+		.start_idx		= start,
+		.end_idx		= end,
+		.state			= vio_dring_state,
+	};
+	int err, delay;
+
+	hdr.seq = dr->snd_nxt;
+	delay = 1;
+	do {
+		err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+		if (err > 0) {
+			dr->snd_nxt++;
+			break;
+		}
+		udelay(delay);
+		if ((delay <<= 1) > 128)
+			delay = 128;
+	} while (err == -EAGAIN);
+
+	return err;
+}
+
+static u32 next_idx(u32 idx, struct vio_dring_state *dr)
+{
+	if (++idx == dr->num_entries)
+		idx = 0;
+	return idx;
+}
+
+static u32 prev_idx(u32 idx, struct vio_dring_state *dr)
+{
+	if (idx == 0)
+		idx = dr->num_entries - 1;
+	else
+		idx--;
+
+	return idx;
+}
+
+static struct vio_net_desc *get_rx_desc(struct vnet_port *port,
+					struct vio_dring_state *dr,
+					u32 index)
+{
+	struct vio_net_desc *desc = port->vio.desc_buf;
+	int err;
+
+	err = ldc_get_dring_entry(port->vio.lp, desc, dr->entry_size,
+				  (index * dr->entry_size),
+				  dr->cookies, dr->ncookies);
+	if (err < 0)
+		return ERR_PTR(err);
+
+	return desc;
+}
+
+static int put_rx_desc(struct vnet_port *port,
+		       struct vio_dring_state *dr,
+		       struct vio_net_desc *desc,
+		       u32 index)
+{
+	int err;
+
+	err = ldc_put_dring_entry(port->vio.lp, desc, dr->entry_size,
+				  (index * dr->entry_size),
+				  dr->cookies, dr->ncookies);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int vnet_walk_rx_one(struct vnet_port *port,
+			    struct vio_dring_state *dr,
+			    u32 index, int *needs_ack)
+{
+	struct vio_net_desc *desc = get_rx_desc(port, dr, index);
+	struct vio_driver_state *vio = &port->vio;
+	int err;
+
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+
+	viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%lx:%lx]\n",
+	       desc->hdr.state, desc->hdr.ack,
+	       desc->size, desc->ncookies,
+	       desc->cookies[0].cookie_addr,
+	       desc->cookies[0].cookie_size);
+
+	if (desc->hdr.state != VIO_DESC_READY)
+		return 1;
+	err = vnet_rx_one(port, desc->size, desc->cookies, desc->ncookies);
+	if (err == -ECONNRESET)
+		return err;
+	desc->hdr.state = VIO_DESC_DONE;
+	err = put_rx_desc(port, dr, desc, index);
+	if (err < 0)
+		return err;
+	*needs_ack = desc->hdr.ack;
+	return 0;
+}
+
+static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr,
+			u32 start, u32 end)
+{
+	struct vio_driver_state *vio = &port->vio;
+	int ack_start = -1, ack_end = -1;
+
+	end = (end == (u32) -1) ? prev_idx(start, dr) : next_idx(end, dr);
+
+	viodbg(DATA, "vnet_walk_rx start[%08x] end[%08x]\n", start, end);
+
+	while (start != end) {
+		int ack = 0, err = vnet_walk_rx_one(port, dr, start, &ack);
+		if (err == -ECONNRESET)
+			return err;
+		if (err != 0)
+			break;
+		if (ack_start == -1)
+			ack_start = start;
+		ack_end = start;
+		start = next_idx(start, dr);
+		if (ack && start != end) {
+			err = vnet_send_ack(port, dr, ack_start, ack_end,
+					    VIO_DRING_ACTIVE);
+			if (err == -ECONNRESET)
+				return err;
+			ack_start = -1;
+		}
+	}
+	if (unlikely(ack_start == -1))
+		ack_start = ack_end = prev_idx(start, dr);
+	return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED);
+}
+
+static int vnet_rx(struct vnet_port *port, void *msgbuf)
+{
+	struct vio_dring_data *pkt = msgbuf;
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_RX_RING];
+	struct vio_driver_state *vio = &port->vio;
+
+	viodbg(DATA, "vnet_rx stype_env[%04x] seq[%016lx] rcv_nxt[%016lx]\n",
+	       pkt->tag.stype_env, pkt->seq, dr->rcv_nxt);
+
+	if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+		return 0;
+	if (unlikely(pkt->seq != dr->rcv_nxt)) {
+		printk(KERN_ERR PFX "RX out of sequence seq[0x%lx] "
+		       "rcv_nxt[0x%lx]\n", pkt->seq, dr->rcv_nxt);
+		return 0;
+	}
+
+	dr->rcv_nxt++;
+
+	/* XXX Validate pkt->start_idx and pkt->end_idx XXX */
+
+	return vnet_walk_rx(port, dr, pkt->start_idx, pkt->end_idx);
+}
+
+static int idx_is_pending(struct vio_dring_state *dr, u32 end)
+{
+	u32 idx = dr->cons;
+	int found = 0;
+
+	while (idx != dr->prod) {
+		if (idx == end) {
+			found = 1;
+			break;
+		}
+		idx = next_idx(idx, dr);
+	}
+	return found;
+}
+
+static int vnet_ack(struct vnet_port *port, void *msgbuf)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data *pkt = msgbuf;
+	struct net_device *dev;
+	struct vnet *vp;
+	u32 end;
+
+	if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+		return 0;
+
+	end = pkt->end_idx;
+	if (unlikely(!idx_is_pending(dr, end)))
+		return 0;
+
+	dr->cons = next_idx(end, dr);
+
+	vp = port->vp;
+	dev = vp->dev;
+	if (unlikely(netif_queue_stopped(dev) &&
+		     vnet_tx_dring_avail(dr) >= VNET_TX_WAKEUP_THRESH(dr)))
+		return 1;
+
+	return 0;
+}
+
+static int vnet_nack(struct vnet_port *port, void *msgbuf)
+{
+	/* XXX just reset or similar XXX */
+	return 0;
+}
+
+static void maybe_tx_wakeup(struct vnet *vp)
+{
+	struct net_device *dev = vp->dev;
+
+	netif_tx_lock(dev);
+	if (likely(netif_queue_stopped(dev))) {
+		struct vnet_port *port;
+		int wake = 1;
+
+		list_for_each_entry(port, &vp->port_list, list) {
+			struct vio_dring_state *dr;
+
+			dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+			if (vnet_tx_dring_avail(dr) <
+			    VNET_TX_WAKEUP_THRESH(dr)) {
+				wake = 0;
+				break;
+			}
+		}
+		if (wake)
+			netif_wake_queue(dev);
+	}
+	netif_tx_unlock(dev);
+}
+
+static void vnet_event(void *arg, int event)
+{
+	struct vnet_port *port = arg;
+	struct vio_driver_state *vio = &port->vio;
+	unsigned long flags;
+	int tx_wakeup, err;
+
+	spin_lock_irqsave(&vio->lock, flags);
+
+	if (unlikely(event == LDC_EVENT_RESET ||
+		     event == LDC_EVENT_UP)) {
+		vio_link_state_change(vio, event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+
+		return;
+	}
+
+	if (unlikely(event != LDC_EVENT_DATA_READY)) {
+		printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+		return;
+	}
+
+	tx_wakeup = err = 0;
+	while (1) {
+		union {
+			struct vio_msg_tag tag;
+			u64 raw[8];
+		} msgbuf;
+
+		err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				vio_conn_reset(vio);
+			break;
+		}
+		if (err == 0)
+			break;
+		viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+		       msgbuf.tag.type,
+		       msgbuf.tag.stype,
+		       msgbuf.tag.stype_env,
+		       msgbuf.tag.sid);
+		err = vio_validate_sid(vio, &msgbuf.tag);
+		if (err < 0)
+			break;
+
+		if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+			if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) {
+				err = vnet_rx(port, &msgbuf);
+			} else if (msgbuf.tag.stype == VIO_SUBTYPE_ACK) {
+				err = vnet_ack(port, &msgbuf);
+				if (err > 0)
+					tx_wakeup |= err;
+			} else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK) {
+				err = vnet_nack(port, &msgbuf);
+			}
+		} else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+			err = vio_control_pkt_engine(vio, &msgbuf);
+			if (err)
+				break;
+		} else {
+			err = vnet_handle_unknown(port, &msgbuf);
+		}
+		if (err == -ECONNRESET)
+			break;
+	}
+	spin_unlock(&vio->lock);
+	if (unlikely(tx_wakeup && err != -ECONNRESET))
+		maybe_tx_wakeup(port->vp);
+	local_irq_restore(flags);
+}
+
+static int __vnet_tx_trigger(struct vnet_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data hdr = {
+		.tag = {
+			.type		= VIO_TYPE_DATA,
+			.stype		= VIO_SUBTYPE_INFO,
+			.stype_env	= VIO_DRING_DATA,
+			.sid		= vio_send_sid(&port->vio),
+		},
+		.dring_ident		= dr->ident,
+		.start_idx		= dr->prod,
+		.end_idx		= (u32) -1,
+	};
+	int err, delay;
+
+	hdr.seq = dr->snd_nxt;
+	delay = 1;
+	do {
+		err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+		if (err > 0) {
+			dr->snd_nxt++;
+			break;
+		}
+		udelay(delay);
+		if ((delay <<= 1) > 128)
+			delay = 128;
+	} while (err == -EAGAIN);
+
+	return err;
+}
+
+struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+	unsigned int hash = vnet_hashfn(skb->data);
+	struct hlist_head *hp = &vp->port_hash[hash];
+	struct hlist_node *n;
+	struct vnet_port *port;
+
+	hlist_for_each_entry(port, n, hp, hash) {
+		if (!compare_ether_addr(port->raddr, skb->data))
+			return port;
+	}
+	port = NULL;
+	if (!list_empty(&vp->port_list))
+		port = list_entry(vp->port_list.next, struct vnet_port, list);
+
+	return port;
+}
+
+struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+	struct vnet_port *ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vp->lock, flags);
+	ret = __tx_port_find(vp, skb);
+	spin_unlock_irqrestore(&vp->lock, flags);
+
+	return ret;
+}
+
+static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vnet *vp = netdev_priv(dev);
+	struct vnet_port *port = tx_port_find(vp, skb);
+	struct vio_dring_state *dr;
+	struct vio_net_desc *d;
+	unsigned long flags;
+	unsigned int len;
+	void *tx_buf;
+	int i, err;
+
+	if (unlikely(!port))
+		goto out_dropped;
+
+	spin_lock_irqsave(&port->vio.lock, flags);
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+		if (!netif_queue_stopped(dev)) {
+			netif_stop_queue(dev);
+
+			/* This is a hard error, log it. */
+			printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+			       "queue awake!\n", dev->name);
+			dev->stats.tx_errors++;
+		}
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+	d = vio_dring_cur(dr);
+
+	tx_buf = port->tx_bufs[dr->prod].buf;
+	skb_copy_from_linear_data(skb, tx_buf + VNET_PACKET_SKIP, skb->len);
+
+	len = skb->len;
+	if (len < ETH_ZLEN) {
+		len = ETH_ZLEN;
+		memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len);
+	}
+
+	d->hdr.ack = VIO_ACK_ENABLE;
+	d->size = len;
+	d->ncookies = port->tx_bufs[dr->prod].ncookies;
+	for (i = 0; i < d->ncookies; i++)
+		d->cookies[i] = port->tx_bufs[dr->prod].cookies[i];
+
+	/* This has to be a non-SMP write barrier because we are writing
+	 * to memory which is shared with the peer LDOM.
+	 */
+	wmb();
+
+	d->hdr.state = VIO_DESC_READY;
+
+	err = __vnet_tx_trigger(port);
+	if (unlikely(err < 0)) {
+		printk(KERN_INFO PFX "%s: TX trigger error %d\n",
+		       dev->name, err);
+		d->hdr.state = VIO_DESC_FREE;
+		dev->stats.tx_carrier_errors++;
+		goto out_dropped_unlock;
+	}
+
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
+	if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+		netif_stop_queue(dev);
+		if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
+			netif_wake_queue(dev);
+	}
+
+	spin_unlock_irqrestore(&port->vio.lock, flags);
+
+	dev_kfree_skb(skb);
+
+	dev->trans_start = jiffies;
+	return NETDEV_TX_OK;
+
+out_dropped_unlock:
+	spin_unlock_irqrestore(&port->vio.lock, flags);
+
+out_dropped:
+	dev_kfree_skb(skb);
+	dev->stats.tx_dropped++;
+	return NETDEV_TX_OK;
+}
+
+static void vnet_tx_timeout(struct net_device *dev)
+{
+	/* XXX Implement me XXX */
+}
+
+static int vnet_open(struct net_device *dev)
+{
+	netif_carrier_on(dev);
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int vnet_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	return 0;
+}
+
+static void vnet_set_rx_mode(struct net_device *dev)
+{
+	/* XXX Implement multicast support XXX */
+}
+
+static int vnet_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if (new_mtu != ETH_DATA_LEN)
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+static int vnet_set_mac_addr(struct net_device *dev, void *p)
+{
+	return -EINVAL;
+}
+
+static void vnet_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_MODULE_NAME);
+	strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static u32 vnet_get_msglevel(struct net_device *dev)
+{
+	struct vnet *vp = netdev_priv(dev);
+	return vp->msg_enable;
+}
+
+static void vnet_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct vnet *vp = netdev_priv(dev);
+	vp->msg_enable = value;
+}
+
+static const struct ethtool_ops vnet_ethtool_ops = {
+	.get_drvinfo		= vnet_get_drvinfo,
+	.get_msglevel		= vnet_get_msglevel,
+	.set_msglevel		= vnet_set_msglevel,
+	.get_link		= ethtool_op_get_link,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
+};
+
+static void vnet_port_free_tx_bufs(struct vnet_port *port)
+{
+	struct vio_dring_state *dr;
+	int i;
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	if (dr->base) {
+		ldc_free_exp_dring(port->vio.lp, dr->base,
+				   (dr->entry_size * dr->num_entries),
+				   dr->cookies, dr->ncookies);
+		dr->base = NULL;
+		dr->entry_size = 0;
+		dr->num_entries = 0;
+		dr->pending = 0;
+		dr->ncookies = 0;
+	}
+
+	for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+		void *buf = port->tx_bufs[i].buf;
+
+		if (!buf)
+			continue;
+
+		ldc_unmap(port->vio.lp,
+			  port->tx_bufs[i].cookies,
+			  port->tx_bufs[i].ncookies);
+
+		kfree(buf);
+		port->tx_bufs[i].buf = NULL;
+	}
+}
+
+static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
+{
+	struct vio_dring_state *dr;
+	unsigned long len;
+	int i, err, ncookies;
+	void *dring;
+
+	for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+		void *buf = kzalloc(ETH_FRAME_LEN + 8, GFP_KERNEL);
+		int map_len = (ETH_FRAME_LEN + 7) & ~7;
+
+		err = -ENOMEM;
+		if (!buf) {
+			printk(KERN_ERR "TX buffer allocation failure\n");
+			goto err_out;
+		}
+		err = -EFAULT;
+		if ((unsigned long)buf & (8UL - 1)) {
+			printk(KERN_ERR "TX buffer misaligned\n");
+			kfree(buf);
+			goto err_out;
+		}
+
+		err = ldc_map_single(port->vio.lp, buf, map_len,
+				     port->tx_bufs[i].cookies, 2,
+				     (LDC_MAP_SHADOW |
+				      LDC_MAP_DIRECT |
+				      LDC_MAP_RW));
+		if (err < 0) {
+			kfree(buf);
+			goto err_out;
+		}
+		port->tx_bufs[i].buf = buf;
+		port->tx_bufs[i].ncookies = err;
+	}
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+	len = (VNET_TX_RING_SIZE *
+	       (sizeof(struct vio_net_desc) +
+		(sizeof(struct ldc_trans_cookie) * 2)));
+
+	ncookies = VIO_MAX_RING_COOKIES;
+	dring = ldc_alloc_exp_dring(port->vio.lp, len,
+				    dr->cookies, &ncookies,
+				    (LDC_MAP_SHADOW |
+				     LDC_MAP_DIRECT |
+				     LDC_MAP_RW));
+	if (IS_ERR(dring)) {
+		err = PTR_ERR(dring);
+		goto err_out;
+	}
+
+	dr->base = dring;
+	dr->entry_size = (sizeof(struct vio_net_desc) +
+			  (sizeof(struct ldc_trans_cookie) * 2));
+	dr->num_entries = VNET_TX_RING_SIZE;
+	dr->prod = dr->cons = 0;
+	dr->pending = VNET_TX_RING_SIZE;
+	dr->ncookies = ncookies;
+
+	return 0;
+
+err_out:
+	vnet_port_free_tx_bufs(port);
+
+	return err;
+}
+
+static struct ldc_channel_config vnet_ldc_cfg = {
+	.event		= vnet_event,
+	.mtu		= 64,
+	.mode		= LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vnet_vio_ops = {
+	.send_attr		= vnet_send_attr,
+	.handle_attr		= vnet_handle_attr,
+	.handshake_complete	= vnet_handshake_complete,
+};
+
+const char *remote_macaddr_prop = "remote-mac-address";
+
+static int __devinit vnet_port_probe(struct vio_dev *vdev,
+				     const struct vio_device_id *id)
+{
+	struct mdesc_handle *hp;
+	struct vnet_port *port;
+	unsigned long flags;
+	struct vnet *vp;
+	const u64 *rmac;
+	int len, i, err, switch_port;
+
+	vp = dev_get_drvdata(vdev->dev.parent);
+	if (!vp) {
+		printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
+		return -ENODEV;
+	}
+
+	hp = mdesc_grab();
+
+	rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
+	err = -ENODEV;
+	if (!rmac) {
+		printk(KERN_ERR PFX "Port lacks %s property.\n",
+		       remote_macaddr_prop);
+		goto err_out_put_mdesc;
+	}
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!port) {
+		printk(KERN_ERR PFX "Cannot allocate vnet_port.\n");
+		goto err_out_put_mdesc;
+	}
+
+	for (i = 0; i < ETH_ALEN; i++)
+		port->raddr[i] = (*rmac >> (5 - i) * 8) & 0xff;
+
+	port->vp = vp;
+
+	err = vio_driver_init(&port->vio, vdev, VDEV_NETWORK,
+			      vnet_versions, ARRAY_SIZE(vnet_versions),
+			      &vnet_vio_ops, vp->dev->name);
+	if (err)
+		goto err_out_free_port;
+
+	err = vio_ldc_alloc(&port->vio, &vnet_ldc_cfg, port);
+	if (err)
+		goto err_out_free_port;
+
+	err = vnet_port_alloc_tx_bufs(port);
+	if (err)
+		goto err_out_free_ldc;
+
+	INIT_HLIST_NODE(&port->hash);
+	INIT_LIST_HEAD(&port->list);
+
+	switch_port = 0;
+	if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL)
+		switch_port = 1;
+
+	spin_lock_irqsave(&vp->lock, flags);
+	if (switch_port)
+		list_add(&port->list, &vp->port_list);
+	else
+		list_add_tail(&port->list, &vp->port_list);
+	hlist_add_head(&port->hash, &vp->port_hash[vnet_hashfn(port->raddr)]);
+	spin_unlock_irqrestore(&vp->lock, flags);
+
+	dev_set_drvdata(&vdev->dev, port);
+
+	printk(KERN_INFO "%s: PORT ( remote-mac ", vp->dev->name);
+	for (i = 0; i < 6; i++)
+		printk("%2.2x%c", port->raddr[i], i == 5 ? ' ' : ':');
+	if (switch_port)
+		printk("switch-port ");
+	printk(")\n");
+
+	vio_port_up(&port->vio);
+
+	mdesc_release(hp);
+
+	return 0;
+
+err_out_free_ldc:
+	vio_ldc_free(&port->vio);
+
+err_out_free_port:
+	kfree(port);
+
+err_out_put_mdesc:
+	mdesc_release(hp);
+	return err;
+}
+
+static int vnet_port_remove(struct vio_dev *vdev)
+{
+	struct vnet_port *port = dev_get_drvdata(&vdev->dev);
+
+	if (port) {
+		struct vnet *vp = port->vp;
+		unsigned long flags;
+
+		del_timer_sync(&port->vio.timer);
+
+		spin_lock_irqsave(&vp->lock, flags);
+		list_del(&port->list);
+		hlist_del(&port->hash);
+		spin_unlock_irqrestore(&vp->lock, flags);
+
+		vnet_port_free_tx_bufs(port);
+		vio_ldc_free(&port->vio);
+
+		dev_set_drvdata(&vdev->dev, NULL);
+
+		kfree(port);
+	}
+	return 0;
+}
+
+static struct vio_device_id vnet_port_match[] = {
+	{
+		.type = "vnet-port",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_port_driver = {
+	.id_table	= vnet_port_match,
+	.probe		= vnet_port_probe,
+	.remove		= vnet_port_remove,
+	.driver		= {
+		.name	= "vnet_port",
+		.owner	= THIS_MODULE,
+	}
+};
+
+const char *local_mac_prop = "local-mac-address";
+
+static int __devinit vnet_probe(struct vio_dev *vdev,
+				const struct vio_device_id *id)
+{
+	static int vnet_version_printed;
+	struct mdesc_handle *hp;
+	struct net_device *dev;
+	struct vnet *vp;
+	const u64 *mac;
+	int err, i, len;
+
+	if (vnet_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	hp = mdesc_grab();
+
+	mac = mdesc_get_property(hp, vdev->mp, local_mac_prop, &len);
+	if (!mac) {
+		printk(KERN_ERR PFX "vnet lacks %s property.\n",
+		       local_mac_prop);
+		err = -ENODEV;
+		goto err_out;
+	}
+
+	dev = alloc_etherdev(sizeof(*vp));
+	if (!dev) {
+		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < ETH_ALEN; i++)
+		dev->dev_addr[i] = (*mac >> (5 - i) * 8) & 0xff;
+
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+	SET_NETDEV_DEV(dev, &vdev->dev);
+
+	vp = netdev_priv(dev);
+
+	spin_lock_init(&vp->lock);
+	vp->dev = dev;
+	vp->vdev = vdev;
+
+	INIT_LIST_HEAD(&vp->port_list);
+	for (i = 0; i < VNET_PORT_HASH_SIZE; i++)
+		INIT_HLIST_HEAD(&vp->port_hash[i]);
+
+	dev->open = vnet_open;
+	dev->stop = vnet_close;
+	dev->set_multicast_list = vnet_set_rx_mode;
+	dev->set_mac_address = vnet_set_mac_addr;
+	dev->tx_timeout = vnet_tx_timeout;
+	dev->ethtool_ops = &vnet_ethtool_ops;
+	dev->watchdog_timeo = VNET_TX_TIMEOUT;
+	dev->change_mtu = vnet_change_mtu;
+	dev->hard_start_xmit = vnet_start_xmit;
+
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot register net device, "
+		       "aborting.\n");
+		goto err_out_free_dev;
+	}
+
+	printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name);
+
+	for (i = 0; i < 6; i++)
+		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
+
+	dev_set_drvdata(&vdev->dev, vp);
+
+	mdesc_release(hp);
+
+	return 0;
+
+err_out_free_dev:
+	free_netdev(dev);
+
+err_out:
+	mdesc_release(hp);
+	return err;
+}
+
+static int vnet_remove(struct vio_dev *vdev)
+{
+
+	struct vnet *vp = dev_get_drvdata(&vdev->dev);
+
+	if (vp) {
+		/* XXX unregister port, or at least check XXX */
+		unregister_netdevice(vp->dev);
+		dev_set_drvdata(&vdev->dev, NULL);
+	}
+	return 0;
+}
+
+static struct vio_device_id vnet_match[] = {
+	{
+		.type = "network",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_driver = {
+	.id_table	= vnet_match,
+	.probe		= vnet_probe,
+	.remove		= vnet_remove,
+	.driver		= {
+		.name	= "vnet",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init vnet_init(void)
+{
+	int err = vio_register_driver(&vnet_driver);
+
+	if (!err) {
+		err = vio_register_driver(&vnet_port_driver);
+		if (err)
+			vio_unregister_driver(&vnet_driver);
+	}
+
+	return err;
+}
+
+static void __exit vnet_exit(void)
+{
+	vio_unregister_driver(&vnet_port_driver);
+	vio_unregister_driver(&vnet_driver);
+}
+
+module_init(vnet_init);
+module_exit(vnet_exit);
diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h
new file mode 100644
index 0000000..1c88730
--- /dev/null
+++ b/drivers/net/sunvnet.h
@@ -0,0 +1,70 @@
+#ifndef _SUNVNET_H
+#define _SUNVNET_H
+
+#define DESC_NCOOKIES(entry_size)	\
+	((entry_size) - sizeof(struct vio_net_desc))
+
+/* length of time before we decide the hardware is borked,
+ * and dev->tx_timeout() should be called to fix the problem
+ */
+#define VNET_TX_TIMEOUT			(5 * HZ)
+
+#define VNET_TX_RING_SIZE		512
+#define VNET_TX_WAKEUP_THRESH(dr)	((dr)->pending / 4)
+
+/* VNET packets are sent in buffers with the first 6 bytes skipped
+ * so that after the ethernet header the IPv4/IPv6 headers are aligned
+ * properly.
+ */
+#define VNET_PACKET_SKIP		6
+
+struct vnet_tx_entry {
+	void			*buf;
+	unsigned int		ncookies;
+	struct ldc_trans_cookie	cookies[2];
+};
+
+struct vnet;
+struct vnet_port {
+	struct vio_driver_state	vio;
+
+	struct hlist_node	hash;
+	u8			raddr[ETH_ALEN];
+
+	struct vnet		*vp;
+
+	struct vnet_tx_entry	tx_bufs[VNET_TX_RING_SIZE];
+
+	struct list_head	list;
+};
+
+static inline struct vnet_port *to_vnet_port(struct vio_driver_state *vio)
+{
+	return container_of(vio, struct vnet_port, vio);
+}
+
+#define VNET_PORT_HASH_SIZE	16
+#define VNET_PORT_HASH_MASK	(VNET_PORT_HASH_SIZE - 1)
+
+static inline unsigned int vnet_hashfn(u8 *mac)
+{
+	unsigned int val = mac[4] ^ mac[5];
+
+	return val & (VNET_PORT_HASH_MASK);
+}
+
+struct vnet {
+	/* Protects port_list and port_hash.  */
+	spinlock_t		lock;
+
+	struct net_device	*dev;
+
+	u32			msg_enable;
+	struct vio_dev		*vdev;
+
+	struct list_head	port_list;
+
+	struct hlist_head	port_hash[VNET_PORT_HASH_SIZE];
+};
+
+#endif /* _SUNVNET_H */
diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c
index bc62b01..943988e 100644
--- a/drivers/net/usb/cdc_subset.c
+++ b/drivers/net/usb/cdc_subset.c
@@ -305,6 +305,9 @@
 	USB_DEVICE (0x8086, 0x07d3),	// "blob" bootloader
 	.driver_info =	(unsigned long) &blob_info,
 }, {
+	USB_DEVICE (0x1286, 0x8001),    // "blob" bootloader
+	.driver_info =  (unsigned long) &blob_info,
+}, {
 	// Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config
 	// e.g. Gumstix, current OpenZaurus, ...
 	USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 4fc8681..a3df09e 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -61,7 +61,7 @@
 #
 config LANMEDIA
 	tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	---help---
 	  Driver for the following Lan Media family of serial boards:
 
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2d3a180..ee1cc14 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -52,6 +52,8 @@
 
 #include "airo.h"
 
+#define DRV_NAME "airo"
+
 #ifdef CONFIG_PCI
 static struct pci_device_id card_ids[] = {
 	{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
@@ -71,7 +73,7 @@
 static int airo_pci_resume(struct pci_dev *pdev);
 
 static struct pci_driver airo_driver = {
-	.name     = "airo",
+	.name     = DRV_NAME,
 	.id_table = card_ids,
 	.probe    = airo_pci_probe,
 	.remove   = __devexit_p(airo_pci_remove),
@@ -1092,7 +1094,7 @@
 static void OUT4500( struct airo_info *, u16 register, u16 value );
 static unsigned short IN4500( struct airo_info *, u16 register );
 static u16 setup_card(struct airo_info*, u8 *mac, int lock);
-static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock );
+static int enable_MAC(struct airo_info *ai, int lock);
 static void disable_MAC(struct airo_info *ai, int lock);
 static void enable_interrupts(struct airo_info*);
 static void disable_interrupts(struct airo_info*);
@@ -1250,7 +1252,7 @@
 static int flashrestart(struct airo_info *ai,struct net_device *dev);
 
 #define airo_print(type, name, fmt, args...) \
-	{ printk(type "airo(%s): " fmt "\n", name, ##args); }
+	printk(type DRV_NAME "(%s): " fmt "\n", name, ##args)
 
 #define airo_print_info(name, fmt, args...) \
 	airo_print(KERN_INFO, name, fmt, ##args)
@@ -1926,28 +1928,54 @@
 	return rc;
 }
 
-static int airo_open(struct net_device *dev) {
-	struct airo_info *info = dev->priv;
-	Resp rsp;
+static void try_auto_wep(struct airo_info *ai)
+{
+	if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
+		ai->expires = RUN_AT(3*HZ);
+		wake_up_interruptible(&ai->thr_wait);
+	}
+}
 
-	if (test_bit(FLAG_FLASHING, &info->flags))
+static int airo_open(struct net_device *dev) {
+	struct airo_info *ai = dev->priv;
+	int rc = 0;
+
+	if (test_bit(FLAG_FLASHING, &ai->flags))
 		return -EIO;
 
 	/* Make sure the card is configured.
 	 * Wireless Extensions may postpone config changes until the card
 	 * is open (to pipeline changes and speed-up card setup). If
 	 * those changes are not yet commited, do it now - Jean II */
-	if (test_bit (FLAG_COMMIT, &info->flags)) {
-		disable_MAC(info, 1);
-		writeConfigRid(info, 1);
+	if (test_bit(FLAG_COMMIT, &ai->flags)) {
+		disable_MAC(ai, 1);
+		writeConfigRid(ai, 1);
 	}
 
-	if (info->wifidev != dev) {
+	if (ai->wifidev != dev) {
+		clear_bit(JOB_DIE, &ai->jobs);
+		ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
+		if (IS_ERR(ai->airo_thread_task))
+			return (int)PTR_ERR(ai->airo_thread_task);
+
+		rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED,
+			dev->name, dev);
+		if (rc) {
+			airo_print_err(dev->name,
+				"register interrupt %d failed, rc %d",
+				dev->irq, rc);
+			set_bit(JOB_DIE, &ai->jobs);
+			kthread_stop(ai->airo_thread_task);
+			return rc;
+		}
+
 		/* Power on the MAC controller (which may have been disabled) */
-		clear_bit(FLAG_RADIO_DOWN, &info->flags);
-		enable_interrupts(info);
+		clear_bit(FLAG_RADIO_DOWN, &ai->flags);
+		enable_interrupts(ai);
+
+		try_auto_wep(ai);
 	}
-	enable_MAC(info, &rsp, 1);
+	enable_MAC(ai, 1);
 
 	netif_start_queue(dev);
 	return 0;
@@ -2338,14 +2366,13 @@
 {
 	struct airo_info *ai = dev->priv;
 	struct sockaddr *addr = p;
-	Resp rsp;
 
 	readConfigRid(ai, 1);
 	memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);
 	set_bit (FLAG_COMMIT, &ai->flags);
 	disable_MAC(ai, 1);
 	writeConfigRid (ai, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 	memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
 	if (ai->wifidev)
 		memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
@@ -2392,6 +2419,11 @@
 		disable_MAC(ai, 1);
 #endif
 		disable_interrupts( ai );
+
+		free_irq(dev->irq, dev);
+
+		set_bit(JOB_DIE, &ai->jobs);
+		kthread_stop(ai->airo_thread_task);
 	}
 	return 0;
 }
@@ -2403,7 +2435,6 @@
 	set_bit(FLAG_RADIO_DOWN, &ai->flags);
 	disable_MAC(ai, 1);
 	disable_interrupts(ai);
-	free_irq( dev->irq, dev );
 	takedown_proc_entry( dev, ai );
 	if (test_bit(FLAG_REGISTERED, &ai->flags)) {
 		unregister_netdev( dev );
@@ -2414,9 +2445,6 @@
 		}
 		clear_bit(FLAG_REGISTERED, &ai->flags);
 	}
-	set_bit(JOB_DIE, &ai->jobs);
-	kthread_stop(ai->airo_thread_task);
-
 	/*
 	 * Clean out tx queue
 	 */
@@ -2554,8 +2582,7 @@
  * 2) Map PCI memory for issueing commands.
  * 3) Allocate memory (shared) to send and receive ethernet frames.
  */
-static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
-		    const char *name)
+static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
 {
 	unsigned long mem_start, mem_len, aux_start, aux_len;
 	int rc = -1;
@@ -2569,35 +2596,35 @@
 	aux_start = pci_resource_start(pci, 2);
 	aux_len = AUXMEMSIZE;
 
-	if (!request_mem_region(mem_start, mem_len, name)) {
-		airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
-		       (int)mem_start, (int)mem_len, name);
+	if (!request_mem_region(mem_start, mem_len, DRV_NAME)) {
+		airo_print_err("", "Couldn't get region %x[%x]",
+			(int)mem_start, (int)mem_len);
 		goto out;
 	}
-	if (!request_mem_region(aux_start, aux_len, name)) {
-		airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
-		       (int)aux_start, (int)aux_len, name);
+	if (!request_mem_region(aux_start, aux_len, DRV_NAME)) {
+		airo_print_err("", "Couldn't get region %x[%x]",
+			(int)aux_start, (int)aux_len);
 		goto free_region1;
 	}
 
 	ai->pcimem = ioremap(mem_start, mem_len);
 	if (!ai->pcimem) {
-		airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
-		       (int)mem_start, (int)mem_len, name);
+		airo_print_err("", "Couldn't map region %x[%x]",
+			(int)mem_start, (int)mem_len);
 		goto free_region2;
 	}
 	ai->pciaux = ioremap(aux_start, aux_len);
 	if (!ai->pciaux) {
-		airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
-		       (int)aux_start, (int)aux_len, name);
+		airo_print_err("", "Couldn't map region %x[%x]",
+			(int)aux_start, (int)aux_len);
 		goto free_memmap;
 	}
 
 	/* Reserve PKTSIZE for each fid and 2K for the Rids */
 	ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
 	if (!ai->shared) {
-		airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d",
-		       PCI_SHARED_LEN);
+		airo_print_err("", "Couldn't alloc_consistent %d",
+			PCI_SHARED_LEN);
 		goto free_auxmap;
 	}
 
@@ -2742,7 +2769,7 @@
 	    kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
 		    GFP_KERNEL);
 	if (!ai->networks) {
-		airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
+		airo_print_warn("", "Out of memory allocating beacons");
 		return -ENOMEM;
 	}
 
@@ -2770,7 +2797,6 @@
 {
 	int status;
 	CapabilityRid cap_rid;
-	const char *name = ai->dev->name;
 
 	status = readCapabilityRid(ai, &cap_rid, 1);
 	if (status != SUCCESS) return 0;
@@ -2778,12 +2804,12 @@
 	/* Only firmware versions 5.30.17 or better can do WPA */
 	if ((cap_rid.softVer > 0x530)
 	  || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
-		airo_print_info(name, "WPA is supported.");
+		airo_print_info("", "WPA is supported.");
 		return 1;
 	}
 
 	/* No WPA support */
-	airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17"
+	airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
 		" and greater support WPA.  Detected %s)", cap_rid.prodVer);
 	return 0;
 }
@@ -2797,23 +2823,19 @@
 	int i, rc;
 
 	/* Create the network device object. */
-        dev = alloc_etherdev(sizeof(*ai));
-        if (!dev) {
+	dev = alloc_netdev(sizeof(*ai), "", ether_setup);
+	if (!dev) {
 		airo_print_err("", "Couldn't alloc_etherdev");
 		return NULL;
-        }
-	if (dev_alloc_name(dev, dev->name) < 0) {
-		airo_print_err("", "Couldn't get name!");
-		goto err_out_free;
 	}
 
 	ai = dev->priv;
 	ai->wifidev = NULL;
-	ai->flags = 0;
+	ai->flags = 1 << FLAG_RADIO_DOWN;
 	ai->jobs = 0;
 	ai->dev = dev;
 	if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
-		airo_print_dbg(dev->name, "Found an MPI350 card");
+		airo_print_dbg("", "Found an MPI350 card");
 		set_bit(FLAG_MPI, &ai->flags);
 	}
 	spin_lock_init(&ai->aux_lock);
@@ -2821,14 +2843,11 @@
 	ai->config.len = 0;
 	ai->pci = pci;
 	init_waitqueue_head (&ai->thr_wait);
-	ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
-	if (IS_ERR(ai->airo_thread_task))
-		goto err_out_free;
 	ai->tfm = NULL;
 	add_airo_dev(ai);
 
 	if (airo_networks_allocate (ai))
-		goto err_out_thr;
+		goto err_out_free;
 	airo_networks_initialize (ai);
 
 	/* The Airo-specific entries in the device structure. */
@@ -2851,27 +2870,22 @@
 	dev->base_addr = port;
 
 	SET_NETDEV_DEV(dev, dmdev);
+	SET_MODULE_OWNER(dev);
 
 	reset_card (dev, 1);
 	msleep(400);
 
-	rc = request_irq( dev->irq, airo_interrupt, IRQF_SHARED, dev->name, dev );
-	if (rc) {
-		airo_print_err(dev->name, "register interrupt %d failed, rc %d",
-				irq, rc);
-		goto err_out_nets;
-	}
 	if (!is_pcmcia) {
-		if (!request_region( dev->base_addr, 64, dev->name )) {
+		if (!request_region(dev->base_addr, 64, DRV_NAME)) {
 			rc = -EBUSY;
 			airo_print_err(dev->name, "Couldn't request region");
-			goto err_out_irq;
+			goto err_out_nets;
 		}
 	}
 
 	if (test_bit(FLAG_MPI,&ai->flags)) {
-		if (mpi_map_card(ai, pci, dev->name)) {
-			airo_print_err(dev->name, "Could not map memory");
+		if (mpi_map_card(ai, pci)) {
+			airo_print_err("", "Could not map memory");
 			goto err_out_res;
 		}
 	}
@@ -2899,6 +2913,7 @@
 		ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
 	}
 
+	strcpy(dev->name, "eth%d");
 	rc = register_netdev(dev);
 	if (rc) {
 		airo_print_err(dev->name, "Couldn't register_netdev");
@@ -2921,8 +2936,6 @@
 	if (setup_proc_entry(dev, dev->priv) < 0)
 		goto err_out_wifi;
 
-	netif_start_queue(dev);
-	SET_MODULE_OWNER(dev);
 	return dev;
 
 err_out_wifi:
@@ -2940,14 +2953,9 @@
 err_out_res:
 	if (!is_pcmcia)
 	        release_region( dev->base_addr, 64 );
-err_out_irq:
-	free_irq(dev->irq, dev);
 err_out_nets:
 	airo_networks_free(ai);
-err_out_thr:
 	del_airo_dev(ai);
-	set_bit(JOB_DIE, &ai->jobs);
-	kthread_stop(ai->airo_thread_task);
 err_out_free:
 	free_netdev(dev);
 	return NULL;
@@ -3078,7 +3086,8 @@
 	struct net_device *dev = data;
 	struct airo_info *ai = dev->priv;
 	int locked;
-	
+
+	set_freezable();
 	while(1) {
 		/* make swsusp happy with our thread */
 		try_to_freeze();
@@ -3529,9 +3538,11 @@
 	return rc;
 }
 
-static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
+static int enable_MAC(struct airo_info *ai, int lock)
+{
 	int rc;
-        Cmd cmd;
+	Cmd cmd;
+	Resp rsp;
 
 	/* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions
 	 * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"
@@ -3547,7 +3558,7 @@
 	if (!test_bit(FLAG_ENABLED, &ai->flags)) {
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.cmd = MAC_ENABLE;
-		rc = issuecommand(ai, &cmd, rsp);
+		rc = issuecommand(ai, &cmd, &rsp);
 		if (rc == SUCCESS)
 			set_bit(FLAG_ENABLED, &ai->flags);
 	} else
@@ -3557,8 +3568,12 @@
 	    up(&ai->sem);
 
 	if (rc)
-		airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d",
-			__FUNCTION__, rc);
+		airo_print_err(ai->dev->name, "Cannot enable MAC");
+	else if ((rsp.status & 0xFF00) != 0) {
+		airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, "
+			"rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2);
+		rc = ERROR;
+	}
 	return rc;
 }
 
@@ -3902,12 +3917,9 @@
 		if ( status != SUCCESS ) return ERROR;
 	}
 
-	status = enable_MAC(ai, &rsp, lock);
-	if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
-		airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x,"
-			" offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
+	status = enable_MAC(ai, lock);
+	if (status != SUCCESS)
 		return ERROR;
-	}
 
 	/* Grab the initial wep key, we gotta save it for auto_wep */
 	rc = readWepKeyRid(ai, &wkr, 1, lock);
@@ -3919,10 +3931,7 @@
 		rc = readWepKeyRid(ai, &wkr, 0, lock);
 	} while(lastindex != wkr.kindex);
 
-	if (auto_wep) {
-		ai->expires = RUN_AT(3*HZ);
-		wake_up_interruptible(&ai->thr_wait);
-	}
+	try_auto_wep(ai);
 
 	return SUCCESS;
 }
@@ -4004,7 +4013,7 @@
 		}
 		if ( !(max_tries--) ) {
 			airo_print_err(ai->dev->name,
-				"airo: BAP setup error too many retries\n");
+				"BAP setup error too many retries\n");
 			return ERROR;
 		}
 		// -- PC4500 missed it, try again
@@ -5152,7 +5161,6 @@
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = dev->priv;
 	SsidRid SSID_rid;
-	Resp rsp;
 	int i;
 	int offset = 0;
 
@@ -5177,7 +5185,7 @@
 		SSID_rid.len = sizeof(SSID_rid);
 	disable_MAC(ai, 1);
 	writeSsidRid(ai, &SSID_rid, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 }
 
 static inline u8 hexVal(char c) {
@@ -5193,7 +5201,6 @@
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = dev->priv;
 	APListRid APList_rid;
-	Resp rsp;
 	int i;
 
 	if ( !data->writelen ) return;
@@ -5218,18 +5225,17 @@
 	}
 	disable_MAC(ai, 1);
 	writeAPListRid(ai, &APList_rid, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 }
 
 /* This function wraps PC4500_writerid with a MAC disable */
 static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
 			int len, int dummy ) {
 	int rc;
-	Resp rsp;
 
 	disable_MAC(ai, 1);
 	rc = PC4500_writerid(ai, rid, rid_data, len, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 	return rc;
 }
 
@@ -5260,7 +5266,6 @@
 		       const char *key, u16 keylen, int perm, int lock ) {
 	static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
 	WepKeyRid wkr;
-	Resp rsp;
 
 	memset(&wkr, 0, sizeof(wkr));
 	if (keylen == 0) {
@@ -5280,7 +5285,7 @@
 
 	if (perm) disable_MAC(ai, lock);
 	writeWepKeyRid(ai, &wkr, perm, lock);
-	if (perm) enable_MAC(ai, &rsp, lock);
+	if (perm) enable_MAC(ai, lock);
 	return 0;
 }
 
@@ -5548,7 +5553,6 @@
    changed. */
 static void timer_func( struct net_device *dev ) {
 	struct airo_info *apriv = dev->priv;
-	Resp rsp;
 
 /* We don't have a link so try changing the authtype */
 	readConfigRid(apriv, 0);
@@ -5575,7 +5579,7 @@
 	}
 	set_bit (FLAG_COMMIT, &apriv->flags);
 	writeConfigRid(apriv, 0);
-	enable_MAC(apriv, &rsp, 0);
+	enable_MAC(apriv, 0);
 	up(&apriv->sem);
 
 /* Schedule check to see if the change worked */
@@ -5597,8 +5601,10 @@
 			dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
 	else
 			dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
-	if (!dev)
+	if (!dev) {
+		pci_disable_device(pdev);
 		return -ENODEV;
+	}
 
 	pci_set_drvdata(pdev, dev);
 	return 0;
@@ -5610,6 +5616,8 @@
 
 	airo_print_info(dev->name, "Unregistering...");
 	stop_airo_card(dev, 1);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
 }
 
 static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -5646,7 +5654,6 @@
 {
 	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, PCI_D0);
@@ -5679,7 +5686,7 @@
 		ai->APList = NULL;
 	}
 	writeConfigRid(ai, 0);
-	enable_MAC(ai, &rsp, 0);
+	enable_MAC(ai, 0);
 	ai->power = PMSG_ON;
 	netif_device_attach(dev);
 	netif_wake_queue(dev);
@@ -5903,7 +5910,6 @@
 			  char *extra)
 {
 	struct airo_info *local = dev->priv;
-	Resp rsp;
 	SsidRid SSID_rid;		/* SSIDs */
 
 	/* Reload the list of current SSID */
@@ -5935,7 +5941,7 @@
 	/* Write it to the card */
 	disable_MAC(local, 1);
 	writeSsidRid(local, &SSID_rid, 1);
-	enable_MAC(local, &rsp, 1);
+	enable_MAC(local, 1);
 
 	return 0;
 }
@@ -6000,7 +6006,7 @@
 		memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
 		disable_MAC(local, 1);
 		writeAPListRid(local, &APList_rid, 1);
-		enable_MAC(local, &rsp, 1);
+		enable_MAC(local, 1);
 	}
 	return 0;
 }
@@ -7454,7 +7460,6 @@
 			      char *extra)			/* NULL */
 {
 	struct airo_info *local = dev->priv;
-	Resp rsp;
 
 	if (!test_bit (FLAG_COMMIT, &local->flags))
 		return 0;
@@ -7479,7 +7484,7 @@
 	if (down_interruptible(&local->sem))
 		return -ERESTARTSYS;
 	writeConfigRid(local, 0);
-	enable_MAC(local, &rsp, 0);
+	enable_MAC(local, 0);
 	if (test_bit (FLAG_RESET, &local->flags))
 		airo_set_promisc(local);
 	else
@@ -7746,7 +7751,6 @@
 	unsigned char *iobuf;
 	int len;
 	struct airo_info *ai = dev->priv;
-	Resp rsp;
 
 	if (test_bit(FLAG_FLASHING, &ai->flags))
 		return -EIO;
@@ -7758,7 +7762,7 @@
 		if (test_bit(FLAG_COMMIT, &ai->flags)) {
 			disable_MAC (ai, 1);
 			writeConfigRid (ai, 1);
-			enable_MAC (ai, &rsp, 1);
+			enable_MAC(ai, 1);
 		}
 		break;
 	case AIROGSLIST:    ridcode = RID_SSID;         break;
@@ -7815,7 +7819,6 @@
 	struct airo_info *ai = dev->priv;
 	int  ridcode;
         int  enabled;
-	Resp      rsp;
 	static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
 	unsigned char *iobuf;
 
@@ -7849,7 +7852,7 @@
 		 * same with MAC off
 		 */
 	case AIROPMACON:
-		if (enable_MAC(ai, &rsp, 1) != 0)
+		if (enable_MAC(ai, 1) != 0)
 			return -EIO;
 		return 0;
 
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index d51daf8..072ede7 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -1768,7 +1768,8 @@
 
 		if (priv->stop_rf_kill) {
 			priv->stop_rf_kill = 0;
-			queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+			queue_delayed_work(priv->workqueue, &priv->rf_kill,
+					   round_jiffies(HZ));
 		}
 
 		deferred = 1;
@@ -2098,7 +2099,7 @@
 	/* Make sure the RF Kill check timer is running */
 	priv->stop_rf_kill = 0;
 	cancel_delayed_work(&priv->rf_kill);
-	queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+	queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ));
 }
 
 static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
@@ -4233,7 +4234,8 @@
 			/* Make sure the RF_KILL check timer is running */
 			priv->stop_rf_kill = 0;
 			cancel_delayed_work(&priv->rf_kill);
-			queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+			queue_delayed_work(priv->workqueue, &priv->rf_kill,
+					   round_jiffies(HZ));
 		} else
 			schedule_reset(priv);
 	}
@@ -5969,7 +5971,8 @@
 	if (rf_kill_active(priv)) {
 		IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
 		if (!priv->stop_rf_kill)
-			queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+			queue_delayed_work(priv->workqueue, &priv->rf_kill,
+					   round_jiffies(HZ));
 		goto exit_unlock;
 	}
 
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 7cb2052..aa32a97 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1751,7 +1751,7 @@
 			/* Make sure the RF_KILL check timer is running */
 			cancel_delayed_work(&priv->rf_kill);
 			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   2 * HZ);
+					   round_jiffies(2 * HZ));
 		} else
 			queue_work(priv->workqueue, &priv->up);
 	}
@@ -4690,7 +4690,8 @@
 			else if (priv->config & CFG_BACKGROUND_SCAN
 				 && priv->status & STATUS_ASSOCIATED)
 				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, HZ);
+						   &priv->request_scan,
+						   round_jiffies(HZ));
 
 			/* Send an empty event to user space.
 			 * We don't send the received data on the event because
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 13f6528..4a8f5dc 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -240,7 +240,7 @@
 		if (*enable)
 			penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
 		else
-			penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
+			penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
 	}
 
 	lbs_deb_leave(LBS_DEB_CMD);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 4a59306..9f36624 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -613,6 +613,7 @@
 
 	init_waitqueue_entry(&wait, current);
 
+	set_freezable();
 	for (;;) {
 		lbs_deb_thread( "main-thread 111: intcounter=%d "
 		       "currenttxskb=%p dnld_sent=%d\n",
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 88d9d2d..769c86f 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -439,7 +439,6 @@
 	ret = 0;
 
 done:
-	skb->protocol = __constant_htons(0x0019);	/* ETH_P_80211_RAW */
 	lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
 	return ret;
 }
diff --git a/drivers/net/wireless/libertas/version.h b/drivers/net/wireless/libertas/version.h
deleted file mode 100644
index 8b13789..0000000
--- a/drivers/net/wireless/libertas/version.h
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index f42b796..2fcc3bf 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1719,9 +1719,6 @@
 			pkey->type = KEY_TYPE_ID_TKIP;
 		} else if (alg == IW_ENCODE_ALG_CCMP) {
 			pkey->type = KEY_TYPE_ID_AES;
-		} else {
-			ret = -EINVAL;
-			goto out;
 		}
 
 		/* If WPA isn't enabled yet, do that now */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 283be4a..585f599 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -1853,7 +1853,6 @@
 	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	struct mac_entry *entry;
-	struct list_head *ptr;
 	struct sockaddr *addr = (struct sockaddr *) extra;
 
 	if (addr->sa_family != ARPHRD_ETHER)
@@ -1861,11 +1860,9 @@
 
 	if (down_interruptible(&acl->sem))
 		return -ERESTARTSYS;
-	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, _list);
-
+	list_for_each_entry(entry, &acl->mac_list, _list) {
 		if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
-			list_del(ptr);
+			list_del(&entry->_list);
 			acl->size--;
 			kfree(entry);
 			up(&acl->sem);
@@ -1883,7 +1880,6 @@
 	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	struct mac_entry *entry;
-	struct list_head *ptr;
 	struct sockaddr *dst = (struct sockaddr *) extra;
 
 	dwrq->length = 0;
@@ -1891,9 +1887,7 @@
 	if (down_interruptible(&acl->sem))
 		return -ERESTARTSYS;
 
-	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, _list);
-
+	list_for_each_entry(entry, &acl->mac_list, _list) {
 		memcpy(dst->sa_data, entry->addr, ETH_ALEN);
 		dst->sa_family = ARPHRD_ETHER;
 		dwrq->length++;
@@ -1960,7 +1954,6 @@
 static int
 prism54_mac_accept(struct islpci_acl *acl, char *mac)
 {
-	struct list_head *ptr;
 	struct mac_entry *entry;
 	int res = 0;
 
@@ -1972,8 +1965,7 @@
 		return 1;
 	}
 
-	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, _list);
+	list_for_each_entry(entry, &acl->mac_list, _list) {
 		if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
 			res = 1;
 			break;
@@ -2216,11 +2208,9 @@
 void
 prism54_wpa_bss_ie_clean(islpci_private *priv)
 {
-	struct list_head *ptr, *n;
+	struct islpci_bss_wpa_ie *bss, *n;
 
-	list_for_each_safe(ptr, n, &priv->bss_wpa_list) {
-		struct islpci_bss_wpa_ie *bss;
-		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+	list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) {
 		kfree(bss);
 	}
 }
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
index e25a09f..efc4120 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -67,7 +67,7 @@
 	msleep(2);
 }
 
-static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
 {
 	struct rtl8187_priv *priv = dev->priv;
 	u16 reg80, reg82, reg84;
@@ -106,7 +106,7 @@
 	struct rtl8187_priv *priv = dev->priv;
 
 	if (priv->asic_rev)
-		rtl8225_write_8051(dev, addr, data);
+		rtl8225_write_8051(dev, addr, cpu_to_le16(data));
 	else
 		rtl8225_write_bitbang(dev, addr, data);
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 5b624bf..c39f198 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -49,8 +49,9 @@
 	ZD_MEMCLEAR(chip, sizeof(*chip));
 }
 
-static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size)
+static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
 {
+	u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr;
 	return scnprintf(buffer, size, "%02x-%02x-%02x",
 		         addr[0], addr[1], addr[2]);
 }
@@ -61,10 +62,10 @@
 	int i = 0;
 
 	i = scnprintf(buffer, size, "zd1211%s chip ",
-		      chip->is_zd1211b ? "b" : "");
+		      zd_chip_is_zd1211b(chip) ? "b" : "");
 	i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " ");
-	i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
+	i += scnprint_mac_oui(chip, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " ");
 	i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
@@ -366,64 +367,9 @@
 	return r;
 }
 
-static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr,
-	                  const zd_addr_t *addr)
-{
-	int r;
-	u32 parts[2];
-
-	r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2);
-	if (r) {
-		dev_dbg_f(zd_chip_dev(chip),
-			"error: couldn't read e2p macs. Error number %d\n", r);
-		return r;
-	}
-
-	mac_addr[0] = parts[0];
-	mac_addr[1] = parts[0] >>  8;
-	mac_addr[2] = parts[0] >> 16;
-	mac_addr[3] = parts[0] >> 24;
-	mac_addr[4] = parts[1];
-	mac_addr[5] = parts[1] >>  8;
-
-	return 0;
-}
-
-static int read_e2p_mac_addr(struct zd_chip *chip)
-{
-	static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 };
-
-	ZD_ASSERT(mutex_is_locked(&chip->mutex));
-	return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr);
-}
-
 /* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and
  *              CR_MAC_ADDR_P2 must be overwritten
  */
-void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
-	mutex_lock(&chip->mutex);
-	memcpy(mac_addr, chip->e2p_mac, ETH_ALEN);
-	mutex_unlock(&chip->mutex);
-}
-
-static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
-	static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 };
-	return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr);
-}
-
-int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
-	int r;
-
-	dev_dbg_f(zd_chip_dev(chip), "\n");
-	mutex_lock(&chip->mutex);
-	r = read_mac_addr(chip, mac_addr);
-	mutex_unlock(&chip->mutex);
-	return r;
-}
-
 int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
 {
 	int r;
@@ -444,12 +390,6 @@
 
 	mutex_lock(&chip->mutex);
 	r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
-#ifdef DEBUG
-	{
-		u8 tmp[ETH_ALEN];
-		read_mac_addr(chip, tmp);
-	}
-#endif /* DEBUG */
 	mutex_unlock(&chip->mutex);
 	return r;
 }
@@ -809,7 +749,7 @@
 
 static int hw_reset_phy(struct zd_chip *chip)
 {
-	return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) :
+	return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) :
 		                  zd1211_hw_reset_phy(chip);
 }
 
@@ -874,7 +814,7 @@
 	if (r)
 		return r;
 
-	return chip->is_zd1211b ?
+	return zd_chip_is_zd1211b(chip) ?
 		zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
 }
 
@@ -1136,8 +1076,15 @@
 	return 0;
 }
 
+/* Read mac address using pre-firmware interface */
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr)
+{
+	dev_dbg_f(zd_chip_dev(chip), "\n");
+	return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr,
+		ETH_ALEN);
+}
 
-int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
+int zd_chip_init_hw(struct zd_chip *chip)
 {
 	int r;
 	u8 rf_type;
@@ -1145,7 +1092,6 @@
 	dev_dbg_f(zd_chip_dev(chip), "\n");
 
 	mutex_lock(&chip->mutex);
-	chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0;
 
 #ifdef DEBUG
 	r = test_init(chip);
@@ -1201,10 +1147,6 @@
 		goto out;
 #endif /* DEBUG */
 
-	r = read_e2p_mac_addr(chip);
-	if (r)
-		goto out;
-
 	r = read_cal_int_tables(chip);
 	if (r)
 		goto out;
@@ -1259,7 +1201,7 @@
 	r = update_pwr_int(chip, channel);
 	if (r)
 		return r;
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		static const struct zd_ioreq16 ioreqs[] = {
 			{ CR69, 0x28 },
 			{},
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 79d0288..f469857 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -704,7 +704,6 @@
 	struct mutex mutex;
 	/* Base address of FW_REG_ registers */
 	zd_addr_t fw_regs_base;
-	u8 e2p_mac[ETH_ALEN];
 	/* EepSetPoint in the vendor driver */
 	u8 pwr_cal_values[E2P_CHANNEL_COUNT];
 	/* integration values in the vendor driver */
@@ -715,7 +714,7 @@
 	unsigned int pa_type:4,
 		patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
 		new_phy_layout:1, al2230s_bit:1,
-		is_zd1211b:1, supports_tx_led:1;
+		supports_tx_led:1;
 };
 
 static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -734,9 +733,15 @@
 	         struct net_device *netdev,
 	         struct usb_interface *intf);
 void zd_chip_clear(struct zd_chip *chip);
-int zd_chip_init_hw(struct zd_chip *chip, u8 device_type);
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
+int zd_chip_init_hw(struct zd_chip *chip);
 int zd_chip_reset(struct zd_chip *chip);
 
+static inline int zd_chip_is_zd1211b(struct zd_chip *chip)
+{
+	return chip->usb.is_zd1211b;
+}
+
 static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
 	                              const zd_addr_t *addresses,
 				      unsigned int count)
@@ -825,8 +830,6 @@
 }
 u8  zd_chip_get_channel(struct zd_chip *chip);
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
-void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr);
-int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr);
 int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
 int zd_chip_switch_radio_on(struct zd_chip *chip);
 int zd_chip_switch_radio_off(struct zd_chip *chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 6753d24..f6c487a 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -86,38 +86,46 @@
 	return r;
 }
 
-int zd_mac_init_hw(struct zd_mac *mac, u8 device_type)
+int zd_mac_preinit_hw(struct zd_mac *mac)
+{
+	int r;
+	u8 addr[ETH_ALEN];
+
+	r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
+	if (r)
+		return r;
+
+	memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
+	return 0;
+}
+
+int zd_mac_init_hw(struct zd_mac *mac)
 {
 	int r;
 	struct zd_chip *chip = &mac->chip;
-	u8 addr[ETH_ALEN];
 	u8 default_regdomain;
 
 	r = zd_chip_enable_int(chip);
 	if (r)
 		goto out;
-	r = zd_chip_init_hw(chip, device_type);
+	r = zd_chip_init_hw(chip);
 	if (r)
 		goto disable_int;
 
-	zd_get_e2p_mac_addr(chip, addr);
-	r = zd_write_mac_addr(chip, addr);
-	if (r)
-		goto disable_int;
 	ZD_ASSERT(!irqs_disabled());
-	spin_lock_irq(&mac->lock);
-	memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
-	spin_unlock_irq(&mac->lock);
 
 	r = zd_read_regdomain(chip, &default_regdomain);
 	if (r)
 		goto disable_int;
 	if (!zd_regdomain_supported(default_regdomain)) {
-		dev_dbg_f(zd_mac_dev(mac),
-			  "Regulatory Domain %#04x is not supported.\n",
-		          default_regdomain);
-		r = -EINVAL;
-		goto disable_int;
+		/* The vendor driver overrides the regulatory domain and
+		 * allowed channel registers and unconditionally restricts
+		 * available channels to 1-11 everywhere. Match their
+		 * questionable behaviour only for regdomains which we don't
+		 * recognise. */
+		dev_warn(zd_mac_dev(mac),  "Unrecognised regulatory domain: "
+			"%#04x. Defaulting to FCC.\n", default_regdomain);
+		default_regdomain = ZD_REGDOMAIN_FCC;
 	}
 	spin_lock_irq(&mac->lock);
 	mac->regdomain = mac->default_regdomain = default_regdomain;
@@ -164,14 +172,25 @@
 {
 	struct zd_mac *mac = zd_netdev_mac(netdev);
 	struct zd_chip *chip = &mac->chip;
+	struct zd_usb *usb = &chip->usb;
 	int r;
 
+	if (!usb->initialized) {
+		r = zd_usb_init_hw(usb);
+		if (r)
+			goto out;
+	}
+
 	tasklet_enable(&mac->rx_tasklet);
 
 	r = zd_chip_enable_int(chip);
 	if (r < 0)
 		goto out;
 
+	r = zd_write_mac_addr(chip, netdev->dev_addr);
+	if (r)
+		goto disable_int;
+
 	r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
 	if (r < 0)
 		goto disable_int;
@@ -251,9 +270,11 @@
 	dev_dbg_f(zd_mac_dev(mac),
 		  "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data));
 
-	r = zd_write_mac_addr(chip, addr->sa_data);
-	if (r)
-		return r;
+	if (netdev->flags & IFF_UP) {
+		r = zd_write_mac_addr(chip, addr->sa_data);
+		if (r)
+			return r;
+	}
 
 	spin_lock_irqsave(&mac->lock, flags);
 	memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -855,7 +876,7 @@
 	/* ZD1211B: Computing the length difference this way, gives us
 	 * flexibility to compute the packet length.
 	 */
-	cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ?
+	cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
 			packet_length - frag_len : packet_length);
 
 	/*
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index faf4c78..9f9344e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -189,7 +189,8 @@
 		struct usb_interface *intf);
 void zd_mac_clear(struct zd_mac *mac);
 
-int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
+int zd_mac_preinit_hw(struct zd_mac *mac);
+int zd_mac_init_hw(struct zd_mac *mac);
 
 int zd_mac_open(struct net_device *netdev);
 int zd_mac_stop(struct net_device *netdev);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 7407409..abe5d38 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -34,7 +34,7 @@
 	[AL2210_RF]	= "AL2210_RF",
 	[MAXIM_NEW_RF]	= "MAXIM_NEW_RF",
 	[UW2453_RF]	= "UW2453_RF",
-	[UNKNOWN_A_RF]	= "UNKNOWN_A_RF",
+	[AL2230S_RF]	= "AL2230S_RF",
 	[RALINK_RF]	= "RALINK_RF",
 	[INTERSIL_RF]	= "INTERSIL_RF",
 	[RF2959_RF]	= "RF2959_RF",
@@ -77,6 +77,7 @@
 		r = zd_rf_init_rf2959(rf);
 		break;
 	case AL2230_RF:
+	case AL2230S_RF:
 		r = zd_rf_init_al2230(rf);
 		break;
 	case AL7230B_RF:
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index c6dfd82..30502f2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -26,7 +26,7 @@
 #define AL2210_RF			0x7
 #define MAXIM_NEW_RF			0x8
 #define UW2453_RF			0x9
-#define UNKNOWN_A_RF			0xa
+#define AL2230S_RF			0xa
 #define RALINK_RF			0xb
 #define INTERSIL_RF			0xc
 #define RF2959_RF			0xd
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index e7a4ecf..006774d 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -21,6 +21,8 @@
 #include "zd_usb.h"
 #include "zd_chip.h"
 
+#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF)
+
 static const u32 zd1211_al2230_table[][3] = {
 	RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
 	RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
@@ -176,7 +178,7 @@
 	if (r)
 		return r;
 
-	if (chip->al2230s_bit) {
+	if (IS_AL2230S(chip)) {
 		r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
 			ARRAY_SIZE(ioreqs_init_al2230s));
 		if (r)
@@ -188,7 +190,7 @@
 		return r;
 
 	/* improve band edge for AL2230S */
-	if (chip->al2230s_bit)
+	if (IS_AL2230S(chip))
 		r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
 	else
 		r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
@@ -314,7 +316,7 @@
 	if (r)
 		return r;
 
-	if (chip->al2230s_bit) {
+	if (IS_AL2230S(chip)) {
 		r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
 			ARRAY_SIZE(ioreqs_init_al2230s));
 		if (r)
@@ -328,7 +330,7 @@
 	if (r)
 		return r;
 
-	if (chip->al2230s_bit)
+	if (IS_AL2230S(chip))
 		r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
 	else
 		r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
@@ -422,7 +424,7 @@
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
 	rf->switch_radio_off = al2230_switch_radio_off;
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		rf->init_hw = zd1211b_al2230_init_hw;
 		rf->set_channel = zd1211b_al2230_set_channel;
 		rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index f4e8b6a..73d0bb2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -473,7 +473,7 @@
 {
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		rf->init_hw = zd1211b_al7230b_init_hw;
 		rf->switch_radio_on = zd1211b_al7230b_switch_radio_on;
 		rf->set_channel = zd1211b_al7230b_set_channel;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
index 2d736bd..cc70d40 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
@@ -265,7 +265,7 @@
 {
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		dev_err(zd_chip_dev(chip),
 		       "RF2959 is currently not supported for ZD1211B"
 		       " devices\n");
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
index 414e40d..857dcf3 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -486,7 +486,7 @@
 	if (r)
 		return r;
 
-	if (chip->is_zd1211b)
+	if (zd_chip_is_zd1211b(chip))
 		ioreqs[1].value = 0x7f;
 
 	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index ca24299..28d41a2 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -71,6 +71,7 @@
 	{ USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
 	/* "Driverless" devices that need ejecting */
 	{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
 	{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
@@ -195,26 +196,27 @@
 	return le16_to_cpu(p[offset]);
 }
 
-static char *get_fw_name(char *buffer, size_t size, u8 device_type,
+static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size,
 	               const char* postfix)
 {
 	scnprintf(buffer, size, "%s%s",
-		device_type == DEVICE_ZD1211B ?
+		usb->is_zd1211b ?
 			FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
 		postfix);
 	return buffer;
 }
 
-static int handle_version_mismatch(struct usb_device *udev, u8 device_type,
+static int handle_version_mismatch(struct zd_usb *usb,
 	const struct firmware *ub_fw)
 {
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	const struct firmware *ur_fw = NULL;
 	int offset;
 	int r = 0;
 	char fw_name[128];
 
 	r = request_fw_file(&ur_fw,
-		get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"),
+		get_fw_name(usb, fw_name, sizeof(fw_name), "ur"),
 		&udev->dev);
 	if (r)
 		goto error;
@@ -237,11 +239,12 @@
 	return r;
 }
 
-static int upload_firmware(struct usb_device *udev, u8 device_type)
+static int upload_firmware(struct zd_usb *usb)
 {
 	int r;
 	u16 fw_bcdDevice;
 	u16 bcdDevice;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	const struct firmware *ub_fw = NULL;
 	const struct firmware *uph_fw = NULL;
 	char fw_name[128];
@@ -249,7 +252,7 @@
 	bcdDevice = get_bcdDevice(udev);
 
 	r = request_fw_file(&ub_fw,
-		get_fw_name(fw_name, sizeof(fw_name), device_type,  "ub"),
+		get_fw_name(usb, fw_name, sizeof(fw_name), "ub"),
 		&udev->dev);
 	if (r)
 		goto error;
@@ -264,7 +267,7 @@
 			dev_warn(&udev->dev, "device has old bootcode, please "
 				"report success or failure\n");
 
-		r = handle_version_mismatch(udev, device_type, ub_fw);
+		r = handle_version_mismatch(usb, ub_fw);
 		if (r)
 			goto error;
 	} else {
@@ -275,7 +278,7 @@
 
 
 	r = request_fw_file(&uph_fw,
-		get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"),
+		get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"),
 		&udev->dev);
 	if (r)
 		goto error;
@@ -294,6 +297,30 @@
 	return r;
 }
 
+/* Read data from device address space using "firmware interface" which does
+ * not require firmware to be loaded. */
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
+{
+	int r;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
+
+	r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+		USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
+		data, len, 5000);
+	if (r < 0) {
+		dev_err(&udev->dev,
+			"read over firmware interface failed: %d\n", r);
+		return r;
+	} else if (r != len) {
+		dev_err(&udev->dev,
+			"incomplete read over firmware interface: %d/%d\n",
+			r, len);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 #define urb_dev(urb) (&(urb)->dev->dev)
 
 static inline void handle_regs_int(struct urb *urb)
@@ -920,9 +947,42 @@
 	return 0;
 }
 
+int zd_usb_init_hw(struct zd_usb *usb)
+{
+	int r;
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	r = upload_firmware(usb);
+	if (r) {
+		dev_err(zd_usb_dev(usb),
+		       "couldn't load firmware. Error number %d\n", r);
+		return r;
+	}
+
+	r = usb_reset_configuration(zd_usb_to_usbdev(usb));
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb),
+			"couldn't reset configuration. Error number %d\n", r);
+		return r;
+	}
+
+	r = zd_mac_init_hw(mac);
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb),
+		         "couldn't initialize mac. Error number %d\n", r);
+		return r;
+	}
+
+	usb->initialized = 1;
+	return 0;
+}
+
 static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	int r;
+	struct zd_usb *usb;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct net_device *netdev = NULL;
 
@@ -950,26 +1010,10 @@
 		goto error;
 	}
 
-	r = upload_firmware(udev, id->driver_info);
-	if (r) {
-		dev_err(&intf->dev,
-		       "couldn't load firmware. Error number %d\n", r);
-		goto error;
-	}
+	usb = &zd_netdev_mac(netdev)->chip.usb;
+	usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
 
-	r = usb_reset_configuration(udev);
-	if (r) {
-		dev_dbg_f(&intf->dev,
-			"couldn't reset configuration. Error number %d\n", r);
-		goto error;
-	}
-
-	/* At this point the interrupt endpoint is not generally enabled. We
-	 * save the USB bandwidth until the network device is opened. But
-	 * notify that the initialization of the MAC will require the
-	 * interrupts to be temporary enabled.
-	 */
-	r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info);
+	r = zd_mac_preinit_hw(zd_netdev_mac(netdev));
 	if (r) {
 		dev_dbg_f(&intf->dev,
 		         "couldn't initialize mac. Error number %d\n", r);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 506ea6a..961a7a1 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -188,6 +188,7 @@
 	struct zd_usb_rx rx;
 	struct zd_usb_tx tx;
 	struct usb_interface *intf;
+	u8 is_zd1211b:1, initialized:1;
 };
 
 #define zd_usb_dev(usb) (&usb->intf->dev)
@@ -236,6 +237,8 @@
 
 int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
 
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len);
+
 extern struct workqueue_struct *zd_workqueue;
 
 #endif /* _ZD_USB_H */
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index f46c69e..09c93ff 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -5,11 +5,9 @@
 # Parport configuration.
 #
 
-menu "Parallel port support"
-	depends on HAS_IOMEM
-
-config PARPORT
+menuconfig PARPORT
 	tristate "Parallel port support"
+	depends on HAS_IOMEM
 	---help---
 	  If you want to use devices connected to your machine's parallel port
 	  (the connector at the computer with 25 holes), e.g. printer, ZIP
@@ -33,9 +31,11 @@
 
 	  If unsure, say Y.
 
+if PARPORT
+
 config PARPORT_PC
 	tristate "PC-style hardware"
-	depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
+	depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
 	---help---
 	  You should say Y here if you have a PC-style parallel port. All
 	  IBM PC compatible computers and some Alphas have PC-style
@@ -85,7 +85,7 @@
 
 config PARPORT_IP32
 	tristate "SGI IP32 builtin port (EXPERIMENTAL)"
-	depends on SGI_IP32 && PARPORT && EXPERIMENTAL
+	depends on SGI_IP32 && EXPERIMENTAL
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port on
@@ -94,7 +94,7 @@
 
 config PARPORT_AMIGA
 	tristate "Amiga builtin port"
-	depends on AMIGA && PARPORT
+	depends on AMIGA
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port hardware on
@@ -103,7 +103,7 @@
 
 config PARPORT_MFC3
 	tristate "Multiface III parallel port"
-	depends on ZORRO && PARPORT
+	depends on ZORRO
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need parallel port support for the MFC3 card.
@@ -112,7 +112,7 @@
 
 config PARPORT_ATARI
 	tristate "Atari hardware"
-	depends on ATARI && PARPORT
+	depends on ATARI
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port hardware on
@@ -122,12 +122,11 @@
 config PARPORT_GSC
 	tristate
 	default GSC
-	depends on PARPORT
 	select PARPORT_NOT_PC
 
 config PARPORT_SUNBPP
 	tristate "Sparc hardware (EXPERIMENTAL)"
-	depends on SBUS && PARPORT && EXPERIMENTAL
+	depends on SBUS && EXPERIMENTAL
 	select PARPORT_NOT_PC
 	help
 	  This driver provides support for the bidirectional parallel port
@@ -136,7 +135,6 @@
 
 config PARPORT_AX88796
 	tristate "AX88796 Parallel Port"
-	depends on PARPORT
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port hardware on
@@ -148,7 +146,6 @@
 
 config PARPORT_1284
 	bool "IEEE 1284 transfer modes"
-	depends on PARPORT
 	help
 	  If you have a printer that supports status readback or device ID, or
 	  want to use a device that uses enhanced parallel port transfer modes
@@ -159,5 +156,4 @@
 config PARPORT_NOT_PC
 	bool
 
-endmenu
-
+endif # PARPORT
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 7bfbad5..5d58ad5 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2424,7 +2424,6 @@
 	u32 ite8872set;
 	u32 ite8872_lpt, ite8872_lpthi;
 	u8 ite8872_irq, type;
-	char *fake_name = "parport probe";
 	int irq;
 	int i;
 
@@ -2432,11 +2431,11 @@
 	
 	// make sure which one chip
 	for(i = 0; i < 5; i++) {
-		base_res = request_region(inta_addr[i], 0x8, fake_name);
+		base_res = request_region(inta_addr[i], 32, "it887x");
 		if (base_res) {
 			int test;
 			pci_write_config_dword (pdev, 0x60,
-						0xe7000000 | inta_addr[i]);
+						0xe5000000 | inta_addr[i]);
 			pci_write_config_dword (pdev, 0x78,
 						0x00000000 | inta_addr[i]);
 			test = inb (inta_addr[i]);
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index bb3c101..deb6b5e 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -159,8 +159,8 @@
 	/* Claim new bus resources */
 	pcibios_claim_one_bus(dev->bus);
 
-	/* ioremap() for child bus, which may or may not succeed */
-	remap_bus_range(dev->subordinate);
+	/* Map IO space for child bus, which may or may not succeed */
+	pcibios_map_io_space(dev->subordinate);
 
 	/* Add new devices to global lists.  Register in proc, sysfs. */
 	pci_bus_add_devices(phb->bus);
@@ -390,7 +390,7 @@
 	} else
 		pcibios_remove_pci_devices(bus);
 
-	if (unmap_bus_range(bus)) {
+	if (pcibios_unmap_io_space(bus)) {
 		printk(KERN_ERR "%s: failed to unmap bus range\n",
 			__FUNCTION__);
 		return -ERANGE;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 10dbdec..1b7b281 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -20,7 +20,7 @@
 #include <linux/stat.h>
 #include <linux/topology.h>
 #include <linux/mm.h>
-
+#include <linux/capability.h>
 #include "pci.h"
 
 static int sysfs_initialized;	/* = 0 */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a7bce75..34b8dae 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -22,6 +22,18 @@
 
 LIST_HEAD(pci_devices);
 
+/*
+ * Some device drivers need know if pci is initiated.
+ * Basically, we think pci is not initiated when there
+ * is no device in list of pci_devices.
+ */
+int no_pci_devices(void)
+{
+	return list_empty(&pci_devices);
+}
+
+EXPORT_SYMBOL(no_pci_devices);
+
 #ifdef HAVE_PCI_LEGACY
 /**
  * pci_create_legacy_files - create legacy I/O port and memory files
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index cfa0dfe..90adc62 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-
+#include <linux/capability.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include "pci.h"
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 9f7090f..c6e79d0 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -202,7 +202,7 @@
 	 * can cause some machines to crash.  So here we detect and flag that
 	 * situation and bail out early.
 	 */
-	if (unlikely(list_empty(&pci_devices)))
+	if (unlikely(no_pci_devices()))
 		return NULL;
 	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
@@ -277,7 +277,7 @@
 	 * can cause some machines to crash.  So here we detect and flag that
 	 * situation and bail out early.
 	 */
-	if (unlikely(list_empty(&pci_devices)))
+	if (unlikely(no_pci_devices()))
 		return NULL;
 	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 35f8864..c0c77f8 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -180,14 +180,15 @@
 	  PCMCIA cards are plugged into. If unsure, say N.
 
 config PCMCIA_M8XX
-        tristate "MPC8xx PCMCIA support"
-        depends on PCMCIA && PPC && 8xx 
-        select PCCARD_IODYN
-        help
-        Say Y here to include support for PowerPC 8xx series PCMCIA
-        controller.
+	tristate "MPC8xx PCMCIA support"
+	depends on PCMCIA && PPC && 8xx
+	select PCCARD_IODYN
+	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.
+	  This driver is also available as a module called m8xx_pcmcia.
 
 config HD64465_PCMCIA
 	tristate "HD64465 host bridge support"
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 50cad3a..7c93a10 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -651,6 +651,7 @@
 	add_wait_queue(&skt->thread_wait, &wait);
 	complete(&skt->thread_done);
 
+	set_freezable();
 	for (;;) {
 		unsigned long flags;
 		unsigned int events;
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 9721ed7..3c45142 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -10,7 +10,7 @@
  * Further fixes, v2.6 kernel port
  *     <marcelo.tosatti@cyclades.com>
  * 
- * Some fixes, additions (C) 2005 Montavista Software, Inc. 
+ * Some fixes, additions (C) 2005-2007 Montavista Software, Inc.
  *     <vbordug@ru.mvista.com>
  *
  * "The ExCA standard specifies that socket controllers should provide
@@ -40,10 +40,6 @@
 #include <linux/fcntl.h>
 #include <linux/string.h>
 
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/system.h>
-
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -51,11 +47,18 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
 
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/irq.h>
+#include <asm/fs_pd.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -110,7 +113,7 @@
 #define CONFIG_PCMCIA_SLOT_B
 #endif
 
-#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
+#endif				/* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
 
 #if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
 
@@ -143,30 +146,20 @@
 
 /* ------------------------------------------------------------------------- */
 
-#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      */
-
+#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       */
 /* ------------------------------------------------------------------------- */
 
-/* 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 int pcmcia_schlvl;
 
 static DEFINE_SPINLOCK(events_lock);
 
-
 #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
-};
+static u32 *m8xx_pgcrx[2];
 
 /*
  * This structure is used to address each window in the PCMCIA controller.
@@ -176,8 +169,8 @@
  */
 
 struct pcmcia_win {
-	u32	br;
-	u32	or;
+	u32 br;
+	u32 or;
 };
 
 /*
@@ -221,22 +214,27 @@
 
 /* we keep one lookup table per socket to check flags */
 
-#define PCMCIA_EVENTS_MAX 5  /* 4 max at a time + termination */
+#define PCMCIA_EVENTS_MAX 5	/* 4 max at a time + termination */
 
 struct event_table {
 	u32 regbit;
 	u32 eventbit;
 };
 
+static const char driver_name[] = "m8xx-pcmcia";
+
 struct socket_info {
-	void	(*handler)(void *info, u32 events);
-	void	*info;
+	void (*handler) (void *info, u32 events);
+	void *info;
 
 	u32 slot;
+	pcmconf8xx_t *pcmcia;
+	u32 bus_freq;
+	int hwirq;
 
 	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 pccard_io_map io_win[PCMCIA_IO_WIN_NO];
 	struct event_table events[PCMCIA_EVENTS_MAX];
 	struct pcmcia_socket socket;
 };
@@ -250,8 +248,7 @@
 
 #define M8XX_SIZES_NO 32
 
-static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] =
-{
+static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = {
 	0x00000001, 0x00000002, 0x00000008, 0x00000004,
 	0x00000080, 0x00000040, 0x00000010, 0x00000020,
 	0x00008000, 0x00004000, 0x00001000, 0x00002000,
@@ -267,7 +264,7 @@
 
 static irqreturn_t m8xx_interrupt(int irq, void *dev);
 
-#define PCMCIA_BMT_LIMIT (15*4)  /* Bus Monitor Timeout value */
+#define PCMCIA_BMT_LIMIT (15*4)	/* Bus Monitor Timeout value */
 
 /* ------------------------------------------------------------------------- */
 /* board specific stuff:                                                     */
@@ -291,8 +288,9 @@
 {
 	u32 reg = 0;
 
-	switch(vcc) {
-	case 0: break;
+	switch (vcc) {
+	case 0:
+		break;
 	case 33:
 		reg |= BCSR1_PCVCTL4;
 		break;
@@ -303,11 +301,12 @@
 		return 1;
 	}
 
-	switch(vpp) {
-	case 0: break;
+	switch (vpp) {
+	case 0:
+		break;
 	case 33:
 	case 50:
-		if(vcc == vpp)
+		if (vcc == vpp)
 			reg |= BCSR1_PCVCTL6;
 		else
 			return 1;
@@ -318,25 +317,29 @@
 		return 1;
 	}
 
-	if(!((vcc == 50) || (vcc == 0)))
+	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));
+	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);
+	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 */
+#define hardware_enable(_slot_)	/* No hardware to enable */
+#define hardware_disable(_slot_)	/* No hardware to disable */
 
-#endif /* CONFIG_RPXCLASSIC */
+#endif				/* CONFIG_RPXCLASSIC */
 
 /* FADS Boards from Motorola                                               */
 
@@ -348,43 +351,45 @@
 {
 	u32 reg = 0;
 
-	switch(vcc) {
-		case 0:
-			break;
-		case 33:
-			reg |= BCSR1_PCCVCC0;
-			break;
-		case 50:
-			reg |= BCSR1_PCCVCC1;
-			break;
-		default:
-			return 1;
+	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:
+	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));
+	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);
+	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg);
 
 	return 0;
 }
@@ -393,12 +398,12 @@
 
 static void hardware_enable(int slot)
 {
-	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~BCSR1_PCCEN);
+	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);
+	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN);
 }
 
 #endif
@@ -408,78 +413,21 @@
 #if defined(CONFIG_MPC885ADS)
 
 #define PCMCIA_BOARD_MSG "MPC885ADS"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-	u32 reg = 0;
-	unsigned *bcsr_io;
-
-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-	switch(vcc) {
-		case 0:
-			break;
-		case 33:
-			reg |= BCSR1_PCCVCC0;
-			break;
-		case 50:
-			reg |= BCSR1_PCCVCC1;
-			break;
-		default:
-			goto out_unmap;
-	}
-
-	switch(vpp) {
-		case 0:
-			break;
-		case 33:
-		case 50:
-			if(vcc == vpp)
-				reg |= BCSR1_PCCVPP1;
-			else
-				goto out_unmap;
-			break;
-		case 120:
-			if ((vcc == 33) || (vcc == 50))
-				reg |= BCSR1_PCCVPP0;
-			else
-				goto out_unmap;
-		default:
-			goto out_unmap;
-	}
-
-	/* first, turn off all power */
-	out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
-
-	/* enable new powersettings */
-	out_be32(bcsr_io, in_be32(bcsr_io) | reg);
-
-	iounmap(bcsr_io);
-	return 0;
-
-out_unmap:
-	iounmap(bcsr_io);
-	return 1;
-}
-
 #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
 
-static void hardware_enable(int slot)
+static inline void hardware_enable(int slot)
 {
-	unsigned *bcsr_io;
-
-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-	out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN);
-	iounmap(bcsr_io);
+	m8xx_pcmcia_ops.hw_ctrl(slot, 1);
 }
 
-static void hardware_disable(int slot)
+static inline void hardware_disable(int slot)
 {
-	unsigned *bcsr_io;
+	m8xx_pcmcia_ops.hw_ctrl(slot, 0);
+}
 
-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-	out_be32(bcsr_io, in_be32(bcsr_io) |  BCSR1_PCCEN);
-	iounmap(bcsr_io);
+static inline int voltage_set(int slot, int vcc, int vpp)
+{
+	return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
 }
 
 #endif
@@ -495,52 +443,53 @@
 {
 	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 (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:
+	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));
+	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);
+	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 */
+#define hardware_enable(_slot_)	/* No hardware to enable */
+#define hardware_disable(_slot_)	/* No hardware to disable */
 
-#endif /* CONFIG_MBX */
+#endif				/* CONFIG_MBX */
 
 #if defined(CONFIG_PRxK)
 #include <asm/cpld.h>
@@ -554,43 +503,46 @@
 	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 (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:
+	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)))) {
+	if (reg !=
+	    (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
 		/* enable new powersettings */
-		regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
+		regread =
+		    regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >>
+				(slot << 2));
 		out_8(&ccpld->fpga_pc_ctl, reg | regread);
 		msleep(100);
 	}
@@ -599,52 +551,10 @@
 }
 
 #define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
-#define hardware_enable(_slot_)  /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
+#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);
-}
-
-static struct device_driver m8xx_driver = {
-        .name = "m8xx-pcmcia",
-        .bus = &platform_bus_type,
-        .suspend = pcmcia_socket_dev_suspend,
-        .resume = pcmcia_socket_dev_resume,
-};
-
-static struct platform_device m8xx_device = {
-        .name = "m8xx-pcmcia",
-        .id = 0,
-};
+#endif				/* CONFIG_PRxK */
 
 static u32 pending_events[PCMCIA_SOCKETS_NO];
 static DEFINE_SPINLOCK(pending_event_lock);
@@ -654,24 +564,25 @@
 	struct socket_info *s;
 	struct event_table *e;
 	unsigned int i, events, pscr, pipr, per;
+	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
 
 	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);
+	pscr = in_be32(&pcmcia->pcmc_pscr);
+	pipr = in_be32(&pcmcia->pcmc_pipr);
+	per = in_be32(&pcmcia->pcmc_per);
 
-	for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
 		s = &socket[i];
 		e = &s->events[0];
 		events = 0;
 
-		while(e->regbit) {
-			if(pscr & e->regbit)
+		while (e->regbit) {
+			if (pscr & e->regbit)
 				events |= e->eventbit;
 
-				e++;
+			e++;
 		}
 
 		/*
@@ -679,13 +590,11 @@
 		 * 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)))
-			{
+		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.
@@ -693,24 +602,23 @@
 		 * 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)) {
+		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))));*/
+			   (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);
+			"pipr = 0x%08x\n", i, events, pscr, pipr);
 
-		if(events) {
+		if (events) {
 			spin_lock(&pending_event_lock);
 			pending_events[i] |= events;
 			spin_unlock(&pending_event_lock);
@@ -724,7 +632,7 @@
 			per &= ~M8XX_PCMCIA_RDY_L(0);
 			per &= ~M8XX_PCMCIA_RDY_L(1);
 
-			out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per);
+			out_be32(&pcmcia->pcmc_per, per);
 
 			if (events)
 				pcmcia_parse_events(&socket[i].socket, events);
@@ -732,7 +640,7 @@
 	}
 
 	/* clear the interrupt sources */
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr);
+	out_be32(&pcmcia->pcmc_pscr, pscr);
 
 	dprintk("Interrupt done.\n");
 
@@ -743,21 +651,21 @@
 {
 	u32 k;
 
-	for(k = 0; k < M8XX_SIZES_NO; k++)
-		if(m8xx_size_to_gray[k] == size)
+	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))
+	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)
+static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
 {
 	u32 reg, clocks, psst, psl, psht;
 
-	if(!ns) {
+	if (!ns) {
 
 		/*
 		 * We get called with IO maps setup to 0ns
@@ -765,10 +673,10 @@
 		 * They should be 255ns.
 		 */
 
-		if(is_io)
+		if (is_io)
 			ns = 255;
 		else
-			ns = 100;  /* fast memory if 0 */
+			ns = 100;	/* fast memory if 0 */
 	}
 
 	/*
@@ -779,23 +687,23 @@
 
 /* how we want to adjust the timing - in percent */
 
-#define ADJ 180 /* 80 % longer accesstime - to be sure */
+#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;
+	clocks = ((bus_freq / 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 / 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 = psst << 12;
+	reg |= psl << 7;
 	reg |= psht << 16;
 
 	return reg;
@@ -806,11 +714,12 @@
 	int lsock = container_of(sock, struct socket_info, socket)->slot;
 	struct socket_info *s = &socket[lsock];
 	unsigned int pipr, reg;
+	pcmconf8xx_t *pcmcia = s->pcmcia;
 
-	pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
+	pipr = in_be32(&pcmcia->pcmc_pipr);
 
-	*value  = ((pipr & (M8XX_PCMCIA_CD1(lsock)
-			    | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
+	*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)
@@ -894,16 +803,16 @@
 	/* read out VS1 and VS2 */
 
 	reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
-		>> M8XX_PCMCIA_VS_SHIFT(lsock);
+	    >> M8XX_PCMCIA_VS_SHIFT(lsock);
 
-	if(socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
-		switch(reg) {
+	if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
+		switch (reg) {
 		case 1:
 			*value |= SS_3VCARD;
-			break; /* GND, NC - 3.3V only */
+			break;	/* GND, NC - 3.3V only */
 		case 2:
 			*value |= SS_XVCARD;
-			break; /* NC. GND - x.xV only */
+			break;	/* NC. GND - x.xV only */
 		};
 	}
 
@@ -911,27 +820,29 @@
 	return 0;
 }
 
-static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+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;
+	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
 
-	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);
+	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))
+	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 */
+	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);
+		out_be32(M8XX_PGCRX(lsock),
+			 in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
 
 	/* ... and output enable. */
 
@@ -943,10 +854,11 @@
 	   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 */
+	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);
+		out_be32(M8XX_PGCRX(lsock),
+			 in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
 
 	/*
 	 * We'd better turn off interrupts before
@@ -963,17 +875,17 @@
 	e = &s->events[0];
 	reg = 0;
 
-	if(state->csc_mask & SS_DETECT) {
+	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) {
+	if (state->flags & SS_IOCARD) {
 		/*
 		 * I/O card
 		 */
-		if(state->csc_mask & SS_STSCHG) {
+		if (state->csc_mask & SS_STSCHG) {
 			e->eventbit = SS_STSCHG;
 			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
 			e++;
@@ -981,8 +893,10 @@
 		/*
 		 * 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);
+		if (state->io_irq) {
+			out_be32(M8XX_PGCRX(lsock),
+				 in_be32(M8XX_PGCRX(lsock)) |
+				 mk_int_int_mask(s->hwirq) << 24);
 			/*
 			 * Strange thing here:
 			 * The manual does not tell us which interrupt
@@ -993,33 +907,32 @@
 			 * 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 {
+		} else
+			out_be32(M8XX_PGCRX(lsock),
+				 in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
+	} else {
 		/*
 		 * Memory card
 		 */
-		if(state->csc_mask & SS_BATDEAD) {
+		if (state->csc_mask & SS_BATDEAD) {
 			e->eventbit = SS_BATDEAD;
 			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
 			e++;
 		}
-		if(state->csc_mask & SS_BATWARN) {
+		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) {
+		if (state->csc_mask & SS_READY) {
 			e->eventbit = SS_READY;
-			reg |= e->regbit = 0; //??
+			reg |= e->regbit = 0;	//??
 			e++;
 		}
 	}
 
-	e->regbit = 0;  /* terminate list */
+	e->regbit = 0;		/* terminate list */
 
 	/*
 	 * Clear the status changed .
@@ -1027,7 +940,7 @@
 	 * Writing ones will clear the bits.
 	 */
 
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg);
+	out_be32(&pcmcia->pcmc_pscr, reg);
 
 	/*
 	 * Write the mask.
@@ -1036,15 +949,10 @@
 	 * 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);
+	reg |=
+	    in_be32(&pcmcia->
+		    pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+	out_be32(&pcmcia->pcmc_per, reg);
 
 	spin_unlock_irqrestore(&events_lock, flags);
 
@@ -1062,66 +970,68 @@
 	struct socket_info *s = &socket[lsock];
 	struct pcmcia_win *w;
 	unsigned int reg, winnr;
+	pcmconf8xx_t *pcmcia = s->pcmcia;
 
 #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);
+	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)
+	if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
 		return -EINVAL;
 
-	if(io->flags & MAP_ACTIVE) {
+	if (io->flags & MAP_ACTIVE) {
 
-		dprintk( "io->flags & MAP_ACTIVE\n");
+		dprintk("io->flags & MAP_ACTIVE\n");
 
 		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
-			+ (lsock * PCMCIA_IO_WIN_NO) + io->map;
+		    + (lsock * PCMCIA_IO_WIN_NO) + io->map;
 
 		/* setup registers */
 
-		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+		w = (void *)&pcmcia->pcmc_pbr0;
 		w += winnr;
 
-		out_be32(&w->or, 0); /* turn off window first */
+		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_PCMCIA_POR_IO | (lsock << 2);
 
-		reg |= m8xx_get_speed(io->speed, 1);
+		reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
 
-		if(io->flags & MAP_WRPROT)
+		if (io->flags & MAP_WRPROT)
 			reg |= M8XX_PCMCIA_POR_WRPROT;
 
-		if(io->flags & (MAP_16BIT | MAP_AUTOSZ))
+		/*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */
+		if (io->flags & MAP_16BIT)
 			reg |= M8XX_PCMCIA_POR_16BIT;
 
-		if(io->flags & MAP_ACTIVE)
+		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);
+			"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;
+		    + (lsock * PCMCIA_IO_WIN_NO) + io->map;
 
 		/* setup registers */
 
-		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+		w = (void *)&pcmcia->pcmc_pbr0;
 		w += winnr;
 
-		out_be32(&w->or, 0); /* turn off window */
-		out_be32(&w->br, 0); /* turn off base address */
+		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);
@@ -1129,35 +1039,35 @@
 
 	/* 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);
+	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)
+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;
+	pcmconf8xx_t *pcmcia = s->pcmcia;
 
-	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);
+	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->s) >= PCMCIA_MEM_WIN_SIZE)
 	    || (mem->card_start >= 0x04000000)
-	    || (mem->static_start & 0xfff)                /* 4KByte resolution */
-	    || (mem->card_start & 0xfff))
+	    || (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);
+	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;
@@ -1166,50 +1076,47 @@
 
 	/* Setup the window in the pcmcia controller */
 
-	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+	w = (void *)&pcmcia->pcmc_pbr0;
 	w += winnr;
 
 	reg |= lsock << 2;
 
-	reg |= m8xx_get_speed(mem->speed, 0);
+	reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
 
-	if(mem->flags & MAP_ATTRIB)
-		reg |=  M8XX_PCMCIA_POR_ATTRMEM;
+	if (mem->flags & MAP_ATTRIB)
+		reg |= M8XX_PCMCIA_POR_ATTRMEM;
 
-	if(mem->flags & MAP_WRPROT)
+	if (mem->flags & MAP_WRPROT)
 		reg |= M8XX_PCMCIA_POR_WRPROT;
 
-	if(mem->flags & MAP_16BIT)
+	if (mem->flags & MAP_16BIT)
 		reg |= M8XX_PCMCIA_POR_16BIT;
 
-	if(mem->flags & MAP_ACTIVE)
+	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);
+		"OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
 
-	if(mem->flags & MAP_ACTIVE) {
+	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;
+		    (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);
+		"%#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);
+	old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
 
 	return 0;
 }
@@ -1220,7 +1127,7 @@
 	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);
+	dprintk("sock_init(%d)\n", s);
 
 	m8xx_set_socket(sock, &dead_socket);
 	for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
@@ -1236,111 +1143,195 @@
 
 }
 
-static int m8xx_suspend(struct pcmcia_socket *sock)
+static int m8xx_sock_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,
+	.init = m8xx_sock_init,
+	.suspend = m8xx_sock_suspend,
 	.get_status = m8xx_get_status,
 	.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)
+static int __init m8xx_probe(struct of_device *ofdev,
+			     const struct of_device_id *match)
 {
 	struct pcmcia_win *w;
-	unsigned int i,m;
+	unsigned int i, m, hwirq;
+	pcmconf8xx_t *pcmcia;
+	int status;
+	struct device_node *np = ofdev->node;
 
 	pcmcia_info("%s\n", version);
 
-	if (driver_register(&m8xx_driver))
-		return -1;
+	pcmcia = of_iomap(np, 0);
+	if (pcmcia == NULL)
+		return -EINVAL;
+
+	pcmcia_schlvl = irq_of_parse_and_map(np, 0);
+	hwirq = irq_map[pcmcia_schlvl].hwirq;
+	if (pcmcia_schlvl < 0)
+		return -EINVAL;
+
+	m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
+	m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
 
 	pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
-		    " with IRQ %u.\n", pcmcia_schlvl);
+		    " with IRQ %u  (%d). \n", pcmcia_schlvl, hwirq);
 
 	/* Configure Status change interrupt */
 
-	if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0,
-			  "m8xx_pcmcia", NULL)) {
+	if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
+			driver_name, socket)) {
 		pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
 			     pcmcia_schlvl);
 		return -1;
 	}
 
-	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+	w = (void *)&pcmcia->pcmc_pbr0;
 
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr,
-		M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
+	out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+	clrbits32(&pcmcia->pcmc_per, 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 */
 
-/* connect interrupt and disable CxOE */
+	out_be32(M8XX_PGCRX(0),
+		 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
+	out_be32(M8XX_PGCRX(1),
+		 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
 
-	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 */
 
-/* intialize the fixed memory windows */
-
-	for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
-		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+	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)));
+				 (PCMCIA_MEM_WIN_SIZE
+				  * (m + i * PCMCIA_MEM_WIN_NO)));
 
-			out_be32(&w->or, 0);  /* set to not valid */
+			out_be32(&w->or, 0);	/* set to not valid */
 
 			w++;
 		}
 	}
 
-/* turn off voltage */
+	/* turn off voltage */
 	voltage_set(0, 0, 0);
 	voltage_set(1, 0, 0);
 
-/* Enable external hardware */
+	/* Enable external hardware */
 	hardware_enable(0);
 	hardware_enable(1);
 
-	platform_device_register(&m8xx_device);
-
-	for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) {
+	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.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.pci_irq = pcmcia_schlvl;
 		socket[i].socket.ops = &m8xx_services;
-		socket[i].socket.resource_ops = &pccard_iodyn_ops;
+		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
 		socket[i].socket.cb_dev = NULL;
-		socket[i].socket.dev.parent = &m8xx_device.dev;
+		socket[i].socket.dev.parent = &ofdev->dev;
+		socket[i].pcmcia = pcmcia;
+		socket[i].bus_freq = ppc_proc_freq;
+		socket[i].hwirq = hwirq;
+
 	}
 
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
-		pcmcia_register_socket(&socket[i].socket);
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+		status = pcmcia_register_socket(&socket[i].socket);
+		if (status < 0)
+			pcmcia_error("Socket register failed\n");
+	}
 
 	return 0;
 }
 
-static void __exit m8xx_exit(void)
+static int m8xx_remove(struct of_device *ofdev)
 {
-	int i;
+	u32 m, i;
+	struct pcmcia_win *w;
+	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
 
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+		w = (void *)&pcmcia->pcmc_pbr0;
+
+		out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
+		out_be32(&pcmcia->pcmc_per,
+			 in_be32(&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);
+	}
 	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
 		pcmcia_unregister_socket(&socket[i].socket);
 
-	m8xx_shutdown();
+	free_irq(pcmcia_schlvl, NULL);
 
-	platform_device_unregister(&m8xx_device);
-	driver_unregister(&m8xx_driver);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&pdev->dev, state);
+}
+
+static int m8xx_resume(struct platform_device *pdev)
+{
+	return pcmcia_socket_dev_resume(&pdev->dev);
+}
+#else
+#define m8xx_suspend NULL
+#define m8xx_resume NULL
+#endif
+
+static struct of_device_id m8xx_pcmcia_match[] = {
+	{
+	 .type = "pcmcia",
+	 .compatible = "fsl,pq-pcmcia",
+	 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
+
+static struct of_platform_driver m8xx_pcmcia_driver = {
+	.name = (char *)driver_name,
+	.match_table = m8xx_pcmcia_match,
+	.probe = m8xx_probe,
+	.remove = m8xx_remove,
+	.suspend = m8xx_suspend,
+	.resume = m8xx_resume,
+};
+
+static int __init m8xx_init(void)
+{
+	return of_register_platform_driver(&m8xx_pcmcia_driver);
+}
+
+static void __exit m8xx_exit(void)
+{
+	of_unregister_platform_driver(&m8xx_pcmcia_driver);
 }
 
 module_init(m8xx_init);
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 1959cef..821933f 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -2,11 +2,9 @@
 # Plug and Play configuration
 #
 
-menu "Plug and Play support"
-	depends on HAS_IOMEM
-
-config PNP
+menuconfig PNP
 	bool "Plug and Play support"
+	depends on HAS_IOMEM
 	depends on ISA || ACPI
 	---help---
 	  Plug and Play (PnP) is a standard for peripherals which allows those
@@ -22,15 +20,15 @@
 
 	  If unsure, say Y.
 
+if PNP
+
 config PNP_DEBUG
 	bool "PnP Debug Messages"
-	depends on PNP
 	help
 	  Say Y if you want the Plug and Play Layer to print debug messages.
 	  This is useful if you are developing a PnP driver or troubleshooting.
 
 comment "Protocols"
-	depends on PNP
 
 source "drivers/pnp/isapnp/Kconfig"
 
@@ -38,5 +36,4 @@
 
 source "drivers/pnp/pnpacpi/Kconfig"
 
-endmenu
-
+endif # PNP
diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig
index 578651e..f1ef366 100644
--- a/drivers/pnp/isapnp/Kconfig
+++ b/drivers/pnp/isapnp/Kconfig
@@ -3,7 +3,7 @@
 #
 config ISAPNP
 	bool "ISA Plug and Play support"
-	depends on PNP && ISA
+	depends on ISA
 	help
 	  Say Y here if you would like support for ISA Plug and Play devices.
 	  Some information is in <file:Documentation/isapnp.txt>.
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index a0b1587..914d00c 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -370,8 +370,6 @@
 #if 0
 	printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
 #endif
-	if (type == 0)				/* wrong type */
-		return -1;
 	if (*type == 0xff && *size == 0xffff)	/* probably invalid data */
 		return -1;
 	return 0;
diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig
index fab848c..b986d9f 100644
--- a/drivers/pnp/pnpbios/Kconfig
+++ b/drivers/pnp/pnpbios/Kconfig
@@ -3,7 +3,7 @@
 #
 config PNPBIOS
 	bool "Plug and Play BIOS support (EXPERIMENTAL)"
-	depends on PNP && ISA && X86 && EXPERIMENTAL
+	depends on ISA && X86 && EXPERIMENTAL
 	default n
 	---help---
 	  Linux uses the PNPBIOS as defined in "Plug and Play BIOS
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 3a201b7..03baf1c 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -160,6 +160,7 @@
 {
 	static struct pnp_docking_station_info now;
 	int docked = -1, d = 0;
+	set_freezable();
 	while (!unloading)
 	{
 		int status;
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index e251d1c..746031d 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1,3 +1,6 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
-obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o
+ps3av_mod-objs		+= ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
 obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
+obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 1393e64..85e2161 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -1,32 +1,30 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend support.
  *
- * AV backend support for PS3
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony 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; version 2 of the License.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
  *
- * 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.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  You 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/delay.h>
 #include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/kernel.h>
 #include <linux/ioctl.h>
 
 #include <asm/firmware.h>
-#include <asm/lv1call.h>
 #include <asm/ps3av.h>
 #include <asm/ps3.h>
 
@@ -39,13 +37,12 @@
 module_param(timeout, int, 0644);
 
 static struct ps3av {
-	int available;
 	struct mutex mutex;
 	struct work_struct work;
 	struct completion done;
 	struct workqueue_struct *wq;
 	int open_count;
-	struct ps3_vuart_port_device *dev;
+	struct ps3_system_bus_device *dev;
 
 	int region;
 	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
@@ -55,11 +52,13 @@
 	u32 audio_port;
 	int ps3av_mode;
 	int ps3av_mode_old;
-} ps3av;
-
-static struct ps3_vuart_port_device ps3av_dev = {
-	.match_id = PS3_MATCH_ID_AV_SETTINGS
-};
+	union {
+		struct ps3av_reply_hdr reply_hdr;
+		u8 raw[PS3AV_BUF_SIZE];
+	} recv_buf;
+	void (*flip_ctl)(int on, void *data);
+	void *flip_data;
+} *ps3av;
 
 /* color space */
 #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
@@ -169,7 +168,7 @@
 	if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
 		table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
 		if (table)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"recv event packet cid:%08x port:0x%x size:%d\n",
 				hdr->cid, ps3av_event_get_port_id(hdr->cid),
 				hdr->size);
@@ -182,6 +181,41 @@
 	return 0;
 }
 
+
+#define POLLING_INTERVAL  25	/* in msec */
+
+static int ps3av_vuart_write(struct ps3_system_bus_device *dev,
+			     const void *buf, unsigned long size)
+{
+	int error;
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	error = ps3_vuart_write(dev, buf, size);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+	return error ? error : size;
+}
+
+static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf,
+			    unsigned long size, int timeout)
+{
+	int error;
+	int loopcnt = 0;
+
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+	while (loopcnt++ <= timeout) {
+		error = ps3_vuart_read(dev, buf, size);
+		if (!error)
+			return size;
+		if (error != -EAGAIN) {
+			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+			       __func__, error);
+			return error;
+		}
+		msleep(POLLING_INTERVAL);
+	}
+	return -EWOULDBLOCK;
+}
+
 static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
 			      struct ps3av_reply_hdr *recv_buf, int write_len,
 			      int read_len)
@@ -190,13 +224,13 @@
 	u32 cmd;
 	int event;
 
-	if (!ps3av.available)
+	if (!ps3av)
 		return -ENODEV;
 
 	/* send pkt */
-	res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+	res = ps3av_vuart_write(ps3av->dev, send_buf, write_len);
 	if (res < 0) {
-		dev_dbg(&ps3av_dev.core,
+		dev_dbg(&ps3av->dev->core,
 			"%s: ps3av_vuart_write() failed (result=%d)\n",
 			__func__, res);
 		return res;
@@ -206,20 +240,20 @@
 	cmd = send_buf->cid;
 	do {
 		/* read header */
-		res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+		res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE,
 				       timeout);
 		if (res != PS3AV_HDR_SIZE) {
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
 				__func__, res);
 			return res;
 		}
 
 		/* read body */
-		res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+		res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid,
 				       recv_buf->size, timeout);
 		if (res < 0) {
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
 				__func__, res);
 			return res;
@@ -230,7 +264,7 @@
 	} while (event);
 
 	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
-		dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
+		dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n",
 			__func__, recv_buf->cid);
 		return -EINVAL;
 	}
@@ -245,7 +279,7 @@
 	int return_len;
 
 	if (recv_buf->version != PS3AV_VERSION) {
-		dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
+		dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n",
 			recv_buf->version);
 		return -EFAULT;
 	}
@@ -267,16 +301,11 @@
 		 struct ps3av_send_hdr *buf)
 {
 	int res = 0;
-	static union {
-		struct ps3av_reply_hdr reply_hdr;
-		u8 raw[PS3AV_BUF_SIZE];
-	} recv_buf;
-
 	u32 *table;
 
-	BUG_ON(!ps3av.available);
+	BUG_ON(!ps3av);
 
-	mutex_lock(&ps3av.mutex);
+	mutex_lock(&ps3av->mutex);
 
 	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
 	BUG_ON(!table);
@@ -288,7 +317,7 @@
 	ps3av_set_hdr(cid, send_len, buf);
 
 	/* send packet via vuart */
-	res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+	res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len,
 				 usr_buf_size);
 	if (res < 0) {
 		printk(KERN_ERR
@@ -298,7 +327,7 @@
 	}
 
 	/* process reply packet */
-	res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+	res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr,
 					 usr_buf_size);
 	if (res < 0) {
 		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
@@ -306,11 +335,11 @@
 		goto err;
 	}
 
-	mutex_unlock(&ps3av.mutex);
+	mutex_unlock(&ps3av->mutex);
 	return 0;
 
       err:
-	mutex_unlock(&ps3av.mutex);
+	mutex_unlock(&ps3av->mutex);
 	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
 	return res;
 }
@@ -319,11 +348,11 @@
 {
 	int i, num_of_av_port, res;
 
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
 	/* video mute on */
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+		res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
@@ -335,13 +364,13 @@
 {
 	int i, num_of_hdmi_port, num_of_av_port, res;
 
-	num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
 
 	/* tv mute */
 	for (i = 0; i < num_of_hdmi_port; i++) {
-		res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+		res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
 					   PS3AV_CMD_MUTE_ON);
 		if (res < 0)
 			return -1;
@@ -350,11 +379,11 @@
 
 	/* video mute on */
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+		res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]);
 		if (res < 0)
 			return -1;
 		if (i < num_of_hdmi_port) {
-			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+			res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
 						   PS3AV_CMD_MUTE_OFF);
 			if (res < 0)
 				return -1;
@@ -369,17 +398,17 @@
 {
 	int i, num_of_av_port, num_of_opt_port, res;
 
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
-	num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
+	num_of_opt_port = ps3av->av_hw_conf.num_of_spdif;
 
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+		res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
 	for (i = 0; i < num_of_opt_port; i++) {
-		res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+		res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
@@ -394,40 +423,40 @@
 	struct ps3av_pkt_audio_mode audio_mode;
 	u32 len = 0;
 
-	num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
-		       ps3av.av_hw_conf.num_of_avmulti +
-		       ps3av.av_hw_conf.num_of_spdif;
+	num_of_audio = ps3av->av_hw_conf.num_of_hdmi +
+		       ps3av->av_hw_conf.num_of_avmulti +
+		       ps3av->av_hw_conf.num_of_spdif;
 
 	avb_param.num_of_video_pkt = 0;
 	avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;	/* always 0 */
 	avb_param.num_of_av_video_pkt = 0;
-	avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+	avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi;
 
-	vid = video_mode_table[ps3av.ps3av_mode].vid;
+	vid = video_mode_table[ps3av->ps3av_mode].vid;
 
 	/* audio mute */
 	ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
 
 	/* audio inactive */
-	res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+	res = ps3av_cmd_audio_active(0, ps3av->audio_port);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core,
+		dev_dbg(&ps3av->dev->core,
 			"ps3av_cmd_audio_active OFF failed\n");
 
 	/* audio_pkt */
 	for (i = 0; i < num_of_audio; i++) {
-		ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
-					 word_bits, format, source);
-		if (i < ps3av.av_hw_conf.num_of_hdmi) {
+		ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch,
+					 fs, word_bits, format, source);
+		if (i < ps3av->av_hw_conf.num_of_hdmi) {
 			/* hdmi only */
 			len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
-							    ps3av.av_port[i],
+							    ps3av->av_port[i],
 							    &audio_mode, vid);
 		}
 		/* audio_mode pkt should be sent separately */
 		res = ps3av_cmd_audio_mode(&audio_mode);
 		if (res < 0)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_audio_mode failed, port:%x\n", i);
 	}
 
@@ -435,15 +464,16 @@
 	len += offsetof(struct ps3av_pkt_avb_param, buf);
 	res = ps3av_cmd_avb_param(&avb_param, len);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+		dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
 	/* audio mute */
 	ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
 
 	/* audio active */
-	res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+	res = ps3av_cmd_audio_active(1, ps3av->audio_port);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
+		dev_dbg(&ps3av->dev->core,
+			"ps3av_cmd_audio_active ON failed\n");
 
 	return 0;
 }
@@ -456,7 +486,7 @@
 	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
 
 	/* wake up ps3avd to do the actual video mode setting */
-	queue_work(ps3av.wq, &ps3av.work);
+	queue_work(ps3av->wq, &ps3av->work);
 
 	return 0;
 }
@@ -473,8 +503,8 @@
 
 	avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;	/* num of head */
 	avb_param.num_of_audio_pkt = 0;
-	avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
-					ps3av.av_hw_conf.num_of_avmulti;
+	avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
+					ps3av->av_hw_conf.num_of_avmulti;
 	avb_param.num_of_av_audio_pkt = 0;
 
 	/* video signal off */
@@ -484,21 +514,21 @@
 	if (id & PS3AV_MODE_HDCP_OFF) {
 		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
 		if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-			dev_dbg(&ps3av_dev.core, "Not supported\n");
+			dev_dbg(&ps3av->dev->core, "Not supported\n");
 		else if (res)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_av_hdmi_mode failed\n");
 	} else if (old_id & PS3AV_MODE_HDCP_OFF) {
 		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
 		if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_av_hdmi_mode failed\n");
 	}
 
 	/* video_pkt */
 	for (i = 0; i < avb_param.num_of_video_pkt; i++)
 		len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
-						ps3av.head[i], video_mode->vid,
+						ps3av->head[i], video_mode->vid,
 						video_mode->fmt, id);
 	/* av_video_pkt */
 	for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
@@ -507,12 +537,12 @@
 		else
 			av_video_cs = video_mode->cs;
 #ifndef PS3AV_HDMI_YUV
-		if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
-		    ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+		if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+		    ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
 			av_video_cs = RGB8;	/* use RGB for HDMI */
 #endif
 		len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
-						 ps3av.av_port[i],
+						 ps3av->av_port[i],
 						 video_mode->vid, av_video_cs,
 						 video_mode->aspect, id);
 	}
@@ -524,7 +554,7 @@
 		       "%s: Command failed. Please try your request again. \n",
 		       __func__);
 	else if (res)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+		dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
 	msleep(1500);
 	/* av video mute */
@@ -533,8 +563,8 @@
 
 static void ps3avd(struct work_struct *work)
 {
-	ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old);
-	complete(&ps3av.done);
+	ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old);
+	complete(&ps3av->done);
 }
 
 static int ps3av_vid2table_id(int vid)
@@ -601,7 +631,7 @@
 		return vid;
 	}
 
-	if (ps3av.region & PS3AV_REGION_60)
+	if (ps3av->region & PS3AV_REGION_60)
 		vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
 	else
 		vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
@@ -643,16 +673,16 @@
 		vid = PS3AV_DEFAULT_DVI_VID;
 	} else if (vid == -1) {
 		/* no HDMI interface or HDMI is off */
-		if (ps3av.region & PS3AV_REGION_60)
+		if (ps3av->region & PS3AV_REGION_60)
 			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
 		else
 			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
-		if (ps3av.region & PS3AV_REGION_RGB)
+		if (ps3av->region & PS3AV_REGION_RGB)
 			rgb = PS3AV_MODE_RGB;
 	} else if (boot) {
 		/* HDMI: using DEFAULT HDMI_VID while booting up */
 		info = &monitor_info.info;
-		if (ps3av.region & PS3AV_REGION_60) {
+		if (ps3av->region & PS3AV_REGION_60) {
 			if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
 				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
 			else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
@@ -715,14 +745,14 @@
 
 	size = ARRAY_SIZE(video_mode_table);
 	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
-		dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id);
+		dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id);
 		return -EINVAL;
 	}
 
 	/* auto mode */
 	option = id & ~PS3AV_MODE_MASK;
 	if ((id & PS3AV_MODE_MASK) == 0) {
-		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+		id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
 		if (id < 1) {
 			printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
 			return -EINVAL;
@@ -731,11 +761,11 @@
 	}
 
 	/* set videomode */
-	wait_for_completion(&ps3av.done);
-	ps3av.ps3av_mode_old = ps3av.ps3av_mode;
-	ps3av.ps3av_mode = id;
+	wait_for_completion(&ps3av->done);
+	ps3av->ps3av_mode_old = ps3av->ps3av_mode;
+	ps3av->ps3av_mode = id;
 	if (ps3av_set_videomode())
-		ps3av.ps3av_mode = ps3av.ps3av_mode_old;
+		ps3av->ps3av_mode = ps3av->ps3av_mode_old;
 
 	return 0;
 }
@@ -744,7 +774,7 @@
 
 int ps3av_get_auto_mode(int boot)
 {
-	return ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+	return ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
@@ -772,7 +802,7 @@
 
 int ps3av_get_mode(void)
 {
-	return ps3av.ps3av_mode;
+	return ps3av ? ps3av->ps3av_mode : 0;
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_mode);
@@ -842,82 +872,65 @@
 
 EXPORT_SYMBOL_GPL(ps3av_audio_mute);
 
-int ps3av_dev_open(void)
+void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+			     void *flip_data)
 {
-	int status = 0;
+	mutex_lock(&ps3av->mutex);
+	ps3av->flip_ctl = flip_ctl;
+	ps3av->flip_data = flip_data;
+	mutex_unlock(&ps3av->mutex);
+}
+EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl);
 
-	mutex_lock(&ps3av.mutex);
-	if (!ps3av.open_count++) {
-		status = lv1_gpu_open(0);
-		if (status) {
-			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
-			       __func__, status);
-			ps3av.open_count--;
-		}
-	}
-	mutex_unlock(&ps3av.mutex);
-
-	return status;
+void ps3av_flip_ctl(int on)
+{
+	mutex_lock(&ps3av->mutex);
+	if (ps3av->flip_ctl)
+		ps3av->flip_ctl(on, ps3av->flip_data);
+	mutex_unlock(&ps3av->mutex);
 }
 
-EXPORT_SYMBOL_GPL(ps3av_dev_open);
-
-int ps3av_dev_close(void)
-{
-	int status = 0;
-
-	mutex_lock(&ps3av.mutex);
-	if (ps3av.open_count <= 0) {
-		printk(KERN_ERR "%s: GPU already closed\n", __func__);
-		status = -1;
-	} else if (!--ps3av.open_count) {
-		status = lv1_gpu_close();
-		if (status)
-			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
-			       __func__, status);
-	}
-	mutex_unlock(&ps3av.mutex);
-
-	return status;
-}
-
-EXPORT_SYMBOL_GPL(ps3av_dev_close);
-
-static int ps3av_probe(struct ps3_vuart_port_device *dev)
+static int ps3av_probe(struct ps3_system_bus_device *dev)
 {
 	int res;
 	u32 id;
 
-	dev_dbg(&ps3av_dev.core, "init ...\n");
-	dev_dbg(&ps3av_dev.core, "  timeout=%d\n", timeout);
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	dev_dbg(&dev->core, "  timeout=%d\n", timeout);
 
-	memset(&ps3av, 0, sizeof(ps3av));
+	if (ps3av) {
+		dev_err(&dev->core, "Only one ps3av device is supported\n");
+		return -EBUSY;
+	}
 
-	mutex_init(&ps3av.mutex);
-	ps3av.ps3av_mode = 0;
-	ps3av.dev = dev;
-
-	INIT_WORK(&ps3av.work, ps3avd);
-	init_completion(&ps3av.done);
-	complete(&ps3av.done);
-	ps3av.wq = create_singlethread_workqueue("ps3avd");
-	if (!ps3av.wq)
+	ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL);
+	if (!ps3av)
 		return -ENOMEM;
 
-	ps3av.available = 1;
+	mutex_init(&ps3av->mutex);
+	ps3av->ps3av_mode = 0;
+	ps3av->dev = dev;
+
+	INIT_WORK(&ps3av->work, ps3avd);
+	init_completion(&ps3av->done);
+	complete(&ps3av->done);
+	ps3av->wq = create_singlethread_workqueue("ps3avd");
+	if (!ps3av->wq)
+		goto fail;
+
 	switch (ps3_os_area_get_av_multi_out()) {
 	case PS3_PARAM_AV_MULTI_OUT_NTSC:
-		ps3av.region = PS3AV_REGION_60;
+		ps3av->region = PS3AV_REGION_60;
 		break;
 	case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
 	case PS3_PARAM_AV_MULTI_OUT_SECAM:
-		ps3av.region = PS3AV_REGION_50;
+		ps3av->region = PS3AV_REGION_50;
 		break;
 	case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
-		ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+		ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
 		break;
 	default:
-		ps3av.region = PS3AV_REGION_60;
+		ps3av->region = PS3AV_REGION_60;
 		break;
 	}
 
@@ -927,39 +940,47 @@
 		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
 		       res);
 
-	ps3av_get_hw_conf(&ps3av);
-	id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
-	mutex_lock(&ps3av.mutex);
-	ps3av.ps3av_mode = id;
-	mutex_unlock(&ps3av.mutex);
+	ps3av_get_hw_conf(ps3av);
+	id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1);
+	mutex_lock(&ps3av->mutex);
+	ps3av->ps3av_mode = id;
+	mutex_unlock(&ps3av->mutex);
 
-	dev_dbg(&ps3av_dev.core, "init...done\n");
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
 	return 0;
+
+fail:
+	kfree(ps3av);
+	ps3av = NULL;
+	return -ENOMEM;
 }
 
-static int ps3av_remove(struct ps3_vuart_port_device *dev)
+static int ps3av_remove(struct ps3_system_bus_device *dev)
 {
-	if (ps3av.available) {
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	if (ps3av) {
 		ps3av_cmd_fin();
-		if (ps3av.wq)
-			destroy_workqueue(ps3av.wq);
-		ps3av.available = 0;
+		if (ps3av->wq)
+			destroy_workqueue(ps3av->wq);
+		kfree(ps3av);
+		ps3av = NULL;
 	}
 
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 	return 0;
 }
 
-static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
+static void ps3av_shutdown(struct ps3_system_bus_device *dev)
 {
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
 	ps3av_remove(dev);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 }
 
 static struct ps3_vuart_port_driver ps3av_driver = {
-	.match_id = PS3_MATCH_ID_AV_SETTINGS,
-	.core = {
-		.name = "ps3_av",
-	},
+	.core.match_id = PS3_MATCH_ID_AV_SETTINGS,
+	.core.core.name = "ps3_av",
 	.probe = ps3av_probe,
 	.remove = ps3av_remove,
 	.shutdown = ps3av_shutdown,
@@ -972,6 +993,8 @@
 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 		return -ENODEV;
 
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
 	error = ps3_vuart_port_driver_register(&ps3av_driver);
 	if (error) {
 		printk(KERN_ERR
@@ -980,20 +1003,21 @@
 		return error;
 	}
 
-	error = ps3_vuart_port_device_register(&ps3av_dev);
-	if (error)
-		printk(KERN_ERR
-		       "%s: ps3_vuart_port_device_register failed %d\n",
-		       __func__, error);
-
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return error;
 }
 
 static void __exit ps3av_module_exit(void)
 {
-	device_unregister(&ps3av_dev.core);
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 	ps3_vuart_port_driver_unregister(&ps3av_driver);
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 }
 
 subsys_initcall(ps3av_module_init);
 module_exit(ps3av_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 AV Settings Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index 0145ea1..f72f5dd 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -143,6 +143,14 @@
 	return PS3AV_CMD_AV_VID_480P;
 }
 
+static int ps3av_hdmi_range(void)
+{
+	if (ps3_compare_firmware_version(1, 8, 0) < 0)
+		return 0;
+	else
+		return 1; /* supported */
+}
+
 int ps3av_cmd_init(void)
 {
 	int res;
@@ -350,6 +358,10 @@
 	/* should be same as video_mode.video_cs_out */
 	av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
 	av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+	if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range())
+		av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON;
+	else /* default off */
+		av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF;
 	av_video_cs->aspect = aspect;
 	if (id & PS3AV_MODE_DITHER) {
 		av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
@@ -392,6 +404,10 @@
 	video_mode->pitch = video_mode->width * 4;	/* line_length */
 	video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
 	video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+	if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range())
+		video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT;
+	else /* default enable */
+		video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT;
 	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
 
 	pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
@@ -852,7 +868,7 @@
 {
 	int res;
 
-	ps3fb_flip_ctl(0);	/* flip off */
+	ps3av_flip_ctl(0);	/* flip off */
 
 	/* avb packet */
 	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
@@ -866,7 +882,7 @@
 			 res);
 
       out:
-	ps3fb_flip_ctl(1);	/* flip on */
+	ps3av_flip_ctl(1);	/* flip on */
 	return res;
 }
 
@@ -987,34 +1003,3 @@
 		| PS3AV_CMD_AV_LAYOUT_176 \
 		| PS3AV_CMD_AV_LAYOUT_192)
 
-/************************* vuart ***************************/
-
-#define POLLING_INTERVAL  25	/* in msec */
-
-int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
-		      unsigned long size)
-{
-	int error = ps3_vuart_write(dev, buf, size);
-	return error ? error : size;
-}
-
-int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-		     unsigned long size, int timeout)
-{
-	int error;
-	int loopcnt = 0;
-
-	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
-	while (loopcnt++ <= timeout) {
-		error = ps3_vuart_read(dev, buf, size);
-		if (!error)
-			return size;
-		if (error != -EAGAIN) {
-			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
-			       __func__, error);
-			return error;
-		}
-		msleep(POLLING_INTERVAL);
-	}
-	return -EWOULDBLOCK;
-}
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
new file mode 100644
index 0000000..3a9824e
--- /dev/null
+++ b/drivers/ps3/ps3stor_lib.c
@@ -0,0 +1,302 @@
+/*
+ * PS3 Storage Library
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+
+static int ps3stor_probe_access(struct ps3_storage_device *dev)
+{
+	int res, error;
+	unsigned int i;
+	unsigned long n;
+
+	if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) {
+		/* special case: CD-ROM is assumed always accessible */
+		dev->accessible_regions = 1;
+		return 0;
+	}
+
+	error = -EPERM;
+	for (i = 0; i < dev->num_regions; i++) {
+		dev_dbg(&dev->sbd.core,
+			"%s:%u: checking accessibility of region %u\n",
+			__func__, __LINE__, i);
+
+		dev->region_idx = i;
+		res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
+						 0);
+		if (res) {
+			dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
+				"region %u is not accessible\n", __func__,
+				__LINE__, i);
+			continue;
+		}
+
+		dev_dbg(&dev->sbd.core, "%s:%u: region %u is accessible\n",
+			__func__, __LINE__, i);
+		set_bit(i, &dev->accessible_regions);
+
+		/* We can access at least one region */
+		error = 0;
+	}
+	if (error)
+		return error;
+
+	n = hweight_long(dev->accessible_regions);
+	if (n > 1)
+		dev_info(&dev->sbd.core,
+			 "%s:%u: %lu accessible regions found. Only the first "
+			 "one will be used",
+			 __func__, __LINE__, n);
+	dev->region_idx = __ffs(dev->accessible_regions);
+	dev_info(&dev->sbd.core,
+		 "First accessible region has index %u start %lu size %lu\n",
+		 dev->region_idx, dev->regions[dev->region_idx].start,
+		 dev->regions[dev->region_idx].size);
+
+	return 0;
+}
+
+
+/**
+ *	ps3stor_setup - Setup a storage device before use
+ *	@dev: Pointer to a struct ps3_storage_device
+ *	@handler: Pointer to an interrupt handler
+ *
+ *	Returns 0 for success, or an error code
+ */
+int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
+{
+	int error, res, alignment;
+	enum ps3_dma_page_size page_size;
+
+	error = ps3_open_hv_device(&dev->sbd);
+	if (error) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: ps3_open_hv_device failed %d\n", __func__,
+			__LINE__, error);
+		goto fail;
+	}
+
+	error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY,
+						&dev->irq);
+	if (error) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
+		       __func__, __LINE__, error);
+		goto fail_close_device;
+	}
+
+	error = request_irq(dev->irq, handler, IRQF_DISABLED,
+			    dev->sbd.core.driver->name, dev);
+	if (error) {
+		dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
+			__func__, __LINE__, error);
+		goto fail_sb_event_receive_port_destroy;
+	}
+
+	alignment = min(__ffs(dev->bounce_size),
+			__ffs((unsigned long)dev->bounce_buf));
+	if (alignment < 12) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: bounce buffer not aligned (%lx at 0x%p)\n",
+			__func__, __LINE__, dev->bounce_size, dev->bounce_buf);
+		error = -EINVAL;
+		goto fail_free_irq;
+	} else if (alignment < 16)
+		page_size = PS3_DMA_4K;
+	else
+		page_size = PS3_DMA_64K;
+	dev->sbd.d_region = &dev->dma_region;
+	ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size,
+			    PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size);
+	res = ps3_dma_region_create(&dev->dma_region);
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n",
+			__func__, __LINE__);
+		error = -ENOMEM;
+		goto fail_free_irq;
+	}
+
+	dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf));
+	dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf,
+					 dev->bounce_size, DMA_BIDIRECTIONAL);
+	if (!dev->bounce_dma) {
+		dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n",
+			__func__, __LINE__);
+		error = -ENODEV;
+		goto fail_free_dma;
+	}
+
+	error = ps3stor_probe_access(dev);
+	if (error) {
+		dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n",
+			__func__, __LINE__);
+		goto fail_unmap_dma;
+	}
+	return 0;
+
+fail_unmap_dma:
+	dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+			 DMA_BIDIRECTIONAL);
+fail_free_dma:
+	ps3_dma_region_free(&dev->dma_region);
+fail_free_irq:
+	free_irq(dev->irq, dev);
+fail_sb_event_receive_port_destroy:
+	ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+fail_close_device:
+	ps3_close_hv_device(&dev->sbd);
+fail:
+	return error;
+}
+EXPORT_SYMBOL_GPL(ps3stor_setup);
+
+
+/**
+ *	ps3stor_teardown - Tear down a storage device after use
+ *	@dev: Pointer to a struct ps3_storage_device
+ */
+void ps3stor_teardown(struct ps3_storage_device *dev)
+{
+	int error;
+
+	dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+			 DMA_BIDIRECTIONAL);
+	ps3_dma_region_free(&dev->dma_region);
+
+	free_irq(dev->irq, dev);
+
+	error = ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+	if (error)
+		dev_err(&dev->sbd.core,
+			"%s:%u: destroy event receive port failed %d\n",
+			__func__, __LINE__, error);
+
+	error = ps3_close_hv_device(&dev->sbd);
+	if (error)
+		dev_err(&dev->sbd.core,
+			"%s:%u: ps3_close_hv_device failed %d\n", __func__,
+			__LINE__, error);
+}
+EXPORT_SYMBOL_GPL(ps3stor_teardown);
+
+
+/**
+ *	ps3stor_read_write_sectors - read/write from/to a storage device
+ *	@dev: Pointer to a struct ps3_storage_device
+ *	@lpar: HV logical partition address
+ *	@start_sector: First sector to read/write
+ *	@sectors: Number of sectors to read/write
+ *	@write: Flag indicating write (non-zero) or read (zero)
+ *
+ *	Returns 0 for success, -1 in case of failure to submit the command, or
+ *	an LV1 status value in case of other errors
+ */
+u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+			       u64 start_sector, u64 sectors, int write)
+{
+	unsigned int region_id = dev->regions[dev->region_idx].id;
+	const char *op = write ? "write" : "read";
+	int res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+		__func__, __LINE__, op, sectors, start_sector);
+
+	init_completion(&dev->done);
+	res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
+					start_sector, sectors, 0, lpar,
+					&dev->tag)
+		    : lv1_storage_read(dev->sbd.dev_id, region_id,
+				       start_sector, sectors, 0, lpar,
+				       &dev->tag);
+	if (res) {
+		dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
+			__LINE__, op, res);
+		return -1;
+	}
+
+	wait_for_completion(&dev->done);
+	if (dev->lv1_status) {
+		dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+			__LINE__, op, dev->lv1_status);
+		return dev->lv1_status;
+	}
+
+	dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__,
+		op);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_read_write_sectors);
+
+
+/**
+ *	ps3stor_send_command - send a device command to a storage device
+ *	@dev: Pointer to a struct ps3_storage_device
+ *	@cmd: Command number
+ *	@arg1: First command argument
+ *	@arg2: Second command argument
+ *	@arg3: Third command argument
+ *	@arg4: Fourth command argument
+ *
+ *	Returns 0 for success, -1 in case of failure to submit the command, or
+ *	an LV1 status value in case of other errors
+ */
+u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
+			 u64 arg2, u64 arg3, u64 arg4)
+{
+	int res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
+		__LINE__, cmd);
+
+	init_completion(&dev->done);
+
+	res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1,
+					      arg2, arg3, arg4, &dev->tag);
+	if (res) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: send_device_command 0x%lx failed %d\n",
+			__func__, __LINE__, cmd, res);
+		return -1;
+	}
+
+	wait_for_completion(&dev->done);
+	if (dev->lv1_status) {
+		dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
+			__func__, __LINE__, cmd, dev->lv1_status);
+		return dev->lv1_status;
+	}
+
+	dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
+		__LINE__, cmd);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_send_command);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 Storage Bus Library");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
new file mode 100644
index 0000000..31648f7
--- /dev/null
+++ b/drivers/ps3/sys-manager-core.c
@@ -0,0 +1,68 @@
+/*
+ *  PS3 System Manager core.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony 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; version 2 of the License.
+ *
+ *  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 <asm/ps3.h>
+
+/**
+ * Staticly linked routines that allow late binding of a loaded sys-manager
+ * module.
+ */
+
+static struct ps3_sys_manager_ops ps3_sys_manager_ops;
+
+/**
+ * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module.
+ * @ops: struct ps3_sys_manager_ops.
+ *
+ * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to
+ * register call back ops for power control.  Copies data to the static
+ * variable ps3_sys_manager_ops.
+ */
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops)
+{
+	BUG_ON(!ops);
+	BUG_ON(!ops->dev);
+	ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops;
+}
+EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops);
+
+void ps3_sys_manager_power_off(void)
+{
+	if (ps3_sys_manager_ops.power_off)
+		ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1)
+		(void)0;
+}
+
+void ps3_sys_manager_restart(void)
+{
+	if (ps3_sys_manager_ops.restart)
+		ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1)
+		(void)0;
+}
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c
index 3aa2b0d..8461b08 100644
--- a/drivers/ps3/sys-manager.c
+++ b/drivers/ps3/sys-manager.c
@@ -35,7 +35,7 @@
 /**
  * ps3_sys_manager - PS3 system manager driver.
  *
- * The system manager provides an asyncronous system event notification
+ * The system manager provides an asynchronous system event notification
  * mechanism for reporting events like thermal alert and button presses to
  * guests.  It also provides support to control system shutdown and startup.
  *
@@ -52,6 +52,7 @@
  * @size: Header size in bytes, curently 16.
  * @payload_size: Message payload size in bytes.
  * @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ * @request_tag: Unique number to identify reply.
  */
 
 struct ps3_sys_manager_header {
@@ -61,29 +62,49 @@
 	u16 reserved_1;
 	u32 payload_size;
 	u16 service_id;
-	u16 reserved_2[3];
+	u16 reserved_2;
+	u32 request_tag;
 };
 
+#define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__)
+static void __maybe_unused _dump_sm_header(
+	const struct ps3_sys_manager_header *h, const char *func, int line)
+{
+	pr_debug("%s:%d: version:      %xh\n", func, line, h->version);
+	pr_debug("%s:%d: size:         %xh\n", func, line, h->size);
+	pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size);
+	pr_debug("%s:%d: service_id:   %xh\n", func, line, h->service_id);
+	pr_debug("%s:%d: request_tag:  %xh\n", func, line, h->request_tag);
+}
+
 /**
- * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length.
+ * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length.
  *
- * Currently all messages received from the system manager are the same length
- * (16 bytes header + 16 bytes payload = 32 bytes).  This knowlege is used to
- * simplify the logic.
+ * Currently all messages received from the system manager are either
+ * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
+ * + 16 bytes payload = 32 bytes).  This knowlege is used to simplify
+ * the logic.
  */
 
 enum {
-	PS3_SM_RX_MSG_LEN = 32,
+	PS3_SM_RX_MSG_LEN_MIN = 24,
+	PS3_SM_RX_MSG_LEN_MAX = 32,
 };
 
 /**
  * enum ps3_sys_manager_service_id - Message header service_id.
- * @PS3_SM_SERVICE_ID_REQUEST:      guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_COMMAND:      guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_RESPONSE:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_SET_ATTR:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_SET_NEXT_OP:  guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST:       guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND:       guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT:  guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP:   guest --> sys_manager.
+ *
+ * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a
+ * a PS3_SM_SERVICE_ID_REQUEST message.  It also seems to be returned when
+ * a REQUEST message is sent at the wrong time.
  */
 
 enum ps3_sys_manager_service_id {
@@ -93,6 +114,7 @@
 	PS3_SM_SERVICE_ID_COMMAND = 3,
 	PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
 	PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+	PS3_SM_SERVICE_ID_REQUEST_ERROR = 6,
 	PS3_SM_SERVICE_ID_SET_ATTR = 8,
 };
 
@@ -185,11 +207,21 @@
 };
 
 /**
+ * ps3_sm_force_power_off - Poweroff helper.
+ *
+ * A global variable used to force a poweroff when the power button has
+ * been pressed irrespective of how init handles the ctrl_alt_del signal.
+ *
+ */
+
+static unsigned int ps3_sm_force_power_off;
+
+/**
  * ps3_sys_manager_write - Helper to write a two part message to the vuart.
  *
  */
 
-static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_write(struct ps3_system_bus_device *dev,
 	const struct ps3_sys_manager_header *header, const void *payload)
 {
 	int result;
@@ -213,15 +245,10 @@
  *
  */
 
-static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev,
 	enum ps3_sys_manager_attr attr)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_SET_ATTR,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 reserved_1[3];
@@ -232,6 +259,12 @@
 
 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_SET_ATTR;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 1;
 	payload.attribute = attr;
@@ -245,16 +278,11 @@
  * Tell the system manager what to do after this lpar is destroyed.
  */
 
-static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev,
 	enum ps3_sys_manager_next_op op,
 	enum ps3_sys_manager_wake_source wake_source)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 type;
@@ -268,6 +296,12 @@
 
 	dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 3;
 	payload.type = op;
@@ -286,32 +320,35 @@
  * the command is then communicated back to the system manager with a response
  * message.
  *
- * Currently, the only supported request it the 'shutdown self' request.
+ * Currently, the only supported request is the 'shutdown self' request.
  */
 
-static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_send_request_shutdown(
+	struct ps3_system_bus_device *dev)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_REQUEST,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 type;
 		u8 gos_id;
 		u8 reserved_1[13];
-	} static const payload = {
-		.version = 1,
-		.type = 1, /* shutdown */
-		.gos_id = 0, /* self */
-	};
+	} payload;
 
 	BUILD_BUG_ON(sizeof(payload) != 16);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_REQUEST;
+
+	memset(&payload, 0, sizeof(payload));
+	payload.version = 1;
+	payload.type = 1; /* shutdown */
+	payload.gos_id = 0; /* self */
+
 	return ps3_sys_manager_write(dev, &header, &payload);
 }
 
@@ -323,15 +360,10 @@
  * failure of a command sent by the system manager.
  */
 
-static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev,
 	u64 status)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_RESPONSE,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 reserved_1[3];
@@ -344,6 +376,12 @@
 	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
 		(status ? "nak" : "ack"));
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_RESPONSE;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 1;
 	payload.status = status;
@@ -356,7 +394,7 @@
  *
  */
 
-static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct {
@@ -370,7 +408,7 @@
 	BUILD_BUG_ON(sizeof(event) != 16);
 
 	result = ps3_vuart_read(dev, &event, sizeof(event));
-	BUG_ON(result);
+	BUG_ON(result && "need to retry here");
 
 	if (event.version != 1) {
 		dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
@@ -382,11 +420,34 @@
 	case PS3_SM_EVENT_POWER_PRESSED:
 		dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
 			__func__, __LINE__);
+		ps3_sm_force_power_off = 1;
+		/*
+		 * A memory barrier is use here to sync memory since
+		 * ps3_sys_manager_final_restart() could be called on
+		 * another cpu.
+		 */
+		wmb();
+		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
 		break;
 	case PS3_SM_EVENT_POWER_RELEASED:
 		dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
 			__func__, __LINE__, event.value);
-		kill_cad_pid(SIGINT, 1);
+		break;
+	case PS3_SM_EVENT_RESET_PRESSED:
+		dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n",
+			__func__, __LINE__);
+		ps3_sm_force_power_off = 0;
+		/*
+		 * A memory barrier is use here to sync memory since
+		 * ps3_sys_manager_final_restart() could be called on
+		 * another cpu.
+		 */
+		wmb();
+		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
+		break;
+	case PS3_SM_EVENT_RESET_RELEASED:
+		dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
+			__func__, __LINE__, event.value);
 		break;
 	case PS3_SM_EVENT_THERMAL_ALERT:
 		dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
@@ -411,7 +472,7 @@
  * The system manager sends this in reply to a 'request' message from the guest.
  */
 
-static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct {
@@ -425,6 +486,7 @@
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
 	result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+	BUG_ON(result && "need to retry here");
 
 	if(result)
 		return result;
@@ -448,9 +510,10 @@
 /**
  * ps3_sys_manager_handle_msg - First stage msg handler.
  *
+ * Can be called directly to manually poll vuart and pump message handler.
  */
 
-static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct ps3_sys_manager_header header;
@@ -464,12 +527,17 @@
 	if (header.version != 1) {
 		dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
 			__func__, __LINE__, header.version);
+		dump_sm_header(&header);
 		goto fail_header;
 	}
 
 	BUILD_BUG_ON(sizeof(header) != 16);
-	BUG_ON(header.size != 16);
-	BUG_ON(header.payload_size != 16);
+
+	if (header.size != 16 || (header.payload_size != 8
+		&& header.payload_size != 16)) {
+		dump_sm_header(&header);
+		BUG();
+	}
 
 	switch (header.service_id) {
 	case PS3_SM_SERVICE_ID_EXTERN_EVENT:
@@ -478,6 +546,11 @@
 	case PS3_SM_SERVICE_ID_COMMAND:
 		dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
 		return ps3_sys_manager_handle_cmd(dev);
+	case PS3_SM_SERVICE_ID_REQUEST_ERROR:
+		dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
+			__LINE__);
+		dump_sm_header(&header);
+		break;
 	default:
 		dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
 			__func__, __LINE__, header.service_id);
@@ -494,69 +567,19 @@
 }
 
 /**
- * ps3_sys_manager_work - Asyncronous read handler.
+ * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
  *
- * Signaled when a complete message arrives at the vuart port.
- */
-
-static void ps3_sys_manager_work(struct work_struct *work)
-{
-	struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
-
-	ps3_sys_manager_handle_msg(dev);
-	ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
-}
-
-struct {
-	struct ps3_vuart_port_device *dev;
-} static drv_priv;
-
-/**
- * ps3_sys_manager_restart - The final platform machine_restart routine.
- *
- * This routine never returns.  The routine disables asyncronous vuart reads
+ * This routine never returns.  The routine disables asynchronous vuart reads
  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
  * the shutdown command sent from the system manager.  Soon after the
  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_restart().
+ * should only be called from ps3_power_off() through
+ * ps3_sys_manager_ops.power_off.
  */
 
-void ps3_sys_manager_restart(void)
+static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
 {
-	struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-	BUG_ON(!drv_priv.dev);
-
-	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
-
-	ps3_vuart_cancel_async(dev);
-
-	ps3_sys_manager_send_attr(dev, 0);
-	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
-		PS3_SM_WAKE_DEFAULT);
-	ps3_sys_manager_send_request_shutdown(dev);
-
-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
-
-	while(1)
-		ps3_sys_manager_handle_msg(dev);
-}
-
-/**
- * ps3_sys_manager_power_off - The final platform machine_power_off routine.
- *
- * This routine never returns.  The routine disables asyncronous vuart reads
- * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
- * the shutdown command sent from the system manager.  Soon after the
- * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_power_off().
- */
-
-void ps3_sys_manager_power_off(void)
-{
-	struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-	BUG_ON(!drv_priv.dev);
+	BUG_ON(!dev);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
@@ -572,31 +595,97 @@
 		ps3_sys_manager_handle_msg(dev);
 }
 
-static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+/**
+ * ps3_sys_manager_final_restart - The final platform machine_restart routine.
+ *
+ * This routine never returns.  The routine disables asynchronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager.  Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV.  This routine
+ * should only be called from ps3_restart() through ps3_sys_manager_ops.restart.
+ */
+
+static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
 {
-	int result;
+	BUG_ON(!dev);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	BUG_ON(drv_priv.dev);
-	drv_priv.dev = dev;
+	/* Check if we got here via a power button event. */
+
+	if (ps3_sm_force_power_off) {
+		dev_dbg(&dev->core, "%s:%d: forcing poweroff\n",
+			__func__, __LINE__);
+		ps3_sys_manager_final_power_off(dev);
+	}
+
+	ps3_vuart_cancel_async(dev);
+
+	ps3_sys_manager_send_attr(dev, 0);
+	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+		PS3_SM_WAKE_DEFAULT);
+	ps3_sys_manager_send_request_shutdown(dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+	while(1)
+		ps3_sys_manager_handle_msg(dev);
+}
+
+/**
+ * ps3_sys_manager_work - Asynchronous read handler.
+ *
+ * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
+{
+	ps3_sys_manager_handle_msg(dev);
+	ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
+}
+
+static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
+{
+	int result;
+	struct ps3_sys_manager_ops ops;
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	ops.power_off = ps3_sys_manager_final_power_off;
+	ops.restart = ps3_sys_manager_final_restart;
+	ops.dev = dev;
+
+	/* ps3_sys_manager_register_ops copies ops. */
+
+	ps3_sys_manager_register_ops(&ops);
 
 	result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
 	BUG_ON(result);
 
-	result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
-		PS3_SM_RX_MSG_LEN);
+	result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
 	BUG_ON(result);
 
 	return result;
 }
 
+static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev)
+{
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev)
+{
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+}
+
 static struct ps3_vuart_port_driver ps3_sys_manager = {
-	.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
-	.core = {
-		.name = "ps3_sys_manager",
-	},
+	.core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+	.core.core.name = "ps3_sys_manager",
 	.probe = ps3_sys_manager_probe,
+	.remove = ps3_sys_manager_remove,
+	.shutdown = ps3_sys_manager_shutdown,
+	.work = ps3_sys_manager_work,
 };
 
 static int __init ps3_sys_manager_init(void)
@@ -608,3 +697,6 @@
 }
 
 module_init(ps3_sys_manager_init);
+/* Module remove not supported. */
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER);
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index ec2d36a..bea25a1 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -71,6 +71,34 @@
 };
 
 /**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+	u64 interrupt_mask;
+
+	struct {
+		spinlock_t lock;
+		struct list_head head;
+	} tx_list;
+	struct {
+		struct ps3_vuart_work work;
+		unsigned long bytes_held;
+		spinlock_t lock;
+		struct list_head head;
+	} rx_list;
+	struct ps3_vuart_stats stats;
+};
+
+static struct ps3_vuart_port_priv *to_port_priv(
+	struct ps3_system_bus_device *dev)
+{
+	BUG_ON(!dev);
+	BUG_ON(!dev->driver_priv);
+	return (struct ps3_vuart_port_priv *)dev->driver_priv;
+}
+
+/**
  * struct ports_bmp - bitmap indicating ports needing service.
  *
  * A 256 bit read only bitmap indicating ports needing service.  Do not write
@@ -83,31 +111,14 @@
 } __attribute__ ((aligned (32)));
 
 #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_ports_bmp(
+static void __maybe_unused _dump_ports_bmp(
 	const struct ports_bmp* bmp, const char* func, int line)
 {
 	pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
 }
 
-static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
-	unsigned int *port_number)
-{
-	switch(match_id) {
-	case PS3_MATCH_ID_AV_SETTINGS:
-		*port_number = 0;
-		return 0;
-	case PS3_MATCH_ID_SYSTEM_MANAGER:
-		*port_number = 2;
-		return 0;
-	default:
-		WARN_ON(1);
-		*port_number = UINT_MAX;
-		return -EINVAL;
-	};
-}
-
 #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+static void __maybe_unused _dump_port_params(unsigned int port_number,
 	const char* func, int line)
 {
 #if defined(DEBUG)
@@ -144,14 +155,14 @@
 	unsigned long tx;
 };
 
-int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
 	struct vuart_triggers *trig)
 {
 	int result;
 	unsigned long size;
 	unsigned long val;
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_TX_TRIGGER, &trig->tx);
 
 	if (result) {
@@ -160,7 +171,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -169,7 +180,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_TRIGGER, &val);
 
 	if (result) {
@@ -186,13 +197,13 @@
 	return result;
 }
 
-int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
 	unsigned int rx)
 {
 	int result;
 	unsigned long size;
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
+	result = lv1_set_virtual_uart_param(dev->port_number,
 		PARAM_TX_TRIGGER, tx);
 
 	if (result) {
@@ -201,7 +212,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -210,7 +221,7 @@
 		return result;
 	}
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
+	result = lv1_set_virtual_uart_param(dev->port_number,
 		PARAM_RX_TRIGGER, size - rx);
 
 	if (result) {
@@ -225,10 +236,12 @@
 	return result;
 }
 
-static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
 	u64 *bytes_waiting)
 {
-	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	int result;
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BYTES, bytes_waiting);
 
 	if (result)
@@ -240,17 +253,24 @@
 	return result;
 }
 
-static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+/**
+ * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
+ */
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
 	unsigned long mask)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
 	dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
 
-	dev->priv->interrupt_mask = mask;
+	priv->interrupt_mask = mask;
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
-		PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
+	result = lv1_set_virtual_uart_param(dev->port_number,
+		PARAM_INTERRUPT_MASK, priv->interrupt_mask);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -259,79 +279,96 @@
 	return result;
 }
 
-static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
 	unsigned long *status)
 {
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	u64 tmp;
-	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_INTERRUPT_STATUS, &tmp);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	*status = tmp & dev->priv->interrupt_mask;
+	*status = tmp & priv->interrupt_mask;
 
 	dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
-		__func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
+		__func__, __LINE__, priv->interrupt_mask, tmp, *status);
 
 	return result;
 }
 
-int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_TX);
 }
 
-int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_RX);
 }
 
-int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_DISCONNECT);
 }
 
-int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_TX)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_TX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_RX)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_RX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_DISCONNECT) : 0;
 }
 
 /**
  * ps3_vuart_raw_write - Low level write helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
  */
 
-static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
 	const void* buf, unsigned int bytes, unsigned long *bytes_written)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
-	result = lv1_write_virtual_uart(dev->priv->port_number,
+	result = lv1_write_virtual_uart(dev->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
 
 	if (result) {
@@ -340,28 +377,30 @@
 		return result;
 	}
 
-	dev->priv->stats.bytes_written += *bytes_written;
+	priv->stats.bytes_written += *bytes_written;
 
 	dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
-		*bytes_written, bytes, dev->priv->stats.bytes_written);
+		*bytes_written, bytes, priv->stats.bytes_written);
 
 	return result;
 }
 
 /**
  * ps3_vuart_raw_read - Low level read helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
  */
 
-static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes, unsigned long *bytes_read)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
 
-	result = lv1_read_virtual_uart(dev->priv->port_number,
+	result = lv1_read_virtual_uart(dev->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
 
 	if (result) {
@@ -370,25 +409,27 @@
 		return result;
 	}
 
-	dev->priv->stats.bytes_read += *bytes_read;
+	priv->stats.bytes_read += *bytes_read;
 
 	dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
-		*bytes_read, bytes, dev->priv->stats.bytes_read);
+		*bytes_read, bytes, priv->stats.bytes_read);
 
 	return result;
 }
 
 /**
  * ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @dev: The struct ps3_system_bus_device instance.
  * @bytes: Max byte count to discard, zero = all pending.
  *
  * Used to clear pending rx interrupt source.  Will not block.
  */
 
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
 	unsigned int bytes)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	u64 bytes_waiting;
 	void* tmp;
 
@@ -418,8 +459,9 @@
 
 	/* Don't include these bytes in the stats. */
 
-	dev->priv->stats.bytes_read -= bytes_waiting;
+	priv->stats.bytes_read -= bytes_waiting;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
 
 /**
  * struct list_buffer - An element for a port device fifo buffer list.
@@ -435,6 +477,7 @@
 
 /**
  * ps3_vuart_write - the entry point for writing data to a port
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * If the port is idle on entry as much of the incoming data is written to
  * the port as the port will accept.  Otherwise a list buffer is created
@@ -442,25 +485,26 @@
  * then enqueued for transmision via the transmit interrupt.
  */
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
 	unsigned int bytes)
 {
 	static unsigned long dbg_number;
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb;
 
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-	if (list_empty(&dev->priv->tx_list.head)) {
+	if (list_empty(&priv->tx_list.head)) {
 		unsigned long bytes_written;
 
 		result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
 
-		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+		spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 		if (result) {
 			dev_dbg(&dev->core,
@@ -478,7 +522,7 @@
 		bytes -= bytes_written;
 		buf += bytes_written;
 	} else
-		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+		spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
 
@@ -491,29 +535,86 @@
 	lb->tail = lb->data + bytes;
 	lb->dbg_number = ++dbg_number;
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->priv->tx_list.head);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
+	list_add_tail(&lb->link, &priv->tx_list.head);
 	ps3_vuart_enable_interrupt_tx(dev);
-	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
 		__func__, __LINE__, lb->dbg_number, bytes);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_write);
 
 /**
- * ps3_vuart_read - the entry point for reading data from a port
+ * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bytes_queued: Number of bytes queued to the buffer list.
  *
- * If enough bytes to satisfy the request are held in the buffer list those
- * bytes are dequeued and copied to the caller's buffer.  Emptied list buffers
- * are retiered.  If the request cannot be statified by bytes held in the list
- * buffers -EAGAIN is returned.
+ * Must be called with priv->rx_list.lock held.
  */
 
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
+	u64 *bytes_queued)
+{
+	static unsigned long dbg_number;
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+	struct list_buffer *lb;
+	u64 bytes;
+
+	*bytes_queued = 0;
+
+	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+	BUG_ON(result);
+
+	if (result)
+		return -EIO;
+
+	if (!bytes)
+		return 0;
+
+	/* Add some extra space for recently arrived data. */
+
+	bytes += 128;
+
+	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+	if (!lb)
+		return -ENOMEM;
+
+	ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+	lb->head = lb->data;
+	lb->tail = lb->data + bytes;
+	lb->dbg_number = ++dbg_number;
+
+	list_add_tail(&lb->link, &priv->rx_list.head);
+	priv->rx_list.bytes_held += bytes;
+
+	dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
+		__func__, __LINE__, lb->dbg_number, bytes);
+
+	*bytes_queued = bytes;
+
+	return 0;
+}
+
+/**
+ * ps3_vuart_read - The entry point for reading data from a port.
+ *
+ * Queue data waiting at the port, and if enough bytes to satisfy the request
+ * are held in the buffer list those bytes are dequeued and copied to the
+ * caller's buffer.  Emptied list buffers are retiered.  If the request cannot
+ * be statified by bytes held in the list buffers -EAGAIN is returned.
+ */
+
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes)
 {
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb, *n;
 	unsigned long bytes_read;
@@ -521,30 +622,37 @@
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
 
-	if (dev->priv->rx_list.bytes_held < bytes) {
-		spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-		dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
-			__func__, __LINE__,
-			bytes - dev->priv->rx_list.bytes_held);
-		return -EAGAIN;
+	/* Queue rx bytes here for polled reads. */
+
+	while (priv->rx_list.bytes_held < bytes) {
+		u64 tmp;
+
+		result = ps3_vuart_queue_rx_bytes(dev, &tmp);
+		if (result || !tmp) {
+			dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+				__func__, __LINE__,
+				bytes - priv->rx_list.bytes_held);
+			spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+			return -EAGAIN;
+		}
 	}
 
-	list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
 		bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
 
 		memcpy(buf, lb->head, bytes_read);
 		buf += bytes_read;
 		bytes -= bytes_read;
-		dev->priv->rx_list.bytes_held -= bytes_read;
+		priv->rx_list.bytes_held -= bytes_read;
 
 		if (bytes_read < lb->tail - lb->head) {
 			lb->head += bytes_read;
 			dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
 				"bytes\n", __func__, __LINE__, lb->dbg_number,
 				bytes_read);
-			spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+			spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 			return 0;
 		}
 
@@ -556,16 +664,32 @@
 		kfree(lb);
 	}
 
-	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read);
 
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
-	unsigned int bytes)
+/**
+ * ps3_vuart_work - Asynchronous read handler.
+ */
+
+static void ps3_vuart_work(struct work_struct *work)
 {
+	struct ps3_system_bus_device *dev =
+		ps3_vuart_work_to_system_bus_dev(work);
+	struct ps3_vuart_port_driver *drv =
+		ps3_system_bus_dev_to_vuart_drv(dev);
+
+	BUG_ON(!drv);
+	drv->work(dev);
+}
+
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
+{
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 
-	if(dev->priv->work.trigger) {
+	if (priv->rx_list.work.trigger) {
 		dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
 			__func__, __LINE__);
 		return -EAGAIN;
@@ -573,30 +697,32 @@
 
 	BUG_ON(!bytes);
 
-	PREPARE_WORK(&dev->priv->work.work, func);
+	PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
 
-	spin_lock_irqsave(&dev->priv->work.lock, flags);
-	if(dev->priv->rx_list.bytes_held >= bytes) {
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
+	if (priv->rx_list.bytes_held >= bytes) {
 		dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
 			__func__, __LINE__, bytes);
-		schedule_work(&dev->priv->work.work);
-		spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+		schedule_work(&priv->rx_list.work.work);
+		spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 		return 0;
 	}
 
-	dev->priv->work.trigger = bytes;
-	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+	priv->rx_list.work.trigger = bytes;
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 
 	dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
 		__LINE__, bytes, bytes);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
 
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
 {
-	dev->priv->work.trigger = 0;
+	to_port_priv(dev)->rx_list.work.trigger = 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
 
 /**
  * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
@@ -606,18 +732,19 @@
  * adjusts the final list buffer state for a partial write.
  */
 
-static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
 {
 	int result = 0;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb, *n;
 	unsigned long bytes_total = 0;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-	list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
 
 		unsigned long bytes_written;
 
@@ -651,7 +778,7 @@
 
 	ps3_vuart_disable_interrupt_tx(dev);
 port_full:
-	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 	dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
 		__func__, __LINE__, bytes_total);
 	return result;
@@ -665,60 +792,37 @@
  * buffer list.  Buffer list data is dequeued via ps3_vuart_read.
  */
 
-static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	static unsigned long dbg_number;
-	int result = 0;
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
-	struct list_buffer *lb;
-	unsigned long bytes;
+	u64 bytes;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
+	result = ps3_vuart_queue_rx_bytes(dev, &bytes);
 
-	if (result)
-		return -EIO;
-
-	BUG_ON(!bytes);
-
-	/* Add some extra space for recently arrived data. */
-
-	bytes += 128;
-
-	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
-
-	if (!lb)
-		return -ENOMEM;
-
-	ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
-
-	lb->head = lb->data;
-	lb->tail = lb->data + bytes;
-	lb->dbg_number = ++dbg_number;
-
-	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->priv->rx_list.head);
-	dev->priv->rx_list.bytes_held += bytes;
-	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-
-	dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
-		__func__, __LINE__, lb->dbg_number, bytes);
-
-	spin_lock_irqsave(&dev->priv->work.lock, flags);
-	if(dev->priv->work.trigger
-		&& dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
-		dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
-			__func__, __LINE__, dev->priv->work.trigger);
-		dev->priv->work.trigger = 0;
-		schedule_work(&dev->priv->work.work);
+	if (result) {
+		spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+		return result;
 	}
-	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
-	return 0;
+
+	if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
+		>= priv->rx_list.work.trigger) {
+		dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
+			__func__, __LINE__, priv->rx_list.work.trigger);
+		priv->rx_list.work.trigger = 0;
+		schedule_work(&priv->rx_list.work.work);
+	}
+
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+	return result;
 }
 
 static int ps3_vuart_handle_interrupt_disconnect(
-	struct ps3_vuart_port_device *dev)
+	struct ps3_system_bus_device *dev)
 {
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 	BUG_ON("no support");
@@ -733,9 +837,10 @@
  * stage handler after one iteration.
  */
 
-static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long status;
 
 	result = ps3_vuart_get_interrupt_status(dev, &status);
@@ -747,21 +852,21 @@
 		status);
 
 	if (status & INTERRUPT_MASK_DISCONNECT) {
-		dev->priv->stats.disconnect_interrupts++;
+		priv->stats.disconnect_interrupts++;
 		result = ps3_vuart_handle_interrupt_disconnect(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_disconnect(dev);
 	}
 
 	if (status & INTERRUPT_MASK_TX) {
-		dev->priv->stats.tx_interrupts++;
+		priv->stats.tx_interrupts++;
 		result = ps3_vuart_handle_interrupt_tx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_tx(dev);
 	}
 
 	if (status & INTERRUPT_MASK_RX) {
-		dev->priv->stats.rx_interrupts++;
+		priv->stats.rx_interrupts++;
 		result = ps3_vuart_handle_interrupt_rx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_rx(dev);
@@ -771,11 +876,11 @@
 }
 
 struct vuart_bus_priv {
-	const struct ports_bmp bmp;
+	struct ports_bmp *bmp;
 	unsigned int virq;
 	struct semaphore probe_mutex;
 	int use_count;
-	struct ps3_vuart_port_device *devices[PORT_COUNT];
+	struct ps3_system_bus_device *devices[PORT_COUNT];
 } static vuart_bus_priv;
 
 /**
@@ -788,17 +893,16 @@
 
 static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
 {
-	struct vuart_bus_priv *bus_priv;
+	struct vuart_bus_priv *bus_priv = _private;
 
-	BUG_ON(!_private);
-	bus_priv = (struct vuart_bus_priv *)_private;
+	BUG_ON(!bus_priv);
 
 	while (1) {
 		unsigned int port;
 
-		dump_ports_bmp(&bus_priv->bmp);
+		dump_ports_bmp(bus_priv->bmp);
 
-		port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
+		port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
 
 		if (port == BITS_PER_LONG)
 			break;
@@ -812,100 +916,144 @@
 	return IRQ_HANDLED;
 }
 
-static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+static int ps3_vuart_bus_interrupt_get(void)
 {
 	int result;
-	struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
 
-	result = dev->match_id == drv->match_id;
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 
-	dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
-		__LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
-		drv->core.name, (result ? "match" : "miss"));
+	vuart_bus_priv.use_count++;
 
+	BUG_ON(vuart_bus_priv.use_count > 2);
+
+	if (vuart_bus_priv.use_count != 1) {
+		return 0;
+	}
+
+	BUG_ON(vuart_bus_priv.bmp);
+
+	vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
+
+	if (!vuart_bus_priv.bmp) {
+		pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
+		result = -ENOMEM;
+		goto fail_bmp_malloc;
+	}
+
+	result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
+		&vuart_bus_priv.virq);
+
+	if (result) {
+		pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
+			__func__, __LINE__, result);
+		result = -EPERM;
+		goto fail_alloc_irq;
+	}
+
+	result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+		IRQF_DISABLED, "vuart", &vuart_bus_priv);
+
+	if (result) {
+		pr_debug("%s:%d: request_irq failed (%d)\n",
+			__func__, __LINE__, result);
+		goto fail_request_irq;
+	}
+
+	pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
+	return result;
+
+fail_request_irq:
+	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+	vuart_bus_priv.virq = NO_IRQ;
+fail_alloc_irq:
+	kfree(vuart_bus_priv.bmp);
+	vuart_bus_priv.bmp = NULL;
+fail_bmp_malloc:
+	vuart_bus_priv.use_count--;
+	pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
 	return result;
 }
 
-static int ps3_vuart_probe(struct device *_dev)
+static int ps3_vuart_bus_interrupt_put(void)
+{
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	vuart_bus_priv.use_count--;
+
+	BUG_ON(vuart_bus_priv.use_count < 0);
+
+	if (vuart_bus_priv.use_count != 0)
+		return 0;
+
+	free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+
+	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+	vuart_bus_priv.virq = NO_IRQ;
+
+	kfree(vuart_bus_priv.bmp);
+	vuart_bus_priv.bmp = NULL;
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
-	unsigned int port_number;
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
+	struct ps3_vuart_port_driver *drv;
+	struct ps3_vuart_port_priv *priv = NULL;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+		drv->core.core.name);
+
 	BUG_ON(!drv);
 
+	if (dev->port_number >= PORT_COUNT) {
+		BUG();
+		return -EINVAL;
+	}
+
 	down(&vuart_bus_priv.probe_mutex);
 
-	/* Setup vuart_bus_priv.devices[]. */
+	result = ps3_vuart_bus_interrupt_get();
 
-	result = ps3_vuart_match_id_to_port(dev->match_id,
-		&port_number);
+	if (result)
+		goto fail_setup_interrupt;
 
-	if (result) {
-		dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
-			__func__, __LINE__, dev->match_id);
-		result = -EINVAL;
-		goto fail_match;
-	}
-
-	if (vuart_bus_priv.devices[port_number]) {
+	if (vuart_bus_priv.devices[dev->port_number]) {
 		dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
-			__LINE__, port_number);
+			__LINE__, dev->port_number);
 		result = -EBUSY;
-		goto fail_match;
+		goto fail_busy;
 	}
 
-	vuart_bus_priv.devices[port_number] = dev;
+	vuart_bus_priv.devices[dev->port_number] = dev;
 
-	/* Setup dev->priv. */
+	/* Setup dev->driver_priv. */
 
-	dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+	dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
+		GFP_KERNEL);
 
-	if (!dev->priv) {
+	if (!dev->driver_priv) {
 		result = -ENOMEM;
-		goto fail_alloc;
+		goto fail_dev_malloc;
 	}
 
-	dev->priv->port_number = port_number;
+	priv = to_port_priv(dev);
 
-	INIT_LIST_HEAD(&dev->priv->tx_list.head);
-	spin_lock_init(&dev->priv->tx_list.lock);
+	INIT_LIST_HEAD(&priv->tx_list.head);
+	spin_lock_init(&priv->tx_list.lock);
 
-	INIT_LIST_HEAD(&dev->priv->rx_list.head);
-	spin_lock_init(&dev->priv->rx_list.lock);
+	INIT_LIST_HEAD(&priv->rx_list.head);
+	spin_lock_init(&priv->rx_list.lock);
 
-	INIT_WORK(&dev->priv->work.work, NULL);
-	spin_lock_init(&dev->priv->work.lock);
-	dev->priv->work.trigger = 0;
-	dev->priv->work.dev = dev;
-
-	if (++vuart_bus_priv.use_count == 1) {
-
-		result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY,
-			(void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
-
-		if (result) {
-			dev_dbg(&dev->core,
-				"%s:%d: ps3_vuart_irq_setup failed (%d)\n",
-				__func__, __LINE__, result);
-			result = -EPERM;
-			goto fail_alloc_irq;
-		}
-
-		result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
-			IRQF_DISABLED, "vuart", &vuart_bus_priv);
-
-		if (result) {
-			dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
-				__func__, __LINE__, result);
-			goto fail_request_irq;
-		}
-	}
+	INIT_WORK(&priv->rx_list.work.work, NULL);
+	priv->rx_list.work.trigger = 0;
+	priv->rx_list.work.dev = dev;
 
 	/* clear stale pending interrupts */
 
@@ -936,152 +1084,160 @@
 
 fail_probe:
 	ps3_vuart_set_interrupt_mask(dev, 0);
-fail_request_irq:
-	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-	vuart_bus_priv.virq = NO_IRQ;
-fail_alloc_irq:
-	--vuart_bus_priv.use_count;
-	kfree(dev->priv);
-	dev->priv = NULL;
-fail_alloc:
-	vuart_bus_priv.devices[port_number] = NULL;
-fail_match:
+	kfree(dev->driver_priv);
+	dev->driver_priv = NULL;
+fail_dev_malloc:
+	vuart_bus_priv.devices[dev->port_number] = NULL;
+fail_busy:
+	ps3_vuart_bus_interrupt_put();
+fail_setup_interrupt:
 	up(&vuart_bus_priv.probe_mutex);
-	dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+	dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
 	return result;
 }
 
-static int ps3_vuart_remove(struct device *_dev)
+/**
+ * ps3_vuart_cleanup - common cleanup helper.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans interrupts and HV resources.  Must be called with
+ * vuart_bus_priv.probe_mutex held.  Used by ps3_vuart_remove and
+ * ps3_vuart_shutdown.  After this call, polled reading will still work.
+ */
+
+static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
 {
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	ps3_vuart_cancel_async(dev);
+	ps3_vuart_set_interrupt_mask(dev, 0);
+	ps3_vuart_bus_interrupt_put();
+	return 0;
+}
+
+/**
+ * ps3_vuart_remove - Completely clean the device instance.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans all memory, interrupts and HV resources.  After this call the
+ * device can no longer be used.
+ */
+
+static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
+{
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+	struct ps3_vuart_port_driver *drv;
+
+	BUG_ON(!dev);
 
 	down(&vuart_bus_priv.probe_mutex);
 
-	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-		dev->core.bus_id);
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
 
-	BUG_ON(vuart_bus_priv.use_count < 1);
-
-	if (drv->remove)
-		drv->remove(dev);
-	else
-		dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
-			__LINE__, dev->core.bus_id);
-
-	vuart_bus_priv.devices[dev->priv->port_number] = NULL;
-
-	if (--vuart_bus_priv.use_count == 0) {
-		BUG();
-		free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
-		ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-		vuart_bus_priv.virq = NO_IRQ;
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		up(&vuart_bus_priv.probe_mutex);
+		return 0;
 	}
 
-	kfree(dev->priv);
-	dev->priv = NULL;
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+	BUG_ON(!drv);
+
+	if (drv->remove) {
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
+		__LINE__);
+		BUG();
+	}
+
+	ps3_vuart_cleanup(dev);
+
+	vuart_bus_priv.devices[dev->port_number] = NULL;
+	kfree(priv);
+	priv = NULL;
+
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+	up(&vuart_bus_priv.probe_mutex);
+	return 0;
+}
+
+/**
+ * ps3_vuart_shutdown - Cleans interrupts and HV resources.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans interrupts and HV resources.  After this call the
+ * device can still be used in polling mode.  This behavior required
+ * by sys-manager to be able to complete the device power operation
+ * sequence.
+ */
+
+static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
+{
+	struct ps3_vuart_port_driver *drv;
+
+	BUG_ON(!dev);
+
+	down(&vuart_bus_priv.probe_mutex);
+
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
+
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		up(&vuart_bus_priv.probe_mutex);
+		return 0;
+	}
+
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+	BUG_ON(!drv);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+	else if (drv->remove) {
+		dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
+			__func__, __LINE__);
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
+			__LINE__);
+		BUG();
+	}
+
+	ps3_vuart_cleanup(dev);
+
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
 	up(&vuart_bus_priv.probe_mutex);
 	return 0;
 }
 
-static void ps3_vuart_shutdown(struct device *_dev)
+static int __init ps3_vuart_bus_init(void)
 {
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
-
-	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-		dev->core.bus_id);
-
-	if (drv->shutdown)
-		drv->shutdown(dev);
-	else
-		dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
-			__LINE__, dev->core.bus_id);
-}
-
-/**
- * ps3_vuart_bus - The vuart bus instance.
- *
- * The vuart is managed as a bus that port devices connect to.
- */
-
-struct bus_type ps3_vuart_bus = {
-        .name = "ps3_vuart",
-	.match = ps3_vuart_match,
-	.probe = ps3_vuart_probe,
-	.remove = ps3_vuart_remove,
-	.shutdown = ps3_vuart_shutdown,
-};
-
-int __init ps3_vuart_bus_init(void)
-{
-	int result;
-
 	pr_debug("%s:%d:\n", __func__, __LINE__);
 
 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 		return -ENODEV;
 
 	init_MUTEX(&vuart_bus_priv.probe_mutex);
-	result = bus_register(&ps3_vuart_bus);
-	BUG_ON(result);
 
-	return result;
+	return 0;
 }
 
-void __exit ps3_vuart_bus_exit(void)
+static void __exit ps3_vuart_bus_exit(void)
 {
 	pr_debug("%s:%d:\n", __func__, __LINE__);
-	bus_unregister(&ps3_vuart_bus);
 }
 
 core_initcall(ps3_vuart_bus_init);
 module_exit(ps3_vuart_bus_exit);
 
 /**
- * ps3_vuart_port_release_device - Remove a vuart port device.
- */
-
-static void ps3_vuart_port_release_device(struct device *_dev)
-{
-#if defined(DEBUG)
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-
-	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
-
-	BUG_ON(dev->priv && "forgot to free");
-	memset(&dev->core, 0, sizeof(dev->core));
-#endif
-}
-
-/**
- * ps3_vuart_port_device_register - Add a vuart port device.
- */
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
-{
-	static unsigned int dev_count = 1;
-
-	BUG_ON(dev->priv && "forgot to free");
-
-	dev->core.parent = NULL;
-	dev->core.bus = &ps3_vuart_bus;
-	dev->core.release = ps3_vuart_port_release_device;
-
-	snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
-		dev_count++);
-
-	dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
-
-	return device_register(&dev->core);
-}
-
-EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
-
-/**
  * ps3_vuart_port_driver_register - Add a vuart port device driver.
  */
 
@@ -1089,12 +1245,18 @@
 {
 	int result;
 
-	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-	drv->core.bus = &ps3_vuart_bus;
-	result = driver_register(&drv->core);
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+
+	BUG_ON(!drv->core.match_id);
+	BUG_ON(!drv->core.core.name);
+
+	drv->core.probe = ps3_vuart_probe;
+	drv->core.remove = ps3_vuart_remove;
+	drv->core.shutdown = ps3_vuart_shutdown;
+
+	result = ps3_system_bus_driver_register(&drv->core);
 	return result;
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
 
 /**
@@ -1103,8 +1265,7 @@
 
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
 {
-	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-	driver_unregister(&drv->core);
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+	ps3_system_bus_driver_unregister(&drv->core);
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 1be992d..eb7f6d9 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -34,29 +34,7 @@
 struct ps3_vuart_work {
 	struct work_struct work;
 	unsigned long trigger;
-	spinlock_t lock;
-	struct ps3_vuart_port_device* dev; /* to convert work to device */
-};
-
-/**
- * struct ps3_vuart_port_priv - private vuart device data.
- */
-
-struct ps3_vuart_port_priv {
-	unsigned int port_number;
-	u64 interrupt_mask;
-
-	struct {
-		spinlock_t lock;
-		struct list_head head;
-	} tx_list;
-	struct {
-		unsigned long bytes_held;
-		spinlock_t lock;
-		struct list_head head;
-	} rx_list;
-	struct ps3_vuart_stats stats;
-	struct ps3_vuart_work work;
+	struct ps3_system_bus_device *dev; /* to convert work to device */
 };
 
 /**
@@ -64,32 +42,30 @@
  */
 
 struct ps3_vuart_port_driver {
-	enum ps3_match_id match_id;
-	struct device_driver core;
-	int (*probe)(struct ps3_vuart_port_device *);
-	int (*remove)(struct ps3_vuart_port_device *);
-	void (*shutdown)(struct ps3_vuart_port_device *);
-	int (*tx_event)(struct ps3_vuart_port_device *dev);
-	int (*rx_event)(struct ps3_vuart_port_device *dev);
-	int (*disconnect_event)(struct ps3_vuart_port_device *dev);
-	/* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
-	/* int (*resume)(struct ps3_vuart_port_device *); */
+	struct ps3_system_bus_driver core;
+	int (*probe)(struct ps3_system_bus_device *);
+	int (*remove)(struct ps3_system_bus_device *);
+	void (*shutdown)(struct ps3_system_bus_device *);
+	void (*work)(struct ps3_system_bus_device *);
+	/* int (*tx_event)(struct ps3_system_bus_device *dev); */
+	/* int (*rx_event)(struct ps3_system_bus_device *dev); */
+	/* int (*disconnect_event)(struct ps3_system_bus_device *dev); */
+	/* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
+	/* int (*resume)(struct ps3_system_bus_device *); */
 };
 
 int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
 
-static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
-	struct device_driver *_drv)
+static inline struct ps3_vuart_port_driver *
+	ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev)
 {
-	return container_of(_drv, struct ps3_vuart_port_driver, core);
+	struct ps3_system_bus_driver *sbd =
+		ps3_system_bus_dev_to_system_bus_drv(_dev);
+	BUG_ON(!sbd);
+	return container_of(sbd, struct ps3_vuart_port_driver, core);
 }
-static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
-	struct device *_dev)
-{
-	return container_of(_dev, struct ps3_vuart_port_device, core);
-}
-static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev(
 	struct work_struct *_work)
 {
 	struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
@@ -97,14 +73,13 @@
 	return vw->dev;
 }
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
 	unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes);
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
-	unsigned int bytes);
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
 	unsigned int bytes);
 
 #endif
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4e4c10a..cea401f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -10,7 +10,6 @@
 
 config RTC_CLASS
 	tristate "RTC class"
-	depends on EXPERIMENTAL
 	default n
 	select RTC_LIB
 	help
@@ -119,7 +118,7 @@
 	  will be called rtc-test.
 
 comment "I2C RTC drivers"
-	depends on RTC_CLASS
+	depends on RTC_CLASS && I2C
 
 config RTC_DRV_DS1307
 	tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00"
@@ -160,11 +159,11 @@
 	  will be called rtc-max6900.
 
 config RTC_DRV_RS5C372
-	tristate "Ricoh RS5C372A/B"
+	tristate "Ricoh RS5C372A/B, RV5C386, RV5C387A"
 	depends on RTC_CLASS && I2C
 	help
 	  If you say yes here you get support for the
-	  Ricoh RS5C372A and RS5C372B RTC chips.
+	  Ricoh RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-rs5c372.
@@ -213,12 +212,40 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf8583.
 
+config RTC_DRV_M41T80
+	tristate "ST M41T80 series RTC"
+	depends on RTC_CLASS && I2C
+	help
+	  If you say Y here you will get support for the
+	  ST M41T80 RTC chips series. Currently following chips are
+	  supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85
+	  and M41ST87.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-m41t80.
+
+config RTC_DRV_M41T80_WDT
+	bool "ST M41T80 series RTC watchdog timer"
+	depends on RTC_DRV_M41T80
+	help
+	  If you say Y here you will get support for the
+	  watchdog timer in ST M41T80 RTC chips series.
+
+config RTC_DRV_TWL92330
+	boolean "TI TWL92330/Menelaus"
+	depends on RTC_CLASS && I2C && MENELAUS
+	help
+	  If you say yes here you get support for the RTC on the
+	  TWL92330 "Menelaus" power mangement chip, used with OMAP2
+	  platforms.  The support is integrated with the rest of
+	  the Menelaus driver; it's not separate module.
+
 comment "SPI RTC drivers"
-	depends on RTC_CLASS
+	depends on RTC_CLASS && SPI_MASTER
 
 config RTC_DRV_RS5C348
 	tristate "Ricoh RS5C348A/B"
-	depends on RTC_CLASS && SPI
+	depends on RTC_CLASS && SPI_MASTER
 	help
 	  If you say yes here you get support for the
 	  Ricoh RS5C348A and RS5C348B RTC chips.
@@ -228,7 +255,7 @@
 
 config RTC_DRV_MAX6902
 	tristate "Maxim 6902"
-	depends on RTC_CLASS && SPI
+	depends on RTC_CLASS && SPI_MASTER
 	help
 	  If you say yes here you will get support for the
 	  Maxim MAX6902 SPI RTC chip.
@@ -246,7 +273,7 @@
 config RTC_DRV_CMOS
 	tristate "PC-style 'CMOS'"
 	depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
-		|| M32R || ATARI || POWERPC || MIPS)
+		|| M32R || ATARI || PPC || MIPS)
 	help
 	  Say "yes" here to get direct support for the real time clock
 	  found in every PC or ACPI-based system, and some other boards.
@@ -262,6 +289,12 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-cmos.
 
+config RTC_DRV_DS1216
+	tristate "Dallas DS1216"
+	depends on RTC_CLASS && SNI_RM
+	help
+	  If you say yes here you get support for the Dallas DS1216 RTC chips.
+
 config RTC_DRV_DS1553
 	tristate "Dallas DS1553"
 	depends on RTC_CLASS
@@ -292,6 +325,16 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-m48t86.
 
+config RTC_DRV_M48T59
+	tristate "ST M48T59"
+	depends on RTC_CLASS
+	help
+	  If you say Y here you will get support for the
+	  ST M48T59 RTC chip.
+
+	  This driver can also be built as a module, if so, the module
+	  will be called "rtc-m48t59".
+
 config RTC_DRV_V3020
 	tristate "EM Microelectronic V3020"
 	depends on RTC_CLASS
@@ -379,6 +422,13 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rtc-pl031.
 
+config RTC_DRV_AT32AP700X
+	tristate "AT32AP700X series RTC"
+	depends on RTC_CLASS && PLATFORM_AT32AP
+	help
+	  Driver for the internal RTC (Realtime Clock) on Atmel AVR32
+	  AT32AP700x family processors.
+
 config RTC_DRV_AT91RM9200
 	tristate "AT91RM9200"
 	depends on RTC_CLASS && ARCH_AT91RM9200
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index a1afbc2..3109af9 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
+obj-$(CONFIG_RTC_DRV_AT32AP700X)	+= rtc-at32ap700x.o
 obj-$(CONFIG_RTC_DRV_DS1307)	+= rtc-ds1307.o
 obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o
@@ -28,6 +29,7 @@
 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
 obj-$(CONFIG_RTC_DRV_S3C)	+= rtc-s3c.o
 obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o
+obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_DS1553)	+= rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_RS5C313)	+= rtc-rs5c313.o
@@ -41,3 +43,5 @@
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_SH)	+= rtc-sh.o
 obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.o
+obj-$(CONFIG_RTC_DRV_M48T59)	+= rtc-m48t59.o
+obj-$(CONFIG_RTC_DRV_DS1216)	+= rtc-ds1216.o
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
new file mode 100644
index 0000000..2999214
--- /dev/null
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -0,0 +1,317 @@
+/*
+ * An RTC driver for the AVR32 AT32AP700x processor series.
+ *
+ * Copyright (C) 2007 Atmel 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/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/io.h>
+
+/*
+ * This is a bare-bones RTC. It runs during most system sleep states, but has
+ * no battery backup and gets reset during system restart.  It must be
+ * initialized from an external clock (network, I2C, etc) before it can be of
+ * much use.
+ *
+ * The alarm functionality is limited by the hardware, not supporting
+ * periodic interrupts.
+ */
+
+#define RTC_CTRL		0x00
+#define RTC_CTRL_EN		   0
+#define RTC_CTRL_PCLR		   1
+#define RTC_CTRL_TOPEN		   2
+#define RTC_CTRL_PSEL		   8
+
+#define RTC_VAL			0x04
+
+#define RTC_TOP			0x08
+
+#define RTC_IER			0x10
+#define RTC_IER_TOPI		   0
+
+#define RTC_IDR			0x14
+#define RTC_IDR_TOPI		   0
+
+#define RTC_IMR			0x18
+#define RTC_IMR_TOPI		   0
+
+#define RTC_ISR			0x1c
+#define RTC_ISR_TOPI		   0
+
+#define RTC_ICR			0x20
+#define RTC_ICR_TOPI		   0
+
+#define RTC_BIT(name)		(1 << RTC_##name)
+#define RTC_BF(name, value)	((value) << RTC_##name)
+
+#define rtc_readl(dev, reg)				\
+	__raw_readl((dev)->regs + RTC_##reg)
+#define rtc_writel(dev, reg, value)			\
+	__raw_writel((value), (dev)->regs + RTC_##reg)
+
+struct rtc_at32ap700x {
+	struct rtc_device	*rtc;
+	void __iomem		*regs;
+	unsigned long		alarm_time;
+	unsigned long		irq;
+	/* Protect against concurrent register access. */
+	spinlock_t		lock;
+};
+
+static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	unsigned long now;
+
+	now = rtc_readl(rtc, VAL);
+	rtc_time_to_tm(now, tm);
+
+	return 0;
+}
+
+static int at32_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	unsigned long now;
+	int ret;
+
+	ret = rtc_tm_to_time(tm, &now);
+	if (ret == 0)
+		rtc_writel(rtc, VAL, now);
+
+	return ret;
+}
+
+static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+
+	rtc_time_to_tm(rtc->alarm_time, &alrm->time);
+	alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
+
+	return 0;
+}
+
+static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	unsigned long rtc_unix_time;
+	unsigned long alarm_unix_time;
+	int ret;
+
+	rtc_unix_time = rtc_readl(rtc, VAL);
+
+	ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time);
+	if (ret)
+		return ret;
+
+	if (alarm_unix_time < rtc_unix_time)
+		return -EINVAL;
+
+	spin_lock_irq(&rtc->lock);
+	rtc->alarm_time = alarm_unix_time;
+	rtc_writel(rtc, TOP, rtc->alarm_time);
+	if (alrm->pending)
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				| RTC_BIT(CTRL_TOPEN));
+	else
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				& ~RTC_BIT(CTRL_TOPEN));
+	spin_unlock_irq(&rtc->lock);
+
+	return ret;
+}
+
+static int at32_rtc_ioctl(struct device *dev, unsigned int cmd,
+			unsigned long arg)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	int ret = 0;
+
+	spin_lock_irq(&rtc->lock);
+
+	switch (cmd) {
+	case RTC_AIE_ON:
+		if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
+			ret = -EINVAL;
+			break;
+		}
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				| RTC_BIT(CTRL_TOPEN));
+		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+		rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
+		break;
+	case RTC_AIE_OFF:
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				& ~RTC_BIT(CTRL_TOPEN));
+		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+
+	spin_unlock_irq(&rtc->lock);
+
+	return ret;
+}
+
+static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
+{
+	struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id;
+	unsigned long isr = rtc_readl(rtc, ISR);
+	unsigned long events = 0;
+	int ret = IRQ_NONE;
+
+	spin_lock(&rtc->lock);
+
+	if (isr & RTC_BIT(ISR_TOPI)) {
+		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				& ~RTC_BIT(CTRL_TOPEN));
+		rtc_writel(rtc, VAL, rtc->alarm_time);
+		events = RTC_AF | RTC_IRQF;
+		rtc_update_irq(rtc->rtc, 1, events);
+		ret = IRQ_HANDLED;
+	}
+
+	spin_unlock(&rtc->lock);
+
+	return ret;
+}
+
+static struct rtc_class_ops at32_rtc_ops = {
+	.ioctl		= at32_rtc_ioctl,
+	.read_time	= at32_rtc_readtime,
+	.set_time	= at32_rtc_settime,
+	.read_alarm	= at32_rtc_readalarm,
+	.set_alarm	= at32_rtc_setalarm,
+};
+
+static int __init at32_rtc_probe(struct platform_device *pdev)
+{
+	struct resource	*regs;
+	struct rtc_at32ap700x *rtc;
+	int irq = -1;
+	int ret;
+
+	rtc = kzalloc(sizeof(struct rtc_at32ap700x), GFP_KERNEL);
+	if (!rtc) {
+		dev_dbg(&pdev->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_dbg(&pdev->dev, "no mmio resource defined\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_dbg(&pdev->dev, "could not get irq\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc);
+	if (ret) {
+		dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
+		goto out;
+	}
+
+	rtc->irq = irq;
+	rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!rtc->regs) {
+		ret = -ENOMEM;
+		dev_dbg(&pdev->dev, "could not map I/O memory\n");
+		goto out_free_irq;
+	}
+	spin_lock_init(&rtc->lock);
+
+	/*
+	 * Maybe init RTC: count from zero at 1 Hz, disable wrap irq.
+	 *
+	 * Do not reset VAL register, as it can hold an old time
+	 * from last JTAG reset.
+	 */
+	if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) {
+		rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR));
+		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+		rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe)
+				| RTC_BIT(CTRL_EN));
+	}
+
+	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+				&at32_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtc)) {
+		dev_dbg(&pdev->dev, "could not register rtc device\n");
+		ret = PTR_ERR(rtc->rtc);
+		goto out_iounmap;
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
+			(unsigned long)rtc->regs, rtc->irq);
+
+	return 0;
+
+out_iounmap:
+	iounmap(rtc->regs);
+out_free_irq:
+	free_irq(irq, rtc);
+out:
+	kfree(rtc);
+	return ret;
+}
+
+static int __exit at32_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_at32ap700x *rtc = platform_get_drvdata(pdev);
+
+	free_irq(rtc->irq, rtc);
+	iounmap(rtc->regs);
+	rtc_device_unregister(rtc->rtc);
+	kfree(rtc);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+MODULE_ALIAS("at32ap700x_rtc");
+
+static struct platform_driver at32_rtc_driver = {
+	.remove		= __exit_p(at32_rtc_remove),
+	.driver		= {
+		.name	= "at32ap700x_rtc",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at32_rtc_init(void)
+{
+	return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe);
+}
+module_init(at32_rtc_init);
+
+static void __exit at32_rtc_exit(void)
+{
+	platform_driver_unregister(&at32_rtc_driver);
+}
+module_exit(at32_rtc_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index f4e5f00..3045359 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -341,6 +341,8 @@
 	case RTC_IRQP_READ:
 		if (ops->irq_set_freq)
 			err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
+		else
+			err = -ENOTTY;
 		break;
 
 	case RTC_IRQP_SET:
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c
new file mode 100644
index 0000000..83efb88
--- /dev/null
+++ b/drivers/rtc/rtc-ds1216.c
@@ -0,0 +1,226 @@
+/*
+ * Dallas DS1216 RTC driver
+ *
+ * Copyright (c) 2007 Thomas Bogendoerfer
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+
+#define DRV_VERSION "0.1"
+
+struct ds1216_regs {
+	u8 tsec;
+	u8 sec;
+	u8 min;
+	u8 hour;
+	u8 wday;
+	u8 mday;
+	u8 month;
+	u8 year;
+};
+
+#define DS1216_HOUR_1224	(1 << 7)
+#define DS1216_HOUR_AMPM	(1 << 5)
+
+struct ds1216_priv {
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;
+	size_t size;
+	unsigned long baseaddr;
+};
+
+static const u8 magic[] = {
+	0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
+};
+
+/*
+ * Read the 64 bit we'd like to have - It a series
+ * of 64 bits showing up in the LSB of the base register.
+ *
+ */
+static void ds1216_read(u8 __iomem *ioaddr, u8 *buf)
+{
+	unsigned char c;
+	int i, j;
+
+	for (i = 0; i < 8; i++) {
+		c = 0;
+		for (j = 0; j < 8; j++)
+			c |= (readb(ioaddr) & 0x1) << j;
+		buf[i] = c;
+	}
+}
+
+static void ds1216_write(u8 __iomem *ioaddr, const u8 *buf)
+{
+	unsigned char c;
+	int i, j;
+
+	for (i = 0; i < 8; i++) {
+		c = buf[i];
+		for (j = 0; j < 8; j++) {
+			writeb(c, ioaddr);
+			c = c >> 1;
+		}
+	}
+}
+
+static void ds1216_switch_ds_to_clock(u8 __iomem *ioaddr)
+{
+	/* Reset magic pointer */
+	readb(ioaddr);
+	/* Write 64 bit magic to DS1216 */
+	ds1216_write(ioaddr, magic);
+}
+
+static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ds1216_priv *priv = platform_get_drvdata(pdev);
+	struct ds1216_regs regs;
+
+	ds1216_switch_ds_to_clock(priv->ioaddr);
+	ds1216_read(priv->ioaddr, (u8 *)&regs);
+
+	tm->tm_sec = BCD2BIN(regs.sec);
+	tm->tm_min = BCD2BIN(regs.min);
+	if (regs.hour & DS1216_HOUR_1224) {
+		/* AM/PM mode */
+		tm->tm_hour = BCD2BIN(regs.hour & 0x1f);
+		if (regs.hour & DS1216_HOUR_AMPM)
+			tm->tm_hour += 12;
+	} else
+		tm->tm_hour = BCD2BIN(regs.hour & 0x3f);
+	tm->tm_wday = (regs.wday & 7) - 1;
+	tm->tm_mday = BCD2BIN(regs.mday & 0x3f);
+	tm->tm_mon = BCD2BIN(regs.month & 0x1f);
+	tm->tm_year = BCD2BIN(regs.year);
+	if (tm->tm_year < 70)
+		tm->tm_year += 100;
+	return 0;
+}
+
+static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ds1216_priv *priv = platform_get_drvdata(pdev);
+	struct ds1216_regs regs;
+
+	ds1216_switch_ds_to_clock(priv->ioaddr);
+	ds1216_read(priv->ioaddr, (u8 *)&regs);
+
+	regs.tsec = 0; /* clear 0.1 and 0.01 seconds */
+	regs.sec = BIN2BCD(tm->tm_sec);
+	regs.min = BIN2BCD(tm->tm_min);
+	regs.hour &= DS1216_HOUR_1224;
+	if (regs.hour && tm->tm_hour > 12) {
+		regs.hour |= DS1216_HOUR_AMPM;
+		tm->tm_hour -= 12;
+	}
+	regs.hour |= BIN2BCD(tm->tm_hour);
+	regs.wday &= ~7;
+	regs.wday |= tm->tm_wday;
+	regs.mday = BIN2BCD(tm->tm_mday);
+	regs.month = BIN2BCD(tm->tm_mon);
+	regs.year = BIN2BCD(tm->tm_year % 100);
+
+	ds1216_switch_ds_to_clock(priv->ioaddr);
+	ds1216_write(priv->ioaddr, (u8 *)&regs);
+	return 0;
+}
+
+static const struct rtc_class_ops ds1216_rtc_ops = {
+	.read_time	= ds1216_rtc_read_time,
+	.set_time	= ds1216_rtc_set_time,
+};
+
+static int __devinit ds1216_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+	struct ds1216_priv *priv;
+	int ret = 0;
+	u8 dummy[8];
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	priv = kzalloc(sizeof *priv, GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->size = res->end - res->start + 1;
+	if (!request_mem_region(res->start, priv->size, pdev->name)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	priv->baseaddr = res->start;
+	priv->ioaddr = ioremap(priv->baseaddr, priv->size);
+	if (!priv->ioaddr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	rtc = rtc_device_register("ds1216", &pdev->dev,
+				  &ds1216_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		ret = PTR_ERR(rtc);
+		goto out;
+	}
+	priv->rtc = rtc;
+	platform_set_drvdata(pdev, priv);
+
+	/* dummy read to get clock into a known state */
+	ds1216_read(priv->ioaddr, dummy);
+	return 0;
+
+out:
+	if (priv->rtc)
+		rtc_device_unregister(priv->rtc);
+	if (priv->ioaddr)
+		iounmap(priv->ioaddr);
+	if (priv->baseaddr)
+		release_mem_region(priv->baseaddr, priv->size);
+	kfree(priv);
+	return ret;
+}
+
+static int __devexit ds1216_rtc_remove(struct platform_device *pdev)
+{
+	struct ds1216_priv *priv = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(priv->rtc);
+	iounmap(priv->ioaddr);
+	release_mem_region(priv->baseaddr, priv->size);
+	kfree(priv);
+	return 0;
+}
+
+static struct platform_driver ds1216_rtc_platform_driver = {
+	.driver		= {
+		.name	= "rtc-ds1216",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ds1216_rtc_probe,
+	.remove		= __devexit_p(ds1216_rtc_remove),
+};
+
+static int __init ds1216_rtc_init(void)
+{
+	return platform_driver_register(&ds1216_rtc_platform_driver);
+}
+
+static void __exit ds1216_rtc_exit(void)
+{
+	platform_driver_unregister(&ds1216_rtc_platform_driver);
+}
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("DS1216 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ds1216_rtc_init);
+module_exit(ds1216_rtc_exit);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 3f0f7b8..5158a62 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -24,29 +24,29 @@
  * setting the date and time), Linux can ignore the non-clock features.
  * That's a natural job for a factory or repair bench.
  *
- * If the I2C "force" mechanism is used, we assume the chip is a ds1337.
- * (Much better would be board-specific tables of I2C devices, along with
- * the platform_data drivers would use to sort such issues out.)
+ * This is currently a simple no-alarms driver.  If your board has the
+ * alarm irq wired up on a ds1337 or ds1339, and you want to use that,
+ * then look at the rtc-rs5c372 driver for code to steal...
  */
 enum ds_type {
-	unknown = 0,
-	ds_1307,		/* or ds1338, ... */
-	ds_1337,		/* or ds1339, ... */
-	ds_1340,		/* or st m41t00, ... */
+	ds_1307,
+	ds_1337,
+	ds_1338,
+	ds_1339,
+	ds_1340,
+	m41t00,
 	// rs5c372 too?  different address...
 };
 
-static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
-
 
 /* RTC registers don't differ much, except for the century flag */
 #define DS1307_REG_SECS		0x00	/* 00-59 */
 #	define DS1307_BIT_CH		0x80
+#	define DS1340_BIT_nEOSC		0x80
 #define DS1307_REG_MIN		0x01	/* 00-59 */
 #define DS1307_REG_HOUR		0x02	/* 00-23, or 1-12{am,pm} */
+#	define DS1307_BIT_12HR		0x40	/* in REG_HOUR */
+#	define DS1307_BIT_PM		0x20	/* in REG_HOUR */
 #	define DS1340_BIT_CENTURY_EN	0x80	/* in REG_HOUR */
 #	define DS1340_BIT_CENTURY	0x40	/* in REG_HOUR */
 #define DS1307_REG_WDAY		0x03	/* 01-07 */
@@ -56,11 +56,12 @@
 #define DS1307_REG_YEAR		0x06	/* 00-99 */
 
 /* Other registers (control, status, alarms, trickle charge, NVRAM, etc)
- * start at 7, and they differ a lot. Only control and status matter for RTC;
- * be careful using them.
+ * start at 7, and they differ a LOT. Only control and status matter for
+ * basic RTC date and time functionality; be careful using them.
  */
-#define DS1307_REG_CONTROL	0x07
+#define DS1307_REG_CONTROL	0x07		/* or ds1338 */
 #	define DS1307_BIT_OUT		0x80
+#	define DS1338_BIT_OSF		0x20
 #	define DS1307_BIT_SQWE		0x10
 #	define DS1307_BIT_RS1		0x02
 #	define DS1307_BIT_RS0		0x01
@@ -71,6 +72,13 @@
 #	define DS1337_BIT_INTCN		0x04
 #	define DS1337_BIT_A2IE		0x02
 #	define DS1337_BIT_A1IE		0x01
+#define DS1340_REG_CONTROL	0x07
+#	define DS1340_BIT_OUT		0x80
+#	define DS1340_BIT_FT		0x40
+#	define DS1340_BIT_CALIB_SIGN	0x20
+#	define DS1340_M_CALIBRATION	0x1f
+#define DS1340_REG_FLAG		0x09
+#	define DS1340_BIT_OSF		0x80
 #define DS1337_REG_STATUS	0x0f
 #	define DS1337_BIT_OSF		0x80
 #	define DS1337_BIT_A2I		0x02
@@ -84,21 +92,63 @@
 	u8			regs[8];
 	enum ds_type		type;
 	struct i2c_msg		msg[2];
-	struct i2c_client	client;
+	struct i2c_client	*client;
+	struct i2c_client	dev;
 	struct rtc_device	*rtc;
 };
 
+struct chip_desc {
+	char			name[9];
+	unsigned		nvram56:1;
+	unsigned		alarm:1;
+	enum ds_type		type;
+};
+
+static const struct chip_desc chips[] = { {
+	.name		= "ds1307",
+	.type		= ds_1307,
+	.nvram56	= 1,
+}, {
+	.name		= "ds1337",
+	.type		= ds_1337,
+	.alarm		= 1,
+}, {
+	.name		= "ds1338",
+	.type		= ds_1338,
+	.nvram56	= 1,
+}, {
+	.name		= "ds1339",
+	.type		= ds_1339,
+	.alarm		= 1,
+}, {
+	.name		= "ds1340",
+	.type		= ds_1340,
+}, {
+	.name		= "m41t00",
+	.type		= m41t00,
+}, };
+
+static inline const struct chip_desc *find_chip(const char *s)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(chips); i++)
+		if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0)
+			return &chips[i];
+	return NULL;
+}
 
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
 	struct ds1307	*ds1307 = dev_get_drvdata(dev);
 	int		tmp;
 
-	/* read the RTC registers all at once */
+	/* read the RTC date and time registers all at once */
 	ds1307->msg[1].flags = I2C_M_RD;
 	ds1307->msg[1].len = 7;
 
-	tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2);
+	tmp = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
+			ds1307->msg, 2);
 	if (tmp != 2) {
 		dev_err(dev, "%s error %d\n", "read", tmp);
 		return -EIO;
@@ -129,7 +179,8 @@
 		t->tm_hour, t->tm_mday,
 		t->tm_mon, t->tm_year, t->tm_wday);
 
-	return 0;
+	/* initial clock setting can be undefined */
+	return rtc_valid_tm(t);
 }
 
 static int ds1307_set_time(struct device *dev, struct rtc_time *t)
@@ -157,11 +208,18 @@
 	tmp = t->tm_year - 100;
 	buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
 
-	if (ds1307->type == ds_1337)
+	switch (ds1307->type) {
+	case ds_1337:
+	case ds_1339:
 		buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
-	else if (ds1307->type == ds_1340)
+		break;
+	case ds_1340:
 		buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
 				| DS1340_BIT_CENTURY;
+		break;
+	default:
+		break;
+	}
 
 	ds1307->msg[1].flags = 0;
 	ds1307->msg[1].len = 8;
@@ -170,7 +228,8 @@
 		"write", buf[0], buf[1], buf[2], buf[3],
 		buf[4], buf[5], buf[6]);
 
-	result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1);
+	result = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
+			&ds1307->msg[1], 1);
 	if (result != 1) {
 		dev_err(dev, "%s error %d\n", "write", tmp);
 		return -EIO;
@@ -185,25 +244,29 @@
 
 static struct i2c_driver ds1307_driver;
 
-static int __devinit
-ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
+static int __devinit ds1307_probe(struct i2c_client *client)
 {
 	struct ds1307		*ds1307;
 	int			err = -ENODEV;
-	struct i2c_client	*client;
 	int			tmp;
+	const struct chip_desc	*chip;
+	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
 
-	if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto exit;
+	chip = find_chip(client->name);
+	if (!chip) {
+		dev_err(&client->dev, "unknown chip type '%s'\n",
+				client->name);
+		return -ENODEV;
 	}
 
-	client = &ds1307->client;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &ds1307_driver;
-	client->flags = 0;
+	if (!i2c_check_functionality(adapter,
+			I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
 
+	if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL)))
+		return -ENOMEM;
+
+	ds1307->client = client;
 	i2c_set_clientdata(client, ds1307);
 
 	ds1307->msg[0].addr = client->addr;
@@ -216,14 +279,16 @@
 	ds1307->msg[1].len = sizeof(ds1307->regs);
 	ds1307->msg[1].buf = ds1307->regs;
 
-	/* HACK: "force" implies "needs ds1337-style-oscillator setup" */
-	if (kind >= 0) {
-		ds1307->type = ds_1337;
+	ds1307->type = chip->type;
 
+	switch (ds1307->type) {
+	case ds_1337:
+	case ds_1339:
 		ds1307->reg_addr = DS1337_REG_CONTROL;
 		ds1307->msg[1].len = 2;
 
-		tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+		/* get registers that the "rtc" read below won't read... */
+		tmp = i2c_transfer(adapter, ds1307->msg, 2);
 		if (tmp != 2) {
 			pr_debug("read error %d\n", tmp);
 			err = -EIO;
@@ -233,19 +298,26 @@
 		ds1307->reg_addr = 0;
 		ds1307->msg[1].len = sizeof(ds1307->regs);
 
-		/* oscillator is off; need to turn it on */
-		if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
-				|| (ds1307->regs[1] & DS1337_BIT_OSF)) {
-			printk(KERN_ERR "no ds1337 oscillator code\n");
-			goto exit_free;
+		/* oscillator off?  turn it on, so clock can tick. */
+		if (ds1307->regs[0] & DS1337_BIT_nEOSC)
+			i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
+				ds1307->regs[0] & ~DS1337_BIT_nEOSC);
+
+		/* oscillator fault?  clear flag, and warn */
+		if (ds1307->regs[1] & DS1337_BIT_OSF) {
+			i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
+				ds1307->regs[1] & ~DS1337_BIT_OSF);
+			dev_warn(&client->dev, "SET TIME!\n");
 		}
-	} else
-		ds1307->type = ds_1307;
+		break;
+	default:
+		break;
+	}
 
 read_rtc:
 	/* read RTC registers */
 
-	tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+	tmp = i2c_transfer(adapter, ds1307->msg, 2);
 	if (tmp != 2) {
 		pr_debug("read error %d\n", tmp);
 		err = -EIO;
@@ -257,119 +329,121 @@
 	 * still a few values that are clearly out-of-range.
 	 */
 	tmp = ds1307->regs[DS1307_REG_SECS];
-	if (tmp & DS1307_BIT_CH) {
-		if (ds1307->type && ds1307->type != ds_1307) {
-			pr_debug("not a ds1307?\n");
-			goto exit_free;
-		}
-		ds1307->type = ds_1307;
-
-		/* this partial initialization should work for ds1307,
-		 * ds1338, ds1340, st m41t00, and more.
+	switch (ds1307->type) {
+	case ds_1340:
+		/* FIXME read register with DS1340_BIT_OSF, use that to
+		 * trigger the "set time" warning (*after* restarting the
+		 * oscillator!) instead of this weaker ds1307/m41t00 test.
 		 */
-		dev_warn(&client->dev, "oscillator started; SET TIME!\n");
-		i2c_smbus_write_byte_data(client, 0, 0);
-		goto read_rtc;
+	case ds_1307:
+	case m41t00:
+		/* clock halted?  turn it on, so clock can tick. */
+		if (tmp & DS1307_BIT_CH) {
+			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+			dev_warn(&client->dev, "SET TIME!\n");
+			goto read_rtc;
+		}
+		break;
+	case ds_1338:
+		/* clock halted?  turn it on, so clock can tick. */
+		if (tmp & DS1307_BIT_CH)
+			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+
+		/* oscillator fault?  clear flag, and warn */
+		if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
+			i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
+					ds1307->regs[DS1337_REG_CONTROL]
+					& ~DS1338_BIT_OSF);
+			dev_warn(&client->dev, "SET TIME!\n");
+			goto read_rtc;
+		}
+		break;
+	case ds_1337:
+	case ds_1339:
+		break;
 	}
+
+	tmp = ds1307->regs[DS1307_REG_SECS];
 	tmp = BCD2BIN(tmp & 0x7f);
 	if (tmp > 60)
-		goto exit_free;
+		goto exit_bad;
 	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
 	if (tmp > 60)
-		goto exit_free;
+		goto exit_bad;
 
 	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
 	if (tmp == 0 || tmp > 31)
-		goto exit_free;
+		goto exit_bad;
 
 	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
 	if (tmp == 0 || tmp > 12)
-		goto exit_free;
+		goto exit_bad;
 
-	/* force into in 24 hour mode (most chips) or
-	 * disable century bit (ds1340)
-	 */
 	tmp = ds1307->regs[DS1307_REG_HOUR];
-	if (tmp & (1 << 6)) {
-		if (tmp & (1 << 5))
-			tmp = BCD2BIN(tmp & 0x1f) + 12;
-		else
-			tmp = BCD2BIN(tmp);
+	switch (ds1307->type) {
+	case ds_1340:
+	case m41t00:
+		/* NOTE: ignores century bits; fix before deploying
+		 * systems that will run through year 2100.
+		 */
+		break;
+	default:
+		if (!(tmp & DS1307_BIT_12HR))
+			break;
+
+		/* Be sure we're in 24 hour mode.  Multi-master systems
+		 * take note...
+		 */
+		tmp = BCD2BIN(tmp & 0x1f);
+		if (tmp == 12)
+			tmp = 0;
+		if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
+			tmp += 12;
 		i2c_smbus_write_byte_data(client,
 				DS1307_REG_HOUR,
 				BIN2BCD(tmp));
 	}
 
-	/* FIXME chips like 1337 can generate alarm irqs too; those are
-	 * worth exposing through the API (especially when the irq is
-	 * wakeup-capable).
-	 */
-
-	switch (ds1307->type) {
-	case unknown:
-		strlcpy(client->name, "unknown", I2C_NAME_SIZE);
-		break;
-	case ds_1307:
-		strlcpy(client->name, "ds1307", I2C_NAME_SIZE);
-		break;
-	case ds_1337:
-		strlcpy(client->name, "ds1337", I2C_NAME_SIZE);
-		break;
-	case ds_1340:
-		strlcpy(client->name, "ds1340", I2C_NAME_SIZE);
-		break;
-	}
-
-	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(client)))
-		goto exit_free;
-
 	ds1307->rtc = rtc_device_register(client->name, &client->dev,
 				&ds13xx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(ds1307->rtc)) {
 		err = PTR_ERR(ds1307->rtc);
 		dev_err(&client->dev,
 			"unable to register the class device\n");
-		goto exit_detach;
+		goto exit_free;
 	}
 
 	return 0;
 
-exit_detach:
-	i2c_detach_client(client);
+exit_bad:
+	dev_dbg(&client->dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+			"bogus register",
+			ds1307->regs[0], ds1307->regs[1],
+			ds1307->regs[2], ds1307->regs[3],
+			ds1307->regs[4], ds1307->regs[5],
+			ds1307->regs[6]);
+
 exit_free:
 	kfree(ds1307);
-exit:
 	return err;
 }
 
-static int __devinit
-ds1307_attach_adapter(struct i2c_adapter *adapter)
+static int __devexit ds1307_remove(struct i2c_client *client)
 {
-	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
-		return 0;
-	return i2c_probe(adapter, &addr_data, ds1307_detect);
-}
-
-static int __devexit ds1307_detach_client(struct i2c_client *client)
-{
-	int		err;
 	struct ds1307	*ds1307 = i2c_get_clientdata(client);
 
 	rtc_device_unregister(ds1307->rtc);
-	if ((err = i2c_detach_client(client)))
-		return err;
 	kfree(ds1307);
 	return 0;
 }
 
 static struct i2c_driver ds1307_driver = {
 	.driver = {
-		.name	= "ds1307",
+		.name	= "rtc-ds1307",
 		.owner	= THIS_MODULE,
 	},
-	.attach_adapter	= ds1307_attach_adapter,
-	.detach_client	= __devexit_p(ds1307_detach_client),
+	.probe		= ds1307_probe,
+	.remove		= __devexit_p(ds1307_remove),
 };
 
 static int __init ds1307_init(void)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
new file mode 100644
index 0000000..80c4a84
--- /dev/null
+++ b/drivers/rtc/rtc-m41t80.c
@@ -0,0 +1,917 @@
+/*
+ * I2C client/driver for the ST M41T80 family of i2c rtc chips.
+ *
+ * Author: Alexander Bigga <ab@mycable.de>
+ *
+ * Based on m41t00.c by Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) mycable GmbH
+ *
+ * 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/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#endif
+
+#define M41T80_REG_SSEC	0
+#define M41T80_REG_SEC	1
+#define M41T80_REG_MIN	2
+#define M41T80_REG_HOUR	3
+#define M41T80_REG_WDAY	4
+#define M41T80_REG_DAY	5
+#define M41T80_REG_MON	6
+#define M41T80_REG_YEAR	7
+#define M41T80_REG_ALARM_MON	0xa
+#define M41T80_REG_ALARM_DAY	0xb
+#define M41T80_REG_ALARM_HOUR	0xc
+#define M41T80_REG_ALARM_MIN	0xd
+#define M41T80_REG_ALARM_SEC	0xe
+#define M41T80_REG_FLAGS	0xf
+#define M41T80_REG_SQW	0x13
+
+#define M41T80_DATETIME_REG_SIZE	(M41T80_REG_YEAR + 1)
+#define M41T80_ALARM_REG_SIZE	\
+	(M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON)
+
+#define M41T80_SEC_ST		(1 << 7)	/* ST: Stop Bit */
+#define M41T80_ALMON_AFE	(1 << 7)	/* AFE: AF Enable Bit */
+#define M41T80_ALMON_SQWE	(1 << 6)	/* SQWE: SQW Enable Bit */
+#define M41T80_ALHOUR_HT	(1 << 6)	/* HT: Halt Update Bit */
+#define M41T80_FLAGS_AF		(1 << 6)	/* AF: Alarm Flag Bit */
+#define M41T80_FLAGS_BATT_LOW	(1 << 4)	/* BL: Battery Low Bit */
+
+#define M41T80_FEATURE_HT	(1 << 0)
+#define M41T80_FEATURE_BL	(1 << 1)
+
+#define DRV_VERSION "0.05"
+
+struct m41t80_chip_info {
+	const char *name;
+	u8 features;
+};
+
+static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
+	{
+		.name		= "m41t80",
+		.features	= 0,
+	},
+	{
+		.name		= "m41t81",
+		.features	= M41T80_FEATURE_HT,
+	},
+	{
+		.name		= "m41t81s",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41t82",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41t83",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41st84",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41st85",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41st87",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+};
+
+struct m41t80_data {
+	const struct m41t80_chip_info *chip;
+	struct rtc_device *rtc;
+};
+
+static int m41t80_get_datetime(struct i2c_client *client,
+			       struct rtc_time *tm)
+{
+	u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC };
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
+			.buf	= buf + M41T80_REG_SEC,
+		},
+	};
+
+	if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+
+	tm->tm_sec = BCD2BIN(buf[M41T80_REG_SEC] & 0x7f);
+	tm->tm_min = BCD2BIN(buf[M41T80_REG_MIN] & 0x7f);
+	tm->tm_hour = BCD2BIN(buf[M41T80_REG_HOUR] & 0x3f);
+	tm->tm_mday = BCD2BIN(buf[M41T80_REG_DAY] & 0x3f);
+	tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07;
+	tm->tm_mon = BCD2BIN(buf[M41T80_REG_MON] & 0x1f) - 1;
+
+	/* assume 20YY not 19YY, and ignore the Century Bit */
+	tm->tm_year = BCD2BIN(buf[M41T80_REG_YEAR]) + 100;
+	return 0;
+}
+
+/* Sets the given date and time to the real time clock. */
+static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+	u8 wbuf[1 + M41T80_DATETIME_REG_SIZE];
+	u8 *buf = &wbuf[1];
+	u8 dt_addr[1] = { M41T80_REG_SEC };
+	struct i2c_msg msgs_in[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
+			.buf	= buf + M41T80_REG_SEC,
+		},
+	};
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1 + M41T80_DATETIME_REG_SIZE,
+			.buf	= wbuf,
+		 },
+	};
+
+	/* Read current reg values into buf[1..7] */
+	if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+
+	wbuf[0] = 0; /* offset into rtc's regs */
+	/* Merge time-data and register flags into buf[0..7] */
+	buf[M41T80_REG_SSEC] = 0;
+	buf[M41T80_REG_SEC] =
+		BIN2BCD(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
+	buf[M41T80_REG_MIN] =
+		BIN2BCD(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
+	buf[M41T80_REG_HOUR] =
+		BIN2BCD(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ;
+	buf[M41T80_REG_WDAY] =
+		(tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07);
+	buf[M41T80_REG_DAY] =
+		BIN2BCD(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
+	buf[M41T80_REG_MON] =
+		BIN2BCD(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
+	/* assume 20YY not 19YY */
+	buf[M41T80_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+
+	if (i2c_transfer(client->adapter, msgs, 1) != 1) {
+		dev_err(&client->dev, "write error\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct m41t80_data *clientdata = i2c_get_clientdata(client);
+	u8 reg;
+
+	if (clientdata->chip->features & M41T80_FEATURE_BL) {
+		reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+		seq_printf(seq, "battery\t\t: %s\n",
+			   (reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
+	}
+	return 0;
+}
+#else
+#define m41t80_rtc_proc NULL
+#endif
+
+static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	return m41t80_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	return m41t80_set_datetime(to_i2c_client(dev), tm);
+}
+
+#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
+static int
+m41t80_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int rc;
+
+	switch (cmd) {
+	case RTC_AIE_OFF:
+	case RTC_AIE_ON:
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+	if (rc < 0)
+		goto err;
+	switch (cmd) {
+	case RTC_AIE_OFF:
+		rc &= ~M41T80_ALMON_AFE;
+		break;
+	case RTC_AIE_ON:
+		rc |= M41T80_ALMON_AFE;
+		break;
+	}
+	if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0)
+		goto err;
+	return 0;
+err:
+	return -EIO;
+}
+#else
+#define	m41t80_rtc_ioctl NULL
+#endif
+
+static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 wbuf[1 + M41T80_ALARM_REG_SIZE];
+	u8 *buf = &wbuf[1];
+	u8 *reg = buf - M41T80_REG_ALARM_MON;
+	u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
+	struct i2c_msg msgs_in[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_ALARM_REG_SIZE,
+			.buf	= buf,
+		},
+	};
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1 + M41T80_ALARM_REG_SIZE,
+			.buf	= wbuf,
+		 },
+	};
+
+	if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+	reg[M41T80_REG_ALARM_MON] &= ~(0x1f | M41T80_ALMON_AFE);
+	reg[M41T80_REG_ALARM_DAY] = 0;
+	reg[M41T80_REG_ALARM_HOUR] &= ~(0x3f | 0x80);
+	reg[M41T80_REG_ALARM_MIN] = 0;
+	reg[M41T80_REG_ALARM_SEC] = 0;
+
+	wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */
+	reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ?
+		BIN2BCD(t->time.tm_sec) : 0x80;
+	reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ?
+		BIN2BCD(t->time.tm_min) : 0x80;
+	reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ?
+		BIN2BCD(t->time.tm_hour) : 0x80;
+	reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ?
+		BIN2BCD(t->time.tm_mday) : 0x80;
+	if (t->time.tm_mon >= 0)
+		reg[M41T80_REG_ALARM_MON] |= BIN2BCD(t->time.tm_mon + 1);
+	else
+		reg[M41T80_REG_ALARM_DAY] |= 0x40;
+
+	if (i2c_transfer(client->adapter, msgs, 1) != 1) {
+		dev_err(&client->dev, "write error\n");
+		return -EIO;
+	}
+
+	if (t->enabled) {
+		reg[M41T80_REG_ALARM_MON] |= M41T80_ALMON_AFE;
+		if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+					      reg[M41T80_REG_ALARM_MON]) < 0) {
+			dev_err(&client->dev, "write error\n");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 buf[M41T80_ALARM_REG_SIZE + 1]; /* all alarm regs and flags */
+	u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
+	u8 *reg = buf - M41T80_REG_ALARM_MON;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_ALARM_REG_SIZE + 1,
+			.buf	= buf,
+		},
+	};
+
+	if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+	t->time.tm_sec = -1;
+	t->time.tm_min = -1;
+	t->time.tm_hour = -1;
+	t->time.tm_mday = -1;
+	t->time.tm_mon = -1;
+	if (!(reg[M41T80_REG_ALARM_SEC] & 0x80))
+		t->time.tm_sec = BCD2BIN(reg[M41T80_REG_ALARM_SEC] & 0x7f);
+	if (!(reg[M41T80_REG_ALARM_MIN] & 0x80))
+		t->time.tm_min = BCD2BIN(reg[M41T80_REG_ALARM_MIN] & 0x7f);
+	if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80))
+		t->time.tm_hour = BCD2BIN(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
+	if (!(reg[M41T80_REG_ALARM_DAY] & 0x80))
+		t->time.tm_mday = BCD2BIN(reg[M41T80_REG_ALARM_DAY] & 0x3f);
+	if (!(reg[M41T80_REG_ALARM_DAY] & 0x40))
+		t->time.tm_mon = BCD2BIN(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
+	t->time.tm_year = -1;
+	t->time.tm_wday = -1;
+	t->time.tm_yday = -1;
+	t->time.tm_isdst = -1;
+	t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE);
+	t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF);
+	return 0;
+}
+
+static struct rtc_class_ops m41t80_rtc_ops = {
+	.read_time = m41t80_rtc_read_time,
+	.set_time = m41t80_rtc_set_time,
+	.read_alarm = m41t80_rtc_read_alarm,
+	.set_alarm = m41t80_rtc_set_alarm,
+	.proc = m41t80_rtc_proc,
+	.ioctl = m41t80_rtc_ioctl,
+};
+
+#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
+static ssize_t m41t80_sysfs_show_flags(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int val;
+
+	val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+	if (val < 0)
+		return -EIO;
+	return sprintf(buf, "%#x\n", val);
+}
+static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL);
+
+static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int val;
+
+	val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
+	if (val < 0)
+		return -EIO;
+	val = (val >> 4) & 0xf;
+	switch (val) {
+	case 0:
+		break;
+	case 1:
+		val = 32768;
+		break;
+	default:
+		val = 32768 >> val;
+	}
+	return sprintf(buf, "%d\n", val);
+}
+static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int almon, sqw;
+	int val = simple_strtoul(buf, NULL, 0);
+
+	if (val) {
+		if (!is_power_of_2(val))
+			return -EINVAL;
+		val = ilog2(val);
+		if (val == 15)
+			val = 1;
+		else if (val < 14)
+			val = 15 - val;
+		else
+			return -EINVAL;
+	}
+	/* disable SQW, set SQW frequency & re-enable */
+	almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+	if (almon < 0)
+		return -EIO;
+	sqw = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
+	if (sqw < 0)
+		return -EIO;
+	sqw = (sqw & 0x0f) | (val << 4);
+	if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+				      almon & ~M41T80_ALMON_SQWE) < 0 ||
+	    i2c_smbus_write_byte_data(client, M41T80_REG_SQW, sqw) < 0)
+		return -EIO;
+	if (val && i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+					     almon | M41T80_ALMON_SQWE) < 0)
+		return -EIO;
+	return count;
+}
+static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
+		   m41t80_sysfs_show_sqwfreq, m41t80_sysfs_set_sqwfreq);
+
+static struct attribute *attrs[] = {
+	&dev_attr_flags.attr,
+	&dev_attr_sqwfreq.attr,
+	NULL,
+};
+static struct attribute_group attr_group = {
+	.attrs = attrs,
+};
+
+static int m41t80_sysfs_register(struct device *dev)
+{
+	return sysfs_create_group(&dev->kobj, &attr_group);
+}
+#else
+static int m41t80_sysfs_register(struct device *dev)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+/*
+ *****************************************************************************
+ *
+ * Watchdog Driver
+ *
+ *****************************************************************************
+ */
+static struct i2c_client *save_client;
+
+/* Default margin */
+#define WD_TIMO 60		/* 1..31 seconds */
+
+static int wdt_margin = WD_TIMO;
+module_param(wdt_margin, int, 0);
+MODULE_PARM_DESC(wdt_margin, "Watchdog timeout in seconds (default 60s)");
+
+static unsigned long wdt_is_open;
+static int boot_flag;
+
+/**
+ *	wdt_ping:
+ *
+ *	Reload counter one with the watchdog timeout. We don't bother reloading
+ *	the cascade counter.
+ */
+static void wdt_ping(void)
+{
+	unsigned char i2c_data[2];
+	struct i2c_msg msgs1[1] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 2,
+			.buf	= i2c_data,
+		},
+	};
+	i2c_data[0] = 0x09;		/* watchdog register */
+
+	if (wdt_margin > 31)
+		i2c_data[1] = (wdt_margin & 0xFC) | 0x83; /* resolution = 4s */
+	else
+		/*
+		 * WDS = 1 (0x80), mulitplier = WD_TIMO, resolution = 1s (0x02)
+		 */
+		i2c_data[1] = wdt_margin<<2 | 0x82;
+
+	i2c_transfer(save_client->adapter, msgs1, 1);
+}
+
+/**
+ *	wdt_disable:
+ *
+ *	disables watchdog.
+ */
+static void wdt_disable(void)
+{
+	unsigned char i2c_data[2], i2c_buf[0x10];
+	struct i2c_msg msgs0[2] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= i2c_data,
+		},
+		{
+			.addr	= save_client->addr,
+			.flags	= I2C_M_RD,
+			.len	= 1,
+			.buf	= i2c_buf,
+		},
+	};
+	struct i2c_msg msgs1[1] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 2,
+			.buf	= i2c_data,
+		},
+	};
+
+	i2c_data[0] = 0x09;
+	i2c_transfer(save_client->adapter, msgs0, 2);
+
+	i2c_data[0] = 0x09;
+	i2c_data[1] = 0x00;
+	i2c_transfer(save_client->adapter, msgs1, 1);
+}
+
+/**
+ *	wdt_write:
+ *	@file: file handle to the watchdog
+ *	@buf: buffer to write (unused as data does not matter here
+ *	@count: count of bytes
+ *	@ppos: pointer to the position to write. No seeks allowed
+ *
+ *	A write to a watchdog device is defined as a keepalive signal. Any
+ *	write of data will do, as we we don't define content meaning.
+ */
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	/*  Can't seek (pwrite) on this device
+	if (ppos != &file->f_pos)
+	return -ESPIPE;
+	*/
+	if (count) {
+		wdt_ping();
+		return 1;
+	}
+	return 0;
+}
+
+static ssize_t wdt_read(struct file *file, char __user *buf,
+			size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+/**
+ *	wdt_ioctl:
+ *	@inode: inode of the device
+ *	@file: file handle to the device
+ *	@cmd: watchdog command
+ *	@arg: argument pointer
+ *
+ *	The watchdog API defines a common set of functions for all watchdogs
+ *	according to their available features. We only actually usefully support
+ *	querying capabilities and current status.
+ */
+static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+	int new_margin, rv;
+	static struct watchdog_info ident = {
+		.options = WDIOF_POWERUNDER | WDIOF_KEEPALIVEPING |
+			WDIOF_SETTIMEOUT,
+		.firmware_version = 1,
+		.identity = "M41T80 WTD"
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		return copy_to_user((struct watchdog_info __user *)arg, &ident,
+				    sizeof(ident)) ? -EFAULT : 0;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(boot_flag, (int __user *)arg);
+	case WDIOC_KEEPALIVE:
+		wdt_ping();
+		return 0;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int __user *)arg))
+			return -EFAULT;
+		/* Arbitrary, can't find the card's limits */
+		if (new_margin < 1 || new_margin > 124)
+			return -EINVAL;
+		wdt_margin = new_margin;
+		wdt_ping();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		return put_user(wdt_margin, (int __user *)arg);
+
+	case WDIOC_SETOPTIONS:
+		if (copy_from_user(&rv, (int __user *)arg, sizeof(int)))
+			return -EFAULT;
+
+		if (rv & WDIOS_DISABLECARD) {
+			printk(KERN_INFO
+			       "rtc-m41t80: disable watchdog\n");
+			wdt_disable();
+		}
+
+		if (rv & WDIOS_ENABLECARD) {
+			printk(KERN_INFO
+			       "rtc-m41t80: enable watchdog\n");
+			wdt_ping();
+		}
+
+		return -EINVAL;
+	}
+	return -ENOTTY;
+}
+
+/**
+ *	wdt_open:
+ *	@inode: inode of device
+ *	@file: file handle to device
+ *
+ */
+static int wdt_open(struct inode *inode, struct file *file)
+{
+	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+		if (test_and_set_bit(0, &wdt_is_open))
+			return -EBUSY;
+		/*
+		 *	Activate
+		 */
+		wdt_is_open = 1;
+		return 0;
+	}
+	return -ENODEV;
+}
+
+/**
+ *	wdt_close:
+ *	@inode: inode to board
+ *	@file: file handle to board
+ *
+ */
+static int wdt_release(struct inode *inode, struct file *file)
+{
+	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR)
+		clear_bit(0, &wdt_is_open);
+	return 0;
+}
+
+/**
+ *	notify_sys:
+ *	@this: our notifier block
+ *	@code: the event being reported
+ *	@unused: unused
+ *
+ *	Our notifier is called on system shutdowns. We want to turn the card
+ *	off at reboot otherwise the machine will reboot again during memory
+ *	test or worse yet during the following fsck. This would suck, in fact
+ *	trust me - if it happens it does suck.
+ */
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+			  void *unused)
+{
+	if (code == SYS_DOWN || code == SYS_HALT)
+		/* Disable Watchdog */
+		wdt_disable();
+	return NOTIFY_DONE;
+}
+
+static const struct file_operations wdt_fops = {
+	.owner	= THIS_MODULE,
+	.read	= wdt_read,
+	.ioctl	= wdt_ioctl,
+	.write	= wdt_write,
+	.open	= wdt_open,
+	.release = wdt_release,
+};
+
+static struct miscdevice wdt_dev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &wdt_fops,
+};
+
+/*
+ *	The WDT card needs to learn about soft shutdowns in order to
+ *	turn the timebomb registers off.
+ */
+static struct notifier_block wdt_notifier = {
+	.notifier_call = wdt_notify_sys,
+};
+#endif /* CONFIG_RTC_DRV_M41T80_WDT */
+
+/*
+ *****************************************************************************
+ *
+ *	Driver Interface
+ *
+ *****************************************************************************
+ */
+static int m41t80_probe(struct i2c_client *client)
+{
+	int i, rc = 0;
+	struct rtc_device *rtc = NULL;
+	struct rtc_time tm;
+	const struct m41t80_chip_info *chip;
+	struct m41t80_data *clientdata = NULL;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
+				     | I2C_FUNC_SMBUS_BYTE_DATA)) {
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	dev_info(&client->dev,
+		 "chip found, driver version " DRV_VERSION "\n");
+
+	chip = NULL;
+	for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
+		if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
+			chip = &m41t80_chip_info_tbl[i];
+			break;
+		}
+	}
+	if (!chip) {
+		dev_err(&client->dev, "%s is not supported\n", client->name);
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
+	if (!clientdata) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	rtc = rtc_device_register(client->name, &client->dev,
+				  &m41t80_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		rc = PTR_ERR(rtc);
+		rtc = NULL;
+		goto exit;
+	}
+
+	clientdata->rtc = rtc;
+	clientdata->chip = chip;
+	i2c_set_clientdata(client, clientdata);
+
+	/* Make sure HT (Halt Update) bit is cleared */
+	rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
+	if (rc < 0)
+		goto ht_err;
+
+	if (rc & M41T80_ALHOUR_HT) {
+		if (chip->features & M41T80_FEATURE_HT) {
+			m41t80_get_datetime(client, &tm);
+			dev_info(&client->dev, "HT bit was set!\n");
+			dev_info(&client->dev,
+				 "Power Down at "
+				 "%04i-%02i-%02i %02i:%02i:%02i\n",
+				 tm.tm_year + 1900,
+				 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+				 tm.tm_min, tm.tm_sec);
+		}
+		if (i2c_smbus_write_byte_data(client,
+					      M41T80_REG_ALARM_HOUR,
+					      rc & ~M41T80_ALHOUR_HT) < 0)
+			goto ht_err;
+	}
+
+	/* Make sure ST (stop) bit is cleared */
+	rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC);
+	if (rc < 0)
+		goto st_err;
+
+	if (rc & M41T80_SEC_ST) {
+		if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC,
+					      rc & ~M41T80_SEC_ST) < 0)
+			goto st_err;
+	}
+
+	rc = m41t80_sysfs_register(&client->dev);
+	if (rc)
+		goto exit;
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+	if (chip->features & M41T80_FEATURE_HT) {
+		rc = misc_register(&wdt_dev);
+		if (rc)
+			goto exit;
+		rc = register_reboot_notifier(&wdt_notifier);
+		if (rc) {
+			misc_deregister(&wdt_dev);
+			goto exit;
+		}
+		save_client = client;
+	}
+#endif
+	return 0;
+
+st_err:
+	rc = -EIO;
+	dev_err(&client->dev, "Can't clear ST bit\n");
+	goto exit;
+ht_err:
+	rc = -EIO;
+	dev_err(&client->dev, "Can't clear HT bit\n");
+	goto exit;
+
+exit:
+	if (rtc)
+		rtc_device_unregister(rtc);
+	kfree(clientdata);
+	return rc;
+}
+
+static int m41t80_remove(struct i2c_client *client)
+{
+	struct m41t80_data *clientdata = i2c_get_clientdata(client);
+	struct rtc_device *rtc = clientdata->rtc;
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+	if (clientdata->chip->features & M41T80_FEATURE_HT) {
+		misc_deregister(&wdt_dev);
+		unregister_reboot_notifier(&wdt_notifier);
+	}
+#endif
+	if (rtc)
+		rtc_device_unregister(rtc);
+	kfree(clientdata);
+
+	return 0;
+}
+
+static struct i2c_driver m41t80_driver = {
+	.driver = {
+		.name = "m41t80",
+	},
+	.probe = m41t80_probe,
+	.remove = m41t80_remove,
+};
+
+static int __init m41t80_rtc_init(void)
+{
+	return i2c_add_driver(&m41t80_driver);
+}
+
+static void __exit m41t80_rtc_exit(void)
+{
+	i2c_del_driver(&m41t80_driver);
+}
+
+MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>");
+MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(m41t80_rtc_init);
+module_exit(m41t80_rtc_exit);
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
new file mode 100644
index 0000000..33b7523
--- /dev/null
+++ b/drivers/rtc/rtc-m48t59.c
@@ -0,0 +1,491 @@
+/*
+ * ST M48T59 RTC driver
+ *
+ * Copyright (c) 2007 Wind River Systems, Inc.
+ *
+ * Author: Mark Zhan <rongkai.zhan@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/rtc/m48t59.h>
+#include <linux/bcd.h>
+
+#ifndef NO_IRQ
+#define NO_IRQ	(-1)
+#endif
+
+#define M48T59_READ(reg)	pdata->read_byte(dev, reg)
+#define M48T59_WRITE(val, reg)	pdata->write_byte(dev, reg, val)
+
+#define M48T59_SET_BITS(mask, reg)	\
+	M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
+#define M48T59_CLEAR_BITS(mask, reg)	\
+	M48T59_WRITE((M48T59_READ(reg) & ~(mask)), (reg))
+
+struct m48t59_private {
+	void __iomem *ioaddr;
+	unsigned int size; /* iomem size */
+	unsigned int irq;
+	struct rtc_device *rtc;
+	spinlock_t lock; /* serialize the NVRAM and RTC access */
+};
+
+/*
+ * This is the generic access method when the chip is memory-mapped
+ */
+static void
+m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+	writeb(val, m48t59->ioaddr+ofs);
+}
+
+static u8
+m48t59_mem_readb(struct device *dev, u32 ofs)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+	return readb(m48t59->ioaddr+ofs);
+}
+
+/*
+ * NOTE: M48T59 only uses BCD mode
+ */
+static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the READ command */
+	M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+
+	tm->tm_year	= BCD2BIN(M48T59_READ(M48T59_YEAR));
+	/* tm_mon is 0-11 */
+	tm->tm_mon	= BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+	tm->tm_mday	= BCD2BIN(M48T59_READ(M48T59_MDAY));
+
+	val = M48T59_READ(M48T59_WDAY);
+	if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
+		dev_dbg(dev, "Century bit is enabled\n");
+		tm->tm_year += 100;	/* one century */
+	}
+
+	tm->tm_wday	= BCD2BIN(val & 0x07);
+	tm->tm_hour	= BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F);
+	tm->tm_min	= BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F);
+	tm->tm_sec	= BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F);
+
+	/* Clear the READ bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+	return 0;
+}
+
+static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	u8 val = 0;
+
+	dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the WRITE command */
+	M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+
+	M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC);
+	M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN);
+	M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR);
+	M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY);
+	/* tm_mon is 0-11 */
+	M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
+	M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
+
+	if (tm->tm_year/100)
+		val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
+	val |= (BIN2BCD(tm->tm_wday) & 0x07);
+	M48T59_WRITE(val, M48T59_WDAY);
+
+	/* Clear the WRITE bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+	return 0;
+}
+
+/*
+ * Read alarm time and date in RTC
+ */
+static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	struct rtc_time *tm = &alrm->time;
+	unsigned long flags;
+	u8 val;
+
+	/* If no irq, we don't support ALARM */
+	if (m48t59->irq == NO_IRQ)
+		return -EIO;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the READ command */
+	M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+
+	tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
+	/* tm_mon is 0-11 */
+	tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+
+	val = M48T59_READ(M48T59_WDAY);
+	if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
+		tm->tm_year += 100;	/* one century */
+
+	tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE));
+	tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR));
+	tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN));
+	tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC));
+
+	/* Clear the READ bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+	return 0;
+}
+
+/*
+ * Set alarm time and date in RTC
+ */
+static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	struct rtc_time *tm = &alrm->time;
+	u8 mday, hour, min, sec;
+	unsigned long flags;
+
+	/* If no irq, we don't support ALARM */
+	if (m48t59->irq == NO_IRQ)
+		return -EIO;
+
+	/*
+	 * 0xff means "always match"
+	 */
+	mday = tm->tm_mday;
+	mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+	if (mday == 0xff)
+		mday = M48T59_READ(M48T59_MDAY);
+
+	hour = tm->tm_hour;
+	hour = (hour < 24) ? BIN2BCD(hour) : 0x00;
+
+	min = tm->tm_min;
+	min = (min < 60) ? BIN2BCD(min) : 0x00;
+
+	sec = tm->tm_sec;
+	sec = (sec < 60) ? BIN2BCD(sec) : 0x00;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the WRITE command */
+	M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+
+	M48T59_WRITE(mday, M48T59_ALARM_DATE);
+	M48T59_WRITE(hour, M48T59_ALARM_HOUR);
+	M48T59_WRITE(min, M48T59_ALARM_MIN);
+	M48T59_WRITE(sec, M48T59_ALARM_SEC);
+
+	/* Clear the WRITE bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+	return 0;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd,
+			unsigned long arg)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	switch (cmd) {
+	case RTC_AIE_OFF:	/* alarm interrupt off */
+		M48T59_WRITE(0x00, M48T59_INTR);
+		break;
+	case RTC_AIE_ON:	/* alarm interrupt on */
+		M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	return ret;
+}
+
+static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	val = M48T59_READ(M48T59_FLAGS);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	seq_printf(seq, "battery\t\t: %s\n",
+		 (val & M48T59_FLAGS_BF) ? "low" : "normal");
+	return 0;
+}
+
+/*
+ * IRQ handler for the RTC
+ */
+static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id)
+{
+	struct device *dev = (struct device *)dev_id;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	u8 event;
+
+	spin_lock(&m48t59->lock);
+	event = M48T59_READ(M48T59_FLAGS);
+	spin_unlock(&m48t59->lock);
+
+	if (event & M48T59_FLAGS_AF) {
+		rtc_update_irq(m48t59->rtc, 1, (RTC_AF | RTC_IRQF));
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static const struct rtc_class_ops m48t59_rtc_ops = {
+	.ioctl		= m48t59_rtc_ioctl,
+	.read_time	= m48t59_rtc_read_time,
+	.set_time	= m48t59_rtc_set_time,
+	.read_alarm	= m48t59_rtc_readalarm,
+	.set_alarm	= m48t59_rtc_setalarm,
+	.proc		= m48t59_rtc_proc,
+};
+
+static ssize_t m48t59_nvram_read(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t pos, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	ssize_t cnt = 0;
+	unsigned long flags;
+
+	for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+		spin_lock_irqsave(&m48t59->lock, flags);
+		*buf++ = M48T59_READ(cnt);
+		spin_unlock_irqrestore(&m48t59->lock, flags);
+	}
+
+	return cnt;
+}
+
+static ssize_t m48t59_nvram_write(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t pos, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	ssize_t cnt = 0;
+	unsigned long flags;
+
+	for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+		spin_lock_irqsave(&m48t59->lock, flags);
+		M48T59_WRITE(*buf++, cnt);
+		spin_unlock_irqrestore(&m48t59->lock, flags);
+	}
+
+	return cnt;
+}
+
+static struct bin_attribute m48t59_nvram_attr = {
+	.attr = {
+		.name = "nvram",
+		.mode = S_IRUGO | S_IWUGO,
+		.owner = THIS_MODULE,
+	},
+	.read = m48t59_nvram_read,
+	.write = m48t59_nvram_write,
+};
+
+static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
+{
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = NULL;
+	struct resource *res;
+	int ret = -ENOMEM;
+
+	/* This chip could be memory-mapped or I/O-mapped */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+		if (!res)
+			return -EINVAL;
+	}
+
+	if (res->flags & IORESOURCE_IO) {
+		/* If we are I/O-mapped, the platform should provide
+		 * the operations accessing chip registers.
+		 */
+		if (!pdata || !pdata->write_byte || !pdata->read_byte)
+			return -EINVAL;
+	} else if (res->flags & IORESOURCE_MEM) {
+		/* we are memory-mapped */
+		if (!pdata) {
+			pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+			if (!pdata)
+				return -ENOMEM;
+			/* Ensure we only kmalloc platform data once */
+			pdev->dev.platform_data = pdata;
+		}
+
+		/* Try to use the generic memory read/write ops */
+		if (!pdata->write_byte)
+			pdata->write_byte = m48t59_mem_writeb;
+		if (!pdata->read_byte)
+			pdata->read_byte = m48t59_mem_readb;
+	}
+
+	m48t59 = kzalloc(sizeof(*m48t59), GFP_KERNEL);
+	if (!m48t59)
+		return -ENOMEM;
+
+	m48t59->size = res->end - res->start + 1;
+	m48t59->ioaddr = ioremap(res->start, m48t59->size);
+	if (!m48t59->ioaddr)
+		goto out;
+
+	/* Try to get irq number. We also can work in
+	 * the mode without IRQ.
+	 */
+	m48t59->irq = platform_get_irq(pdev, 0);
+	if (m48t59->irq < 0)
+		m48t59->irq = NO_IRQ;
+
+	if (m48t59->irq != NO_IRQ) {
+		ret = request_irq(m48t59->irq, m48t59_rtc_interrupt,
+			IRQF_SHARED, "rtc-m48t59", &pdev->dev);
+		if (ret)
+			goto out;
+	}
+
+	m48t59->rtc = rtc_device_register("m48t59", &pdev->dev,
+				&m48t59_rtc_ops, THIS_MODULE);
+	if (IS_ERR(m48t59->rtc)) {
+		ret = PTR_ERR(m48t59->rtc);
+		goto out;
+	}
+
+	ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
+	if (ret)
+		goto out;
+
+	spin_lock_init(&m48t59->lock);
+	platform_set_drvdata(pdev, m48t59);
+	return 0;
+
+out:
+	if (!IS_ERR(m48t59->rtc))
+		rtc_device_unregister(m48t59->rtc);
+	if (m48t59->irq != NO_IRQ)
+		free_irq(m48t59->irq, &pdev->dev);
+	if (m48t59->ioaddr)
+		iounmap(m48t59->ioaddr);
+	if (m48t59)
+		kfree(m48t59);
+	return ret;
+}
+
+static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
+{
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+	sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
+	if (!IS_ERR(m48t59->rtc))
+		rtc_device_unregister(m48t59->rtc);
+	if (m48t59->ioaddr)
+		iounmap(m48t59->ioaddr);
+	if (m48t59->irq != NO_IRQ)
+		free_irq(m48t59->irq, &pdev->dev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(m48t59);
+	return 0;
+}
+
+static struct platform_driver m48t59_rtc_platdrv = {
+	.driver		= {
+		.name	= "rtc-m48t59",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= m48t59_rtc_probe,
+	.remove		= __devexit_p(m48t59_rtc_remove),
+};
+
+static int __init m48t59_rtc_init(void)
+{
+	return platform_driver_register(&m48t59_rtc_platdrv);
+}
+
+static void __exit m48t59_rtc_exit(void)
+{
+	platform_driver_unregister(&m48t59_rtc_platdrv);
+}
+
+module_init(m48t59_rtc_init);
+module_exit(m48t59_rtc_exit);
+
+MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
+MODULE_DESCRIPTION("M48T59 RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 09bbe57..6b67b50 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -13,13 +13,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 
-#define DRV_VERSION "0.4"
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
+#define DRV_VERSION "0.5"
 
 
 /*
@@ -88,9 +82,6 @@
 	unsigned		has_irq:1;
 	char			buf[17];
 	char			*regs;
-
-	/* on conversion to a "new style" i2c driver, this vanishes */
-	struct i2c_client	dev;
 };
 
 static int rs5c_get_regs(struct rs5c372 *rs5c)
@@ -483,25 +474,35 @@
 	return err;
 }
 
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_trim);
+	device_remove_file(dev, &dev_attr_osc);
+}
+
 #else
 static int rs5c_sysfs_register(struct device *dev)
 {
 	return 0;
 }
+
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+	/* nothing */
+}
 #endif	/* SYSFS */
 
 static struct i2c_driver rs5c372_driver;
 
-static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
+static int rs5c372_probe(struct i2c_client *client)
 {
 	int err = 0;
-	struct i2c_client *client;
 	struct rs5c372 *rs5c372;
 	struct rtc_time tm;
 
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		err = -ENODEV;
 		goto exit;
 	}
@@ -514,35 +515,22 @@
 	/* we read registers 0x0f then 0x00-0x0f; skip the first one */
 	rs5c372->regs=&rs5c372->buf[1];
 
-	/* On conversion to a "new style" i2c driver, we'll be handed
-	 * the i2c_client (we won't create it)
-	 */
-	client = &rs5c372->dev;
 	rs5c372->client = client;
-
-	/* I2C client */
-	client->addr = address;
-	client->driver = &rs5c372_driver;
-	client->adapter = adapter;
-
-	strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);
-
 	i2c_set_clientdata(client, rs5c372);
 
-	/* Inform the i2c layer */
-	if ((err = i2c_attach_client(client)))
-		goto exit_kfree;
-
 	err = rs5c_get_regs(rs5c372);
 	if (err < 0)
-		goto exit_detach;
+		goto exit_kfree;
 
-	/* For "new style" drivers, irq is in i2c_client and chip type
-	 * info comes from i2c_client.dev.platform_data.  Meanwhile:
-	 *
-	 * STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE
-	 */
-	if (rs5c372->type == rtc_undef) {
+	if (strcmp(client->name, "rs5c372a") == 0)
+		rs5c372->type = rtc_rs5c372a;
+	else if (strcmp(client->name, "rs5c372b") == 0)
+		rs5c372->type = rtc_rs5c372b;
+	else if (strcmp(client->name, "rv5c386") == 0)
+		rs5c372->type = rtc_rv5c386;
+	else if (strcmp(client->name, "rv5c387a") == 0)
+		rs5c372->type = rtc_rv5c387a;
+	else {
 		rs5c372->type = rtc_rs5c372b;
 		dev_warn(&client->dev, "assuming rs5c372b\n");
 	}
@@ -567,7 +555,7 @@
 		break;
 	default:
 		dev_err(&client->dev, "unknown RTC type\n");
-		goto exit_detach;
+		goto exit_kfree;
 	}
 
 	/* if the oscillator lost power and no other software (like
@@ -601,7 +589,7 @@
 
 		if ((i2c_master_send(client, buf, 3)) != 3) {
 			dev_err(&client->dev, "setup error\n");
-			goto exit_detach;
+			goto exit_kfree;
 		}
 		rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
 		rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
@@ -621,14 +609,14 @@
 			rs5c372->time24 ? "24hr" : "am/pm"
 			);
 
-	/* FIXME when client->irq exists, use it to register alarm irq */
+	/* REVISIT use client->irq to register alarm irq ... */
 
 	rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name,
 				&client->dev, &rs5c372_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rs5c372->rtc)) {
 		err = PTR_ERR(rs5c372->rtc);
-		goto exit_detach;
+		goto exit_kfree;
 	}
 
 	err = rs5c_sysfs_register(&client->dev);
@@ -640,9 +628,6 @@
 exit_devreg:
 	rtc_device_unregister(rs5c372->rtc);
 
-exit_detach:
-	i2c_detach_client(client);
-
 exit_kfree:
 	kfree(rs5c372);
 
@@ -650,24 +635,12 @@
 	return err;
 }
 
-static int rs5c372_attach(struct i2c_adapter *adapter)
+static int rs5c372_remove(struct i2c_client *client)
 {
-	return i2c_probe(adapter, &addr_data, rs5c372_probe);
-}
-
-static int rs5c372_detach(struct i2c_client *client)
-{
-	int err;
 	struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
 
-	if (rs5c372->rtc)
-		rtc_device_unregister(rs5c372->rtc);
-
-	/* REVISIT properly destroy the sysfs files ... */
-
-	if ((err = i2c_detach_client(client)))
-		return err;
-
+	rtc_device_unregister(rs5c372->rtc);
+	rs5c_sysfs_unregister(&client->dev);
 	kfree(rs5c372);
 	return 0;
 }
@@ -676,8 +649,8 @@
 	.driver		= {
 		.name	= "rtc-rs5c372",
 	},
-	.attach_adapter	= &rs5c372_attach,
-	.detach_client	= &rs5c372_detach,
+	.probe		= rs5c372_probe,
+	.remove		= rs5c372_remove,
 };
 
 static __init int rs5c372_init(void)
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 1340451..35765f6 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -747,14 +747,9 @@
 static void __exit
 dcssblk_exit(void)
 {
-	int rc;
-
 	PRINT_DEBUG("DCSSBLOCK EXIT...\n");
 	s390_root_dev_unregister(dcssblk_root_dev);
-	rc = unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
-	if (rc) {
-		PRINT_ERR("unregister_blkdev() failed!\n");
-	}
+	unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
 	PRINT_DEBUG("...finished!\n");
 }
 
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index b34eb82..ec18bae 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -211,6 +211,10 @@
 	/* initial values when measuring starts */
 	unsigned long initial_rx_packets;
 	unsigned long initial_tx_packets;
+	/* inbound scatter gather data */
+	unsigned int sg_skbs_rx;
+	unsigned int sg_frags_rx;
+	unsigned int sg_alloc_page_rx;
 };
 
 /* Routing stuff */
@@ -341,6 +345,9 @@
 
 #define QETH_IP_HEADER_SIZE 40
 
+/* large receive scatter gather copy break */
+#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+
 struct qeth_hdr_layer3 {
 	__u8  id;
 	__u8  flags;
@@ -771,6 +778,7 @@
 	int layer2;
 	enum qeth_large_send_types large_send;
 	int performance_stats;
+	int rx_sg_cb;
 };
 
 /*
@@ -828,6 +836,7 @@
 	int (*orig_hard_header)(struct sk_buff *,struct net_device *,
 				unsigned short,void *,void *,unsigned);
 	struct qeth_osn_info osn_info;
+	atomic_t force_alloc_skb;
 };
 
 struct qeth_card_list_struct {
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 86b0c44..57f6943 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1054,6 +1054,7 @@
 	else
 		card->options.layer2 = 0;
 	card->options.performance_stats = 0;
+	card->options.rx_sg_cb = QETH_RX_SG_CB;
 }
 
 /**
@@ -1934,6 +1935,7 @@
 			atomic_inc(&reply->received);
 			wake_up(&reply->wait_q);
 		}
+		cpu_relax();
 	};
 	rc = reply->rc;
 	qeth_put_reply(reply);
@@ -2258,6 +2260,89 @@
 	return skb;
 }
 
+static inline int
+qeth_create_skb_frag(struct qdio_buffer_element *element,
+		     struct sk_buff **pskb,
+		     int offset, int *pfrag, int data_len)
+{
+	struct page *page = virt_to_page(element->addr);
+	if (*pfrag == 0) {
+		/* the upper protocol layers assume that there is data in the
+		 * skb itself. Copy a small amount (64 bytes) to make them
+		 * happy. */
+		*pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
+		if (!(*pskb))
+			return -ENOMEM;
+		skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
+		if (data_len <= 64) {
+			memcpy(skb_put(*pskb, data_len), element->addr + offset,
+				data_len);
+		} else {
+			get_page(page);
+			memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
+			skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
+				data_len - 64);
+			(*pskb)->data_len += data_len - 64;
+			(*pskb)->len	  += data_len - 64;
+			(*pskb)->truesize += data_len - 64;
+		}
+	} else {
+		get_page(page);
+		skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
+		(*pskb)->data_len += data_len;
+		(*pskb)->len	  += data_len;
+		(*pskb)->truesize += data_len;
+	}
+	(*pfrag)++;
+	return 0;
+}
+
+static inline struct qeth_buffer_pool_entry *
+qeth_find_free_buffer_pool_entry(struct qeth_card *card)
+{
+	struct list_head *plh;
+	struct qeth_buffer_pool_entry *entry;
+	int i, free;
+	struct page *page;
+
+	if (list_empty(&card->qdio.in_buf_pool.entry_list))
+		return NULL;
+
+	list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
+		entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
+		free = 1;
+		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+			if (page_count(virt_to_page(entry->elements[i])) > 1) {
+				free = 0;
+				break;
+			}
+		}
+		if (free) {
+			list_del_init(&entry->list);
+			return entry;
+		}
+	}
+
+	/* no free buffer in pool so take first one and swap pages */
+	entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
+			struct qeth_buffer_pool_entry, list);
+	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+		if (page_count(virt_to_page(entry->elements[i])) > 1) {
+			page = alloc_page(GFP_ATOMIC|GFP_DMA);
+			if (!page) {
+				return NULL;
+			} else {
+				free_page((unsigned long)entry->elements[i]);
+				entry->elements[i] = page_address(page);
+				if (card->options.performance_stats)
+					card->perf_stats.sg_alloc_page_rx++;
+			}
+		}
+	}
+	list_del_init(&entry->list);
+	return entry;
+}
+
 static struct sk_buff *
 qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
 		  struct qdio_buffer_element **__element, int *__offset,
@@ -2269,6 +2354,8 @@
 	int skb_len;
 	void *data_ptr;
 	int data_len;
+	int use_rx_sg = 0;
+	int frag = 0;
 
 	QETH_DBF_TEXT(trace,6,"nextskb");
 	/* qeth_hdr must not cross element boundaries */
@@ -2293,23 +2380,43 @@
 
 	if (!skb_len)
 		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, *hdr)))
-				goto no_mem;
-			skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
+	if ((skb_len >= card->options.rx_sg_cb) &&
+	    (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+	    (!atomic_read(&card->force_alloc_skb))) {
+		use_rx_sg = 1;
+	} else {
+		if (card->options.fake_ll) {
+			if (card->dev->type == ARPHRD_IEEE802_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, *hdr)))
+					goto no_mem;
+				skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
+			}
 		} else {
-			if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
+			skb = qeth_get_skb(skb_len, *hdr);
+			if (!skb)
 				goto no_mem;
-			skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
 		}
-	} else if (!(skb = qeth_get_skb(skb_len, *hdr)))
-		goto no_mem;
+	}
+
 	data_ptr = element->addr + offset;
 	while (skb_len) {
 		data_len = min(skb_len, (int)(element->length - offset));
-		if (data_len)
-			memcpy(skb_put(skb, data_len), data_ptr, data_len);
+		if (data_len) {
+			if (use_rx_sg) {
+				if (qeth_create_skb_frag(element, &skb, offset,
+				    &frag, data_len))
+					goto no_mem;
+			} else {
+				memcpy(skb_put(skb, data_len), data_ptr,
+					data_len);
+			}
+		}
 		skb_len -= data_len;
 		if (skb_len){
 			if (qeth_is_last_sbale(element)){
@@ -2331,6 +2438,10 @@
 	}
 	*__element = element;
 	*__offset = offset;
+	if (use_rx_sg && card->options.performance_stats) {
+		card->perf_stats.sg_skbs_rx++;
+		card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+	}
 	return skb;
 no_mem:
 	if (net_ratelimit()){
@@ -2608,28 +2719,15 @@
 	}
 }
 
-static struct qeth_buffer_pool_entry *
-qeth_get_buffer_pool_entry(struct qeth_card *card)
-{
-	struct qeth_buffer_pool_entry *entry;
-
-	QETH_DBF_TEXT(trace, 6, "gtbfplen");
-	if (!list_empty(&card->qdio.in_buf_pool.entry_list)) {
-		entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
-				struct qeth_buffer_pool_entry, list);
-		list_del_init(&entry->list);
-		return entry;
-	}
-	return NULL;
-}
-
-static void
+static int
 qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
 {
 	struct qeth_buffer_pool_entry *pool_entry;
 	int i;
- 
-	pool_entry = qeth_get_buffer_pool_entry(card);
+
+	pool_entry = qeth_find_free_buffer_pool_entry(card);
+	if (!pool_entry)
+		return 1;
 	/*
 	 * since the buffer is accessed only from the input_tasklet
 	 * there shouldn't be a need to synchronize; also, since we use
@@ -2648,6 +2746,7 @@
 			buf->buffer->element[i].flags = 0;
 	}
 	buf->state = QETH_QDIO_BUF_EMPTY;
+	return 0;
 }
 
 static void
@@ -2682,6 +2781,7 @@
 	int count;
 	int i;
 	int rc;
+	int newcount = 0;
 
 	QETH_DBF_TEXT(trace,6,"queinbuf");
 	count = (index < queue->next_buf_to_init)?
@@ -2692,9 +2792,27 @@
 	/* only requeue at a certain threshold to avoid SIGAs */
 	if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
 		for (i = queue->next_buf_to_init;
-		     i < queue->next_buf_to_init + count; ++i)
-			qeth_init_input_buffer(card,
-				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]);
+		     i < queue->next_buf_to_init + count; ++i) {
+			if (qeth_init_input_buffer(card,
+				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
+				break;
+			} else {
+				newcount++;
+			}
+		}
+
+		if (newcount < count) {
+			/* we are in memory shortage so we switch back to
+			   traditional skb allocation and drop packages */
+			if (atomic_cmpxchg(&card->force_alloc_skb, 0, 1))
+				printk(KERN_WARNING
+					"qeth: switch to alloc skb\n");
+			count = newcount;
+		} else {
+			if (atomic_cmpxchg(&card->force_alloc_skb, 1, 0))
+				printk(KERN_WARNING "qeth: switch to sg\n");
+		}
+
 		/*
 		 * according to old code it should be avoided to requeue all
 		 * 128 buffers in order to benefit from PCI avoidance.
@@ -6494,6 +6612,7 @@
 
 	QETH_DBF_TEXT(setup, 2, "hrdsetup");
 
+	atomic_set(&card->force_alloc_skb, 0);
 retry:
 	if (retries < 3){
 		PRINT_WARN("Retrying to do IDX activates.\n");
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 89d56c8..f1ff165 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -212,6 +212,12 @@
 		      "  Skb fragments sent in SG mode          : %u\n\n",
 		      card->perf_stats.sg_skbs_sent,
 		      card->perf_stats.sg_frags_sent);
+	seq_printf(s, "  Skbs received in SG mode               : %u\n"
+		      "  Skb fragments received in SG mode      : %u\n"
+		      "  Page allocations for rx SG mode        : %u\n\n",
+		      card->perf_stats.sg_skbs_rx,
+		      card->perf_stats.sg_frags_rx,
+		      card->perf_stats.sg_alloc_page_rx);
 	seq_printf(s, "  large_send tx (in Kbytes)              : %u\n"
 		      "  large_send count                       : %u\n\n",
 		      card->perf_stats.large_send_bytes >> 10,
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index 022e869..7b5773d 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -24,6 +24,7 @@
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/smp_lock.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/ebus.h>
 #include <asm/oplib.h>
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 512857a..5157a2a 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -619,8 +619,7 @@
 	jsf0.busy = 0;
 
 	misc_deregister(&jsf_dev);
-	if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0)
-		printk("jsfd: cleanup_module failed\n");
+	unregister_blkdev(JSFD_MAJOR, "jsfd");
 	blk_cleanup_queue(jsf_queue);
 }
 
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 9d2119b..3727231 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -545,7 +545,7 @@
 
 config SCSI_BUSLOGIC
 	tristate "BusLogic SCSI support"
-	depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API
+	depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API && VIRT_TO_BUS
 	---help---
 	  This is support for BusLogic MultiMaster and FlashPoint SCSI Host
 	  Adapters. Consult the SCSI-HOWTO, available from
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index d70ddfd..9c5342e 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -40,6 +40,7 @@
 
 #include <linux/err.h>
 #include <linux/blkdev.h>
+#include <linux/freezer.h>
 #include <linux/scatterlist.h>
 
 /* ---------- SCSI Host glue ---------- */
@@ -868,8 +869,6 @@
 {
 	struct sas_ha_struct *sas_ha = _sas_ha;
 
-	current->flags |= PF_NOFREEZE;
-
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 9adb64a..8a525ab 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -19,6 +19,7 @@
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
@@ -1516,8 +1517,6 @@
 {
 	struct Scsi_Host *shost = data;
 
-	current->flags |= PF_NOFREEZE;
-
 	/*
 	 * We use TASK_INTERRUPTIBLE so that the thread is not
 	 * counted against the load average as a running process.
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 448d316..424d557 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -684,7 +684,7 @@
 		case SCSI_IOCTL_GET_BUS_NUMBER:
 			return scsi_ioctl(sdp, cmd, p);
 		default:
-			error = scsi_cmd_ioctl(filp, disk, cmd, p);
+			error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p);
 			if (error != -ENOTTY)
 				return error;
 	}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 55bfecc..a4f7b84 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3549,7 +3549,8 @@
 			    !capable(CAP_SYS_RAWIO))
 				i = -EPERM;
 			else
-				i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
+				i = scsi_cmd_ioctl(file, STp->disk->queue,
+						   STp->disk, cmd_in, p);
 			if (i != -ENOTTY)
 				return i;
 			break;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 68817a7..2aa6bfe 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -934,8 +934,6 @@
 	/*
 	 * Set up parity check flag
 	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 	info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
 	if (I_INPCK(info->tty))
 		info->read_status_mask |= BD_SC_FR | BD_SC_PR;
@@ -1527,11 +1525,6 @@
 {
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
 
-	if (   (tty->termios->c_cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	change_speed(info);
 
 #ifdef modem_control
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index c84dab0..0b3ec38 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2514,12 +2514,18 @@
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
+static int __init serial8250_console_early_setup(void)
+{
+	return serial8250_find_port_for_earlycon();
+}
+
 static struct uart_driver serial8250_reg;
 static struct console serial8250_console = {
 	.name		= "ttyS",
 	.write		= serial8250_console_write,
 	.device		= uart_console_device,
 	.setup		= serial8250_console_setup,
+	.early_setup	= serial8250_console_early_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
 	.data		= &serial8250_reg,
@@ -2533,7 +2539,7 @@
 }
 console_initcall(serial8250_console_init);
 
-static int __init find_port(struct uart_port *p)
+int serial8250_find_port(struct uart_port *p)
 {
 	int line;
 	struct uart_port *port;
@@ -2546,26 +2552,6 @@
 	return -ENODEV;
 }
 
-int __init serial8250_start_console(struct uart_port *port, char *options)
-{
-	int line;
-
-	line = find_port(port);
-	if (line < 0)
-		return -ENODEV;
-
-	add_preferred_console("ttyS", line, options);
-	printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
-		line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
-		port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
-		    (unsigned long) port->iobase, options);
-	if (!(serial8250_console.flags & CON_ENABLED)) {
-		serial8250_console.flags &= ~CON_PRINTBUFFER;
-		register_console(&serial8250_console);
-	}
-	return line;
-}
-
 #define SERIAL8250_CONSOLE	&serial8250_console
 #else
 #define SERIAL8250_CONSOLE	NULL
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 7e51119..947c205 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -17,13 +17,11 @@
  * we locate the device directly by its MMIO or I/O port address.
  *
  * The user can specify the device directly, e.g.,
- *	console=uart,io,0x3f8,9600n8
- *	console=uart,mmio,0xff5e0000,115200n8
- * or platform code can call early_uart_console_init() to set
- * the early UART device.
- *
- * After the normal serial driver starts, we try to locate the
- * matching ttyS device and start a console there.
+ *	earlycon=uart8250,io,0x3f8,9600n8
+ *	earlycon=uart8250,mmio,0xff5e0000,115200n8
+ * or
+ *	console=uart8250,io,0x3f8,9600n8
+ *	console=uart8250,mmio,0xff5e0000,115200n8
  */
 
 #include <linux/tty.h>
@@ -32,17 +30,21 @@
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
+#include <linux/serial_8250.h>
 #include <asm/io.h>
 #include <asm/serial.h>
+#ifdef CONFIG_FIX_EARLYCON_MEM
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#endif
 
-struct early_uart_device {
+struct early_serial8250_device {
 	struct uart_port port;
 	char options[16];		/* e.g., 115200n8 */
 	unsigned int baud;
 };
 
-static struct early_uart_device early_device __initdata;
-static int early_uart_registered __initdata;
+static struct early_serial8250_device early_device;
 
 static unsigned int __init serial_in(struct uart_port *port, int offset)
 {
@@ -80,7 +82,7 @@
 	serial_out(port, UART_TX, c);
 }
 
-static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
+static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
 {
 	struct uart_port *port = &early_device.port;
 	unsigned int ier;
@@ -111,7 +113,7 @@
 	return (port->uartclk / 16) / quot;
 }
 
-static void __init init_port(struct early_uart_device *device)
+static void __init init_port(struct early_serial8250_device *device)
 {
 	struct uart_port *port = &device->port;
 	unsigned int divisor;
@@ -130,10 +132,9 @@
 	serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 
-static int __init parse_options(struct early_uart_device *device, char *options)
+static int __init parse_options(struct early_serial8250_device *device, char *options)
 {
 	struct uart_port *port = &device->port;
-	int mapsize = 64;
 	int mmio, length;
 
 	if (!options)
@@ -143,12 +144,18 @@
 	if (!strncmp(options, "mmio,", 5)) {
 		port->iotype = UPIO_MEM;
 		port->mapbase = simple_strtoul(options + 5, &options, 0);
-		port->membase = ioremap(port->mapbase, mapsize);
+#ifdef CONFIG_FIX_EARLYCON_MEM
+		set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
+		port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+		port->membase += port->mapbase & ~PAGE_MASK;
+#else
+		port->membase = ioremap(port->mapbase, 64);
 		if (!port->membase) {
 			printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
 				__FUNCTION__, port->mapbase);
 			return -ENOMEM;
 		}
+#endif
 		mmio = 1;
 	} else if (!strncmp(options, "io,", 3)) {
 		port->iotype = UPIO_PORT;
@@ -175,9 +182,16 @@
 	return 0;
 }
 
-static int __init early_uart_setup(struct console *console, char *options)
+static struct console early_serial8250_console __initdata = {
+	.name	= "uart",
+	.write	= early_serial8250_write,
+	.flags	= CON_PRINTBUFFER | CON_BOOT,
+	.index	= -1,
+};
+
+static int __init early_serial8250_setup(char *options)
 {
-	struct early_uart_device *device = &early_device;
+	struct early_serial8250_device *device = &early_device;
 	int err;
 
 	if (device->port.membase || device->port.iobase)
@@ -190,61 +204,48 @@
 	return 0;
 }
 
-static struct console early_uart_console __initdata = {
-	.name	= "uart",
-	.write	= early_uart_write,
-	.setup	= early_uart_setup,
-	.flags	= CON_PRINTBUFFER,
-	.index	= -1,
-};
-
-static int __init early_uart_console_init(void)
-{
-	if (!early_uart_registered) {
-		register_console(&early_uart_console);
-		early_uart_registered = 1;
-	}
-	return 0;
-}
-console_initcall(early_uart_console_init);
-
-int __init early_serial_console_init(char *cmdline)
+int __init setup_early_serial8250_console(char *cmdline)
 {
 	char *options;
 	int err;
 
-	options = strstr(cmdline, "console=uart,");
-	if (!options)
-		return -ENODEV;
+	options = strstr(cmdline, "uart8250,");
+	if (!options) {
+		options = strstr(cmdline, "uart,");
+		if (!options)
+			return 0;
+	}
 
 	options = strchr(cmdline, ',') + 1;
-	if ((err = early_uart_setup(NULL, options)) < 0)
+	if ((err = early_serial8250_setup(options)) < 0)
 		return err;
-	return early_uart_console_init();
-}
 
-static int __init early_uart_console_switch(void)
-{
-	struct early_uart_device *device = &early_device;
-	struct uart_port *port = &device->port;
-	int mmio, line;
-
-	if (!(early_uart_console.flags & CON_ENABLED))
-		return 0;
-
-	/* Try to start the normal driver on a matching line.  */
-	mmio = (port->iotype == UPIO_MEM);
-	line = serial8250_start_console(port, device->options);
-	if (line < 0)
-		printk("No ttyS device at %s 0x%lx for console\n",
-			mmio ? "MMIO" : "I/O port",
-			mmio ? port->mapbase :
-			    (unsigned long) port->iobase);
-
-	unregister_console(&early_uart_console);
-	if (mmio)
-		iounmap(port->membase);
+	register_console(&early_serial8250_console);
 
 	return 0;
 }
-late_initcall(early_uart_console_switch);
+
+int __init serial8250_find_port_for_earlycon(void)
+{
+	struct early_serial8250_device *device = &early_device;
+	struct uart_port *port = &device->port;
+	int line;
+	int ret;
+
+	if (!device->port.membase && !device->port.iobase)
+		return -ENODEV;
+
+	line = serial8250_find_port(port);
+	if (line < 0)
+		return -ENODEV;
+
+	ret = update_console_cmdline("uart", 8250,
+			     "ttyS", line, device->options);
+	if (ret < 0)
+		ret = update_console_cmdline("uart", 0,
+				     "ttyS", line, device->options);
+
+	return ret;
+}
+
+early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 2adbed4..7fa413d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,8 +62,22 @@
 	  kernel will automatically use the first serial line, /dev/ttyS0, as
 	  system console.
 
+	  you can set that using a kernel command line option such as
+	  "console=uart8250,io,0x3f8,9600n8"
+	  "console=uart8250,mmio,0xff5e0000,115200n8".
+	  and it will switch to normal serial console when correponding port is
+	  ready.
+	  "earlycon=uart8250,io,0x3f8,9600n8"
+	  "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+	  it will not only setup early console.
+
 	  If unsure, say N.
 
+config FIX_EARLYCON_MEM
+	bool
+	depends on X86
+	default y
+
 config SERIAL_8250_GSC
 	tristate
 	depends on SERIAL_8250 && GSC
@@ -324,6 +338,34 @@
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_SB1250_DUART
+	tristate "BCM1xxx on-chip DUART serial support"
+	depends on SIBYTE_SB1xxx_SOC=y
+	select SERIAL_CORE
+	default y
+	---help---
+	  Support for the asynchronous serial interface (DUART) included in
+	  the BCM1250 and derived System-On-a-Chip (SOC) devices.  Note that
+	  the letter D in DUART stands for "dual", which is how the device
+	  is implemented.  Depending on the SOC configuration there may be
+	  one or more DUARTs available of which all are handled.
+
+	  If unsure, say Y.  To compile this driver as a module, choose M here:
+	  the module will be called sb1250-duart.
+
+config SERIAL_SB1250_DUART_CONSOLE
+	bool "Support for console on a BCM1xxx DUART serial port"
+	depends on SERIAL_SB1250_DUART=y
+	select SERIAL_CORE_CONSOLE
+	default y
+	---help---
+	  If you say Y here, it will be possible to use a serial port as the
+	  system console (the system console is the device which receives all
+	  kernel messages and warnings and which allows logins in single user
+	  mode).
+
+	  If unsure, say Y.
+
 config SERIAL_ATMEL
 	bool "AT91 / AT32 on-chip serial port support"
 	depends on (ARM && ARCH_AT91) || AVR32
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 08ad0d9..c48cdd6 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -51,6 +51,7 @@
 obj-$(CONFIG_SERIAL_ICOM) += icom.o
 obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
 obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
+obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 3320bcd..4d6b3c5 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -114,6 +114,7 @@
 	struct uart_port	uart;		/* uart */
 	struct clk		*clk;		/* uart clock */
 	unsigned short		suspended;	/* is port suspended? */
+	int			break_active;	/* break being received */
 };
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
@@ -252,6 +253,7 @@
  */
 static void atmel_rx_chars(struct uart_port *port)
 {
+	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
 	struct tty_struct *tty = port->info->tty;
 	unsigned int status, ch, flg;
 
@@ -267,13 +269,29 @@
 		 * note that the error handling code is
 		 * out of the main execution path
 		 */
-		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
+		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
+				       | ATMEL_US_OVRE | ATMEL_US_RXBRK)
+			     || atmel_port->break_active)) {
 			UART_PUT_CR(port, ATMEL_US_RSTSTA);	/* clear error */
-			if (status & ATMEL_US_RXBRK) {
+			if (status & ATMEL_US_RXBRK
+			    && !atmel_port->break_active) {
 				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */
 				port->icount.brk++;
+				atmel_port->break_active = 1;
+				UART_PUT_IER(port, ATMEL_US_RXBRK);
 				if (uart_handle_break(port))
 					goto ignore_char;
+			} else {
+				/*
+				 * This is either the end-of-break
+				 * condition or we've received at
+				 * least one character without RXBRK
+				 * being set. In both cases, the next
+				 * RXBRK will indicate start-of-break.
+				 */
+				UART_PUT_IDR(port, ATMEL_US_RXBRK);
+				status &= ~ATMEL_US_RXBRK;
+				atmel_port->break_active = 0;
 			}
 			if (status & ATMEL_US_PARE)
 				port->icount.parity++;
@@ -352,6 +370,16 @@
 		/* Interrupt receive */
 		if (pending & ATMEL_US_RXRDY)
 			atmel_rx_chars(port);
+		else if (pending & ATMEL_US_RXBRK) {
+			/*
+			 * End of break detected. If it came along
+			 * with a character, atmel_rx_chars will
+			 * handle it.
+			 */
+			UART_PUT_CR(port, ATMEL_US_RSTSTA);
+			UART_PUT_IDR(port, ATMEL_US_RXBRK);
+			atmel_port->break_active = 0;
+		}
 
 		// TODO: All reads to CSR will clear these interrupts!
 		if (pending & ATMEL_US_RIIC) port->icount.rng++;
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b63ff8d..cefde58 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -678,7 +678,7 @@
 		}
 		bdp->cbd_datlen = count;
 		bdp->cbd_sc |= BD_SC_READY;
-		__asm__("eieio");
+		eieio();
 		/* Get next BD. */
 		if (bdp->cbd_sc & BD_SC_WRAP)
 			bdp = pinfo->tx_bd_base;
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index c3abfb3..f3257f7 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -862,6 +862,7 @@
 	up->cflag = termios->c_cflag;
 
 	ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+	uart_update_timeout(port, termios->c_cflag, baud);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
@@ -1017,6 +1018,8 @@
 	}
 
 	con->cflag = cflag | CS8;			/* 8N1 */
+
+	uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud);
 }
 
 static int __init ip22zilog_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
index 7ffdaea..a64d858 100644
--- a/drivers/serial/of_serial.c
+++ b/drivers/serial/of_serial.c
@@ -17,6 +17,11 @@
 #include <asm/of_platform.h>
 #include <asm/prom.h>
 
+struct of_serial_info {
+	int type;
+	int line;
+};
+
 /*
  * Fill a struct uart_port for a given device node
  */
@@ -62,6 +67,7 @@
 static int __devinit of_platform_serial_probe(struct of_device *ofdev,
 						const struct of_device_id *id)
 {
+	struct of_serial_info *info;
 	struct uart_port port;
 	int port_type;
 	int ret;
@@ -69,30 +75,35 @@
 	if (of_find_property(ofdev->node, "used-by-rtas", NULL))
 		return -EBUSY;
 
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (info == NULL)
+		return -ENOMEM;
+
 	port_type = (unsigned long)id->data;
 	ret = of_platform_serial_setup(ofdev, port_type, &port);
 	if (ret)
 		goto out;
 
 	switch (port_type) {
-	case PORT_UNKNOWN:
-		dev_info(&ofdev->dev, "Unknown serial port found, "
-			"attempting to use 8250 driver\n");
-		/* fallthrough */
 	case PORT_8250 ... PORT_MAX_8250:
 		ret = serial8250_register_port(&port);
 		break;
 	default:
 		/* need to add code for these */
+	case PORT_UNKNOWN:
+		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
 		ret = -ENODEV;
 		break;
 	}
 	if (ret < 0)
 		goto out;
 
-	ofdev->dev.driver_data = (void *)(unsigned long)ret;
+	info->type = port_type;
+	info->line = ret;
+	ofdev->dev.driver_data = info;
 	return 0;
 out:
+	kfree(info);
 	irq_dispose_mapping(port.irq);
 	return ret;
 }
@@ -102,8 +113,16 @@
  */
 static int of_platform_serial_remove(struct of_device *ofdev)
 {
-	int line = (unsigned long)ofdev->dev.driver_data;
-	serial8250_unregister_port(line);
+	struct of_serial_info *info = ofdev->dev.driver_data;
+	switch (info->type) {
+	case PORT_8250 ... PORT_MAX_8250:
+		serial8250_unregister_port(info->line);
+		break;
+	default:
+		/* need to add code for these */
+		break;
+	}
+	kfree(info);
 	return 0;
 }
 
diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c
new file mode 100644
index 0000000..1d9d728
--- /dev/null
+++ b/drivers/serial/sb1250-duart.c
@@ -0,0 +1,972 @@
+/*
+ *	drivers/serial/sb1250-duart.c
+ *
+ *	Support for the asynchronous serial interface (DUART) included
+ *	in the BCM1250 and derived System-On-a-Chip (SOC) devices.
+ *
+ *	Copyright (c) 2007  Maciej W. Rozycki
+ *
+ *	Derived from drivers/char/sb1250_duart.c for which the following
+ *	copyright applies:
+ *
+ *	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.
+ *
+ *	References:
+ *
+ *	"BCM1250/BCM1125/BCM1125H User Manual", Broadcom Corporation
+ */
+
+#if defined(CONFIG_SERIAL_SB1250_DUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/spinlock.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/war.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/swarm.h>
+
+
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+#define SBD_CHANREGS(line)	A_BCM1480_DUART_CHANREG((line), 0)
+#define SBD_CTRLREGS(line)	A_BCM1480_DUART_CTRLREG((line), 0)
+#define SBD_INT(line)		(K_BCM1480_INT_UART_0 + (line))
+
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+
+#define SBD_CHANREGS(line)	A_DUART_CHANREG((line), 0)
+#define SBD_CTRLREGS(line)	A_DUART_CTRLREG(0)
+#define SBD_INT(line)		(K_INT_UART_0 + (line))
+
+#else
+#error invalid SB1250 UART configuration
+
+#endif
+
+
+MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
+MODULE_DESCRIPTION("BCM1xxx on-chip DUART serial driver");
+MODULE_LICENSE("GPL");
+
+
+#define DUART_MAX_CHIP 2
+#define DUART_MAX_SIDE 2
+
+/*
+ * Per-port state.
+ */
+struct sbd_port {
+	struct sbd_duart	*duart;
+	struct uart_port	port;
+	unsigned char __iomem	*memctrl;
+	int			tx_stopped;
+	int			initialised;
+};
+
+/*
+ * Per-DUART state for the shared register space.
+ */
+struct sbd_duart {
+	struct sbd_port		sport[2];
+	unsigned long		mapctrl;
+	atomic_t		map_guard;
+};
+
+#define to_sport(uport) container_of(uport, struct sbd_port, port)
+
+static struct sbd_duart sbd_duarts[DUART_MAX_CHIP];
+
+#define __unused __attribute__((__unused__))
+
+
+/*
+ * Reading and writing SB1250 DUART registers.
+ *
+ * There are three register spaces: two per-channel ones and
+ * a shared one.  We have to define accessors appropriately.
+ * All registers are 64-bit and all but the Baud Rate Clock
+ * registers only define 8 least significant bits.  There is
+ * also a workaround to take into account.  Raw accessors use
+ * the full register width, but cooked ones truncate it
+ * intentionally so that the rest of the driver does not care.
+ */
+static u64 __read_sbdchn(struct sbd_port *sport, int reg)
+{
+	void __iomem *csr = sport->port.membase + reg;
+
+	return __raw_readq(csr);
+}
+
+static u64 __read_sbdshr(struct sbd_port *sport, int reg)
+{
+	void __iomem *csr = sport->memctrl + reg;
+
+	return __raw_readq(csr);
+}
+
+static void __write_sbdchn(struct sbd_port *sport, int reg, u64 value)
+{
+	void __iomem *csr = sport->port.membase + reg;
+
+	__raw_writeq(value, csr);
+}
+
+static void __write_sbdshr(struct sbd_port *sport, int reg, u64 value)
+{
+	void __iomem *csr = sport->memctrl + reg;
+
+	__raw_writeq(value, csr);
+}
+
+/*
+ * In bug 1956, we get glitches that can mess up uart registers.  This
+ * "read-mode-reg after any register access" is an accepted workaround.
+ */
+static void __war_sbd1956(struct sbd_port *sport)
+{
+	__read_sbdchn(sport, R_DUART_MODE_REG_1);
+	__read_sbdchn(sport, R_DUART_MODE_REG_2);
+}
+
+static unsigned char read_sbdchn(struct sbd_port *sport, int reg)
+{
+	unsigned char retval;
+
+	retval = __read_sbdchn(sport, reg);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+	return retval;
+}
+
+static unsigned char read_sbdshr(struct sbd_port *sport, int reg)
+{
+	unsigned char retval;
+
+	retval = __read_sbdshr(sport, reg);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+	return retval;
+}
+
+static void write_sbdchn(struct sbd_port *sport, int reg, unsigned int value)
+{
+	__write_sbdchn(sport, reg, value);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+}
+
+static void write_sbdshr(struct sbd_port *sport, int reg, unsigned int value)
+{
+	__write_sbdshr(sport, reg, value);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+}
+
+
+static int sbd_receive_ready(struct sbd_port *sport)
+{
+	return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_RX_RDY;
+}
+
+static int sbd_receive_drain(struct sbd_port *sport)
+{
+	int loops = 10000;
+
+	while (sbd_receive_ready(sport) && loops--)
+		read_sbdchn(sport, R_DUART_RX_HOLD);
+	return loops;
+}
+
+static int __unused sbd_transmit_ready(struct sbd_port *sport)
+{
+	return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_RDY;
+}
+
+static int __unused sbd_transmit_drain(struct sbd_port *sport)
+{
+	int loops = 10000;
+
+	while (!sbd_transmit_ready(sport) && loops--)
+		udelay(2);
+	return loops;
+}
+
+static int sbd_transmit_empty(struct sbd_port *sport)
+{
+	return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_EMT;
+}
+
+static int sbd_line_drain(struct sbd_port *sport)
+{
+	int loops = 10000;
+
+	while (!sbd_transmit_empty(sport) && loops--)
+		udelay(2);
+	return loops;
+}
+
+
+static unsigned int sbd_tx_empty(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	return sbd_transmit_empty(sport) ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int sbd_get_mctrl(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mctrl, status;
+
+	status = read_sbdshr(sport, R_DUART_IN_PORT);
+	status >>= (uport->line) % 2;
+	mctrl = (!(status & M_DUART_IN_PIN0_VAL) ? TIOCM_CTS : 0) |
+		(!(status & M_DUART_IN_PIN4_VAL) ? TIOCM_CAR : 0) |
+		(!(status & M_DUART_RIN0_PIN) ? TIOCM_RNG : 0) |
+		(!(status & M_DUART_IN_PIN2_VAL) ? TIOCM_DSR : 0);
+	return mctrl;
+}
+
+static void sbd_set_mctrl(struct uart_port *uport, unsigned int mctrl)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int clr = 0, set = 0, mode2;
+
+	if (mctrl & TIOCM_DTR)
+		set |= M_DUART_SET_OPR2;
+	else
+		clr |= M_DUART_CLR_OPR2;
+	if (mctrl & TIOCM_RTS)
+		set |= M_DUART_SET_OPR0;
+	else
+		clr |= M_DUART_CLR_OPR0;
+	clr <<= (uport->line) % 2;
+	set <<= (uport->line) % 2;
+
+	mode2 = read_sbdchn(sport, R_DUART_MODE_REG_2);
+	mode2 &= ~M_DUART_CHAN_MODE;
+	if (mctrl & TIOCM_LOOP)
+		mode2 |= V_DUART_CHAN_MODE_LCL_LOOP;
+	else
+		mode2 |= V_DUART_CHAN_MODE_NORMAL;
+
+	write_sbdshr(sport, R_DUART_CLEAR_OPR, clr);
+	write_sbdshr(sport, R_DUART_SET_OPR, set);
+	write_sbdchn(sport, R_DUART_MODE_REG_2, mode2);
+}
+
+static void sbd_stop_tx(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
+	sport->tx_stopped = 1;
+};
+
+static void sbd_start_tx(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mask;
+
+	/* Enable tx interrupts.  */
+	mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+	mask |= M_DUART_IMR_TX;
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+
+	/* Go!, go!, go!...  */
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
+	sport->tx_stopped = 0;
+};
+
+static void sbd_stop_rx(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
+};
+
+static void sbd_enable_ms(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdchn(sport, R_DUART_AUXCTL_X,
+		     M_DUART_CIN_CHNG_ENA | M_DUART_CTS_CHNG_ENA);
+}
+
+static void sbd_break_ctl(struct uart_port *uport, int break_state)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	if (break_state == -1)
+		write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_START_BREAK);
+	else
+		write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_STOP_BREAK);
+}
+
+
+static void sbd_receive_chars(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+	struct uart_icount *icount;
+	unsigned int status, ch, flag;
+	int count;
+
+	for (count = 16; count; count--) {
+		status = read_sbdchn(sport, R_DUART_STATUS);
+		if (!(status & M_DUART_RX_RDY))
+			break;
+
+		ch = read_sbdchn(sport, R_DUART_RX_HOLD);
+
+		flag = TTY_NORMAL;
+
+		icount = &uport->icount;
+		icount->rx++;
+
+		if (unlikely(status &
+			     (M_DUART_RCVD_BRK | M_DUART_FRM_ERR |
+			      M_DUART_PARITY_ERR | M_DUART_OVRUN_ERR))) {
+			if (status & M_DUART_RCVD_BRK) {
+				icount->brk++;
+				if (uart_handle_break(uport))
+					continue;
+			} else if (status & M_DUART_FRM_ERR)
+				icount->frame++;
+			else if (status & M_DUART_PARITY_ERR)
+				icount->parity++;
+			if (status & M_DUART_OVRUN_ERR)
+				icount->overrun++;
+
+			status &= uport->read_status_mask;
+			if (status & M_DUART_RCVD_BRK)
+				flag = TTY_BREAK;
+			else if (status & M_DUART_FRM_ERR)
+				flag = TTY_FRAME;
+			else if (status & M_DUART_PARITY_ERR)
+				flag = TTY_PARITY;
+		}
+
+		if (uart_handle_sysrq_char(uport, ch))
+			continue;
+
+		uart_insert_char(uport, status, M_DUART_OVRUN_ERR, ch, flag);
+	}
+
+	tty_flip_buffer_push(uport->info->tty);
+}
+
+static void sbd_transmit_chars(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+	struct circ_buf *xmit = &sport->port.info->xmit;
+	unsigned int mask;
+	int stop_tx;
+
+	/* XON/XOFF chars.  */
+	if (sport->port.x_char) {
+		write_sbdchn(sport, R_DUART_TX_HOLD, sport->port.x_char);
+		sport->port.icount.tx++;
+		sport->port.x_char = 0;
+		return;
+	}
+
+	/* If nothing to do or stopped or hardware stopped.  */
+	stop_tx = (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port));
+
+	/* Send char.  */
+	if (!stop_tx) {
+		write_sbdchn(sport, R_DUART_TX_HOLD, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		sport->port.icount.tx++;
+
+		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+			uart_write_wakeup(&sport->port);
+	}
+
+	/* Are we are done?  */
+	if (stop_tx || uart_circ_empty(xmit)) {
+		/* Disable tx interrupts.  */
+		mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+		mask &= ~M_DUART_IMR_TX;
+		write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+	}
+}
+
+static void sbd_status_handle(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+	unsigned int delta;
+
+	delta = read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
+	delta >>= (uport->line) % 2;
+
+	if (delta & (M_DUART_IN_PIN0_VAL << S_DUART_IN_PIN_CHNG))
+		uart_handle_cts_change(uport, !(delta & M_DUART_IN_PIN0_VAL));
+
+	if (delta & (M_DUART_IN_PIN2_VAL << S_DUART_IN_PIN_CHNG))
+		uport->icount.dsr++;
+
+	if (delta & ((M_DUART_IN_PIN2_VAL | M_DUART_IN_PIN0_VAL) <<
+		     S_DUART_IN_PIN_CHNG))
+		wake_up_interruptible(&uport->info->delta_msr_wait);
+}
+
+static irqreturn_t sbd_interrupt(int irq, void *dev_id)
+{
+	struct sbd_port *sport = dev_id;
+	struct uart_port *uport = &sport->port;
+	irqreturn_t status = IRQ_NONE;
+	unsigned int intstat;
+	int count;
+
+	for (count = 16; count; count--) {
+		intstat = read_sbdshr(sport,
+				      R_DUART_ISRREG((uport->line) % 2));
+		intstat &= read_sbdshr(sport,
+				       R_DUART_IMRREG((uport->line) % 2));
+		intstat &= M_DUART_ISR_ALL;
+		if (!intstat)
+			break;
+
+		if (intstat & M_DUART_ISR_RX)
+			sbd_receive_chars(sport);
+		if (intstat & M_DUART_ISR_IN)
+			sbd_status_handle(sport);
+		if (intstat & M_DUART_ISR_TX)
+			sbd_transmit_chars(sport);
+
+		status = IRQ_HANDLED;
+	}
+
+	return status;
+}
+
+
+static int sbd_startup(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mode1;
+	int ret;
+
+	ret = request_irq(sport->port.irq, sbd_interrupt,
+			  IRQF_SHARED, "sb1250-duart", sport);
+	if (ret)
+		return ret;
+
+	/* Clear the receive FIFO.  */
+	sbd_receive_drain(sport);
+
+	/* Clear the interrupt registers.  */
+	write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT);
+	read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
+
+	/* Set rx/tx interrupt to FIFO available.  */
+	mode1 = read_sbdchn(sport, R_DUART_MODE_REG_1);
+	mode1 &= ~(M_DUART_RX_IRQ_SEL_RXFULL | M_DUART_TX_IRQ_SEL_TXEMPT);
+	write_sbdchn(sport, R_DUART_MODE_REG_1, mode1);
+
+	/* Disable tx, enable rx.  */
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_EN);
+	sport->tx_stopped = 1;
+
+	/* Enable interrupts.  */
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
+		     M_DUART_IMR_IN | M_DUART_IMR_RX);
+
+	return 0;
+}
+
+static void sbd_shutdown(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
+	sport->tx_stopped = 1;
+	free_irq(sport->port.irq, sport);
+}
+
+
+static void sbd_init_port(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+
+	if (sport->initialised)
+		return;
+
+	/* There is no DUART reset feature, so just set some sane defaults.  */
+	write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_TX);
+	write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_RX);
+	write_sbdchn(sport, R_DUART_MODE_REG_1, V_DUART_BITS_PER_CHAR_8);
+	write_sbdchn(sport, R_DUART_MODE_REG_2, 0);
+	write_sbdchn(sport, R_DUART_FULL_CTL,
+		     V_DUART_INT_TIME(0) | V_DUART_SIG_FULL(15));
+	write_sbdchn(sport, R_DUART_OPCR_X, 0);
+	write_sbdchn(sport, R_DUART_AUXCTL_X, 0);
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
+
+	sport->initialised = 1;
+}
+
+static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios,
+			    struct ktermios *old_termios)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mode1 = 0, mode2 = 0, aux = 0;
+	unsigned int mode1mask = 0, mode2mask = 0, auxmask = 0;
+	unsigned int oldmode1, oldmode2, oldaux;
+	unsigned int baud, brg;
+	unsigned int command;
+
+	mode1mask |= ~(M_DUART_PARITY_MODE | M_DUART_PARITY_TYPE_ODD |
+		       M_DUART_BITS_PER_CHAR);
+	mode2mask |= ~M_DUART_STOP_BIT_LEN_2;
+	auxmask |= ~M_DUART_CTS_CHNG_ENA;
+
+	/* Byte size.  */
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+	case CS6:
+		/* Unsupported, leave unchanged.  */
+		mode1mask |= M_DUART_PARITY_MODE;
+		break;
+	case CS7:
+		mode1 |= V_DUART_BITS_PER_CHAR_7;
+		break;
+	case CS8:
+	default:
+		mode1 |= V_DUART_BITS_PER_CHAR_8;
+		break;
+	}
+
+	/* Parity and stop bits.  */
+	if (termios->c_cflag & CSTOPB)
+		mode2 |= M_DUART_STOP_BIT_LEN_2;
+	else
+		mode2 |= M_DUART_STOP_BIT_LEN_1;
+	if (termios->c_cflag & PARENB)
+		mode1 |= V_DUART_PARITY_MODE_ADD;
+	else
+		mode1 |= V_DUART_PARITY_MODE_NONE;
+	if (termios->c_cflag & PARODD)
+		mode1 |= M_DUART_PARITY_TYPE_ODD;
+	else
+		mode1 |= M_DUART_PARITY_TYPE_EVEN;
+
+	baud = uart_get_baud_rate(uport, termios, old_termios, 1200, 5000000);
+	brg = V_DUART_BAUD_RATE(baud);
+	/* The actual lower bound is 1221bps, so compensate.  */
+	if (brg > M_DUART_CLK_COUNTER)
+		brg = M_DUART_CLK_COUNTER;
+
+	uart_update_timeout(uport, termios->c_cflag, baud);
+
+	uport->read_status_mask = M_DUART_OVRUN_ERR;
+	if (termios->c_iflag & INPCK)
+		uport->read_status_mask |= M_DUART_FRM_ERR |
+					   M_DUART_PARITY_ERR;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		uport->read_status_mask |= M_DUART_RCVD_BRK;
+
+	uport->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		uport->ignore_status_mask |= M_DUART_FRM_ERR |
+					     M_DUART_PARITY_ERR;
+	if (termios->c_iflag & IGNBRK) {
+		uport->ignore_status_mask |= M_DUART_RCVD_BRK;
+		if (termios->c_iflag & IGNPAR)
+			uport->ignore_status_mask |= M_DUART_OVRUN_ERR;
+	}
+
+	if (termios->c_cflag & CREAD)
+		command = M_DUART_RX_EN;
+	else
+		command = M_DUART_RX_DIS;
+
+	if (termios->c_cflag & CRTSCTS)
+		aux |= M_DUART_CTS_CHNG_ENA;
+	else
+		aux &= ~M_DUART_CTS_CHNG_ENA;
+
+	spin_lock(&uport->lock);
+
+	if (sport->tx_stopped)
+		command |= M_DUART_TX_DIS;
+	else
+		command |= M_DUART_TX_EN;
+
+	oldmode1 = read_sbdchn(sport, R_DUART_MODE_REG_1) & mode1mask;
+	oldmode2 = read_sbdchn(sport, R_DUART_MODE_REG_2) & mode2mask;
+	oldaux = read_sbdchn(sport, R_DUART_AUXCTL_X) & auxmask;
+
+	if (!sport->tx_stopped)
+		sbd_line_drain(sport);
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
+
+	write_sbdchn(sport, R_DUART_MODE_REG_1, mode1 | oldmode1);
+	write_sbdchn(sport, R_DUART_MODE_REG_2, mode2 | oldmode2);
+	write_sbdchn(sport, R_DUART_CLK_SEL, brg);
+	write_sbdchn(sport, R_DUART_AUXCTL_X, aux | oldaux);
+
+	write_sbdchn(sport, R_DUART_CMD, command);
+
+	spin_unlock(&uport->lock);
+}
+
+
+static const char *sbd_type(struct uart_port *uport)
+{
+	return "SB1250 DUART";
+}
+
+static void sbd_release_port(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	struct sbd_duart *duart = sport->duart;
+	int map_guard;
+
+	iounmap(sport->memctrl);
+	sport->memctrl = NULL;
+	iounmap(uport->membase);
+	uport->membase = NULL;
+
+	map_guard = atomic_add_return(-1, &duart->map_guard);
+	if (!map_guard)
+		release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
+	release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
+}
+
+static int sbd_map_port(struct uart_port *uport)
+{
+	static const char *err = KERN_ERR "sbd: Cannot map MMIO\n";
+	struct sbd_port *sport = to_sport(uport);
+	struct sbd_duart *duart = sport->duart;
+
+	if (!uport->membase)
+		uport->membase = ioremap_nocache(uport->mapbase,
+						 DUART_CHANREG_SPACING);
+	if (!uport->membase) {
+		printk(err);
+		return -ENOMEM;
+	}
+
+	if (!sport->memctrl)
+		sport->memctrl = ioremap_nocache(duart->mapctrl,
+						 DUART_CHANREG_SPACING);
+	if (!sport->memctrl) {
+		printk(err);
+		iounmap(uport->membase);
+		uport->membase = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int sbd_request_port(struct uart_port *uport)
+{
+	static const char *err = KERN_ERR
+				 "sbd: Unable to reserve MMIO resource\n";
+	struct sbd_duart *duart = to_sport(uport)->duart;
+	int map_guard;
+	int ret = 0;
+
+	if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
+				"sb1250-duart")) {
+		printk(err);
+		return -EBUSY;
+	}
+	map_guard = atomic_add_return(1, &duart->map_guard);
+	if (map_guard == 1) {
+		if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
+					"sb1250-duart")) {
+			atomic_add(-1, &duart->map_guard);
+			printk(err);
+			ret = -EBUSY;
+		}
+	}
+	if (!ret) {
+		ret = sbd_map_port(uport);
+		if (ret) {
+			map_guard = atomic_add_return(-1, &duart->map_guard);
+			if (!map_guard)
+				release_mem_region(duart->mapctrl,
+						   DUART_CHANREG_SPACING);
+		}
+	}
+	if (ret) {
+		release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
+		return ret;
+	}
+	return 0;
+}
+
+static void sbd_config_port(struct uart_port *uport, int flags)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	if (flags & UART_CONFIG_TYPE) {
+		if (sbd_request_port(uport))
+			return;
+
+		uport->type = PORT_SB1250_DUART;
+
+		sbd_init_port(sport);
+	}
+}
+
+static int sbd_verify_port(struct uart_port *uport, struct serial_struct *ser)
+{
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_SB1250_DUART)
+		ret = -EINVAL;
+	if (ser->irq != uport->irq)
+		ret = -EINVAL;
+	if (ser->baud_base != uport->uartclk / 16)
+		ret = -EINVAL;
+	return ret;
+}
+
+
+static struct uart_ops sbd_ops = {
+	.tx_empty	= sbd_tx_empty,
+	.set_mctrl	= sbd_set_mctrl,
+	.get_mctrl	= sbd_get_mctrl,
+	.stop_tx	= sbd_stop_tx,
+	.start_tx	= sbd_start_tx,
+	.stop_rx	= sbd_stop_rx,
+	.enable_ms	= sbd_enable_ms,
+	.break_ctl	= sbd_break_ctl,
+	.startup	= sbd_startup,
+	.shutdown	= sbd_shutdown,
+	.set_termios	= sbd_set_termios,
+	.type		= sbd_type,
+	.release_port	= sbd_release_port,
+	.request_port	= sbd_request_port,
+	.config_port	= sbd_config_port,
+	.verify_port	= sbd_verify_port,
+};
+
+/* Initialize SB1250 DUART port structures.  */
+static void __init sbd_probe_duarts(void)
+{
+	static int probed;
+	int chip, side;
+	int max_lines, line;
+
+	if (probed)
+		return;
+
+	/* Set the number of available units based on the SOC type.  */
+	switch (soc_type) {
+	case K_SYS_SOC_TYPE_BCM1x55:
+	case K_SYS_SOC_TYPE_BCM1x80:
+		max_lines = 4;
+		break;
+	default:
+		/* Assume at least two serial ports at the normal address.  */
+		max_lines = 2;
+		break;
+	}
+
+	probed = 1;
+
+	for (chip = 0, line = 0; chip < DUART_MAX_CHIP && line < max_lines;
+	     chip++) {
+		sbd_duarts[chip].mapctrl = SBD_CTRLREGS(line);
+
+		for (side = 0; side < DUART_MAX_SIDE && line < max_lines;
+		     side++, line++) {
+			struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+			struct uart_port *uport = &sport->port;
+
+			sport->duart	= &sbd_duarts[chip];
+
+			uport->irq	= SBD_INT(line);
+			uport->uartclk	= 100000000 / 20 * 16;
+			uport->fifosize	= 16;
+			uport->iotype	= UPIO_MEM;
+			uport->flags	= UPF_BOOT_AUTOCONF;
+			uport->ops	= &sbd_ops;
+			uport->line	= line;
+			uport->mapbase	= SBD_CHANREGS(line);
+		}
+	}
+}
+
+
+#ifdef CONFIG_SERIAL_SB1250_DUART_CONSOLE
+/*
+ * Serial console stuff.  Very basic, polling driver for doing serial
+ * console output.  The console_sem is held by the caller, so we
+ * shouldn't be interrupted for more console activity.
+ */
+static void sbd_console_putchar(struct uart_port *uport, int ch)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	sbd_transmit_drain(sport);
+	write_sbdchn(sport, R_DUART_TX_HOLD, ch);
+}
+
+static void sbd_console_write(struct console *co, const char *s,
+			      unsigned int count)
+{
+	int chip = co->index / DUART_MAX_SIDE;
+	int side = co->index % DUART_MAX_SIDE;
+	struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+	struct uart_port *uport = &sport->port;
+	unsigned long flags;
+	unsigned int mask;
+
+	/* Disable transmit interrupts and enable the transmitter. */
+	spin_lock_irqsave(&uport->lock, flags);
+	mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
+		     mask & ~M_DUART_IMR_TX);
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	uart_console_write(&sport->port, s, count, sbd_console_putchar);
+
+	/* Restore transmit interrupts and the transmitter enable. */
+	spin_lock_irqsave(&uport->lock, flags);
+	sbd_line_drain(sport);
+	if (sport->tx_stopped)
+		write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+	spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+static int __init sbd_console_setup(struct console *co, char *options)
+{
+	int chip = co->index / DUART_MAX_SIDE;
+	int side = co->index % DUART_MAX_SIDE;
+	struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+	struct uart_port *uport = &sport->port;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+	int ret;
+
+	if (!sport->duart)
+		return -ENXIO;
+
+	ret = sbd_map_port(uport);
+	if (ret)
+		return ret;
+
+	sbd_init_port(sport);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	return uart_set_options(uport, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver sbd_reg;
+static struct console sbd_console = {
+	.name	= "duart",
+	.write	= sbd_console_write,
+	.device	= uart_console_device,
+	.setup	= sbd_console_setup,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+	.data	= &sbd_reg
+};
+
+static int __init sbd_serial_console_init(void)
+{
+	sbd_probe_duarts();
+	register_console(&sbd_console);
+
+	return 0;
+}
+
+console_initcall(sbd_serial_console_init);
+
+#define SERIAL_SB1250_DUART_CONSOLE	&sbd_console
+#else
+#define SERIAL_SB1250_DUART_CONSOLE	NULL
+#endif /* CONFIG_SERIAL_SB1250_DUART_CONSOLE */
+
+
+static struct uart_driver sbd_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "serial",
+	.dev_name	= "duart",
+	.major		= TTY_MAJOR,
+	.minor		= SB1250_DUART_MINOR_BASE,
+	.nr		= DUART_MAX_CHIP * DUART_MAX_SIDE,
+	.cons		= SERIAL_SB1250_DUART_CONSOLE,
+};
+
+/* Set up the driver and register it.  */
+static int __init sbd_init(void)
+{
+	int i, ret;
+
+	sbd_probe_duarts();
+
+	ret = uart_register_driver(&sbd_reg);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < DUART_MAX_CHIP * DUART_MAX_SIDE; i++) {
+		struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
+		struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
+		struct uart_port *uport = &sport->port;
+
+		if (sport->duart)
+			uart_add_one_port(&sbd_reg, uport);
+	}
+
+	return 0;
+}
+
+/* Unload the driver.  Unregister stuff, get ready to go away.  */
+static void __exit sbd_exit(void)
+{
+	int i;
+
+	for (i = DUART_MAX_CHIP * DUART_MAX_SIDE - 1; i >= 0; i--) {
+		struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
+		struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
+		struct uart_port *uport = &sport->port;
+
+		if (sport->duart)
+			uart_remove_one_port(&sbd_reg, uport);
+	}
+
+	uart_unregister_driver(&sbd_reg);
+}
+
+module_init(sbd_init);
+module_exit(sbd_exit);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 326020f..9c57486 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1910,6 +1910,12 @@
 	if (flow == 'r')
 		termios.c_cflag |= CRTSCTS;
 
+	/*
+	 * some uarts on other side don't support no flow control.
+	 * So we set * DTR in host uart to make them happy
+	 */
+	port->mctrl |= TIOCM_DTR;
+
 	port->ops->set_termios(port, &termios, NULL);
 	co->cflag = termios.c_cflag;
 
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 1f89496..672cd10 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -367,7 +367,9 @@
 	} else {
 #ifdef CONFIG_CPU_SUBTYPE_SH7343
 		/* Nothing */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+      defined(CONFIG_CPU_SUBTYPE_SHX3)
 		ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
 #else
 		ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index fb04fb5..247fb66 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -53,7 +53,12 @@
 # define SCIF_ORER 0x0001   /* overrun error bit */
 # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751R)
 # define SCSPTR1 0xffe0001c /* 8  bit SCI */
 # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -73,7 +78,7 @@
 # define SCPDR  0xA4050136        /* 16 bit SCIF */
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) 
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
 # define SCSPTR0 0xA4400000	  /* 16 bit SCIF */
 # define SCI_NPORTS 2
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -168,6 +173,14 @@
 # define SCIF_ORER 0x0001  /* overrun error bit */
 # define SCSCR_INIT(port)	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+# define SCSPTR0 0xffc30020		/* 16 bit SCIF */
+# define SCSPTR1 0xffc40020		/* 16 bit SCIF */
+# define SCSPTR2 0xffc50020		/* 16 bit SCIF */
+# define SCSPTR3 0xffc60020		/* 16 bit SCIF */
+# define SCIF_ORER 0x0001		/* Overrun error bit */
+# define SCSCR_INIT(port)	0x38	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
 #else
 # error CPU subtype not defined
 #endif
@@ -177,10 +190,15 @@
 #define SCI_CTRL_FLAGS_RIE  0x40 /* all */
 #define SCI_CTRL_FLAGS_TE   0x20 /* all */
 #define SCI_CTRL_FLAGS_RE   0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7751) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785)
+#if defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7780)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7785)  || \
+    defined(CONFIG_CPU_SUBTYPE_SHX3)
 #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
 #else
 #define SCI_CTRL_FLAGS_REIE 0
@@ -514,8 +532,12 @@
 	}
 }
 
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
       defined(CONFIG_CPU_SUBTYPE_SH4_202)
 static inline int sci_rxd_in(struct uart_port *port)
 {
@@ -653,6 +675,18 @@
 		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
 	return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+	if (port->mapbase == 0xffc30000)
+		return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xffc40000)
+		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xffc50000)
+		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xffc60000)
+		return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+}
 #endif
 
 /*
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index a27e9e9..41fc6126 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -759,7 +759,7 @@
  */
 
 static void sn_sal_console_write(struct console *, const char *, unsigned);
-static int __init sn_sal_console_setup(struct console *, char *);
+static int sn_sal_console_setup(struct console *, char *);
 static struct uart_driver sal_console_uart;
 extern struct tty_driver *uart_console_device(struct console *, int *);
 
@@ -1006,7 +1006,7 @@
  * here so providing it is easier.
  *
  */
-static int __init sn_sal_console_setup(struct console *co, char *options)
+static int sn_sal_console_setup(struct console *co, char *options)
 {
 	return 0;
 }
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 96557e6..d82be42 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -258,17 +258,7 @@
 /* port->lock held by caller.  */
 static void sunhv_start_tx(struct uart_port *port)
 {
-	struct circ_buf *xmit = &port->info->xmit;
-
-	while (!uart_circ_empty(xmit)) {
-		long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
-
-		if (status != HV_EOK)
-			break;
-
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		port->icount.tx++;
-	}
+	transmit_chars(port);
 }
 
 /* port->lock is not held.  */
@@ -440,8 +430,16 @@
 {
 	struct uart_port *port = sunhv_port;
 	unsigned long flags;
+	int locked = 1;
 
-	spin_lock_irqsave(&port->lock, flags);
+	local_irq_save(flags);
+	if (port->sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&port->lock);
+	} else
+		spin_lock(&port->lock);
+
 	while (n > 0) {
 		unsigned long ra = __pa(con_write_page);
 		unsigned long page_bytes;
@@ -469,7 +467,10 @@
 			ra += written;
 		}
 	}
-	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
 }
 
 static inline void sunhv_console_putchar(struct uart_port *port, char c)
@@ -488,7 +489,15 @@
 {
 	struct uart_port *port = sunhv_port;
 	unsigned long flags;
-	int i;
+	int i, locked = 1;
+
+	local_irq_save(flags);
+	if (port->sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&port->lock);
+	} else
+		spin_lock(&port->lock);
 
 	spin_lock_irqsave(&port->lock, flags);
 	for (i = 0; i < n; i++) {
@@ -496,7 +505,10 @@
 			sunhv_console_putchar(port, '\r');
 		sunhv_console_putchar(port, *s++);
 	}
-	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
 }
 
 static struct console sunhv_console = {
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index deb9ab4..8a0f9e4 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -860,22 +860,31 @@
 static void sunsab_console_putchar(struct uart_port *port, int c)
 {
 	struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
 
 	sunsab_tec_wait(up);
 	writeb(c, &up->regs->w.tic);
-
-	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static void sunsab_console_write(struct console *con, const char *s, unsigned n)
 {
 	struct uart_sunsab_port *up = &sunsab_ports[con->index];
+	unsigned long flags;
+	int locked = 1;
+
+	local_irq_save(flags);
+	if (up->port.sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&up->port.lock);
+	} else
+		spin_lock(&up->port.lock);
 
 	uart_console_write(&up->port, s, n, sunsab_console_putchar);
 	sunsab_tec_wait(up);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
 }
 
 static int sunsab_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 2a63cdb..26d720b 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1288,7 +1288,17 @@
 				unsigned int count)
 {
 	struct uart_sunsu_port *up = &sunsu_ports[co->index];
+	unsigned long flags;
 	unsigned int ier;
+	int locked = 1;
+
+	local_irq_save(flags);
+	if (up->port.sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&up->port.lock);
+	} else
+		spin_lock(&up->port.lock);
 
 	/*
 	 *	First save the UER then disable the interrupts
@@ -1304,6 +1314,10 @@
 	 */
 	wait_for_xmitr(up);
 	serial_out(up, UART_IER, ier);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
 }
 
 /*
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 15b6e1c..0a3e10a 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -9,7 +9,7 @@
  * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
  * work there.
  *
- *  Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/module.h>
@@ -1151,11 +1151,22 @@
 {
 	struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
 	unsigned long flags;
+	int locked = 1;
 
-	spin_lock_irqsave(&up->port.lock, flags);
+	local_irq_save(flags);
+	if (up->port.sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&up->port.lock);
+	} else
+		spin_lock(&up->port.lock);
+
 	uart_console_write(&up->port, s, count, sunzilog_putchar);
 	udelay(2);
-	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
 }
 
 static int __init sunzilog_console_setup(struct console *con, char *options)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5e3f748..b915711 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -107,6 +107,15 @@
 	  This enables using the Freescale iMX SPI controller in master
 	  mode.
 
+config SPI_LM70_LLP
+	tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
+	depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+	select SPI_BITBANG
+	help
+	  This driver supports the NS LM70 LLP Evaluation Board,
+	  which interfaces to an LM70 temperature sensor using
+	  a parallel port.
+
 config SPI_MPC52xx_PSC
 	tristate "Freescale MPC52xx PSC SPI controller"
 	depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
@@ -133,6 +142,12 @@
 	help
 	  This hooks up to the MicroWire controller on OMAP1 chips.
 
+config SPI_OMAP24XX
+	tristate "McSPI driver for OMAP24xx"
+	depends on SPI_MASTER && ARCH_OMAP24XX
+	help
+	  SPI master controller for OMAP24xx Multichannel SPI
+	  (McSPI) modules.
 
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
@@ -145,17 +160,36 @@
 config SPI_S3C24XX
 	tristate "Samsung S3C24XX series SPI"
 	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+	select SPI_BITBANG
 	help
 	  SPI driver for Samsung S3C24XX series ARM SoCs
 
 config SPI_S3C24XX_GPIO
 	tristate "Samsung S3C24XX series SPI by GPIO"
-	depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
+	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+	select SPI_BITBANG
 	help
 	  SPI driver for Samsung S3C24XX series ARM SoCs using
 	  GPIO lines to provide the SPI bus. This can be used where
 	  the inbuilt hardware cannot provide the transfer mode, or
 	  where the board is using non hardware connected pins.
+
+config SPI_TXX9
+	tristate "Toshiba TXx9 SPI controller"
+	depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+	help
+	  SPI driver for Toshiba TXx9 MIPS SoCs
+
+config SPI_XILINX
+	tristate "Xilinx SPI controller"
+	depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+	select SPI_BITBANG
+	help
+	  This exposes the SPI controller IP from the Xilinx EDK.
+
+	  See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
+	  Product Specification document (DS464) for hardware details.
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
@@ -187,6 +221,15 @@
 	  Note that this application programming interface is EXPERIMENTAL
 	  and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
 
+config SPI_TLE62X0
+	tristate "Infineon TLE62X0 (for power switching)"
+	depends on SPI_MASTER && SYSFS
+	help
+	  SPI driver for Infineon TLE62X0 series line driver chips,
+	  such as the TLE6220, TLE6230 and TLE6240.  This provides a
+	  sysfs interface, with each line presented as a kind of GPIO
+	  exposing both switch control and diagnostic feedback.
+
 #
 # Add new SPI protocol masters in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 5788d86..41fbac4 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,17 +17,22 @@
 obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
+obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
+obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC83xx)		+= spi_mpc83xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
+obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
+obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
 # 	... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
 obj-$(CONFIG_SPI_AT25)		+= at25.o
 obj-$(CONFIG_SPI_SPIDEV)	+= spidev.o
+obj-$(CONFIG_SPI_TLE62X0)	+= tle62x0.o
 # 	... add above this line ...
 
 # SPI slave controller drivers (upstream link)
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 8b2601d..ad14405 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -46,6 +46,7 @@
 	struct clk		*clk;
 	struct platform_device	*pdev;
 	unsigned		new_1:1;
+	struct spi_device	*stay;
 
 	u8			stopping;
 	struct list_head	queue;
@@ -62,29 +63,62 @@
 /*
  * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
  * they assume that spi slave device state will not change on deselect, so
- * that automagic deselection is OK.  Not so!  Workaround uses nCSx pins
- * as GPIOs; or newer controllers have CSAAT and friends.
+ * that automagic deselection is OK.  ("NPCSx rises if no data is to be
+ * transmitted")  Not so!  Workaround uses nCSx pins as GPIOs; or newer
+ * controllers have CSAAT and friends.
  *
- * Since the CSAAT functionality is a bit weird on newer controllers
- * as well, we use GPIO to control nCSx pins on all controllers.
+ * Since the CSAAT functionality is a bit weird on newer controllers as
+ * well, we use GPIO to control nCSx pins on all controllers, updating
+ * MR.PCS to avoid confusing the controller.  Using GPIOs also lets us
+ * support active-high chipselects despite the controller's belief that
+ * only active-low devices/systems exists.
+ *
+ * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
+ * right when driven with GPIO.  ("Mode Fault does not allow more than one
+ * Master on Chip Select 0.")  No workaround exists for that ... so for
+ * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
+ * and (c) will trigger that first erratum in some cases.
  */
 
-static inline void cs_activate(struct spi_device *spi)
+static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 {
 	unsigned gpio = (unsigned) spi->controller_data;
 	unsigned active = spi->mode & SPI_CS_HIGH;
+	u32 mr;
 
-	dev_dbg(&spi->dev, "activate %u%s\n", gpio, active ? " (high)" : "");
-	gpio_set_value(gpio, active);
+	mr = spi_readl(as, MR);
+	mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
+
+	dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
+			gpio, active ? " (high)" : "",
+			mr);
+
+	if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+		gpio_set_value(gpio, active);
+	spi_writel(as, MR, mr);
 }
 
-static inline void cs_deactivate(struct spi_device *spi)
+static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 {
 	unsigned gpio = (unsigned) spi->controller_data;
 	unsigned active = spi->mode & SPI_CS_HIGH;
+	u32 mr;
 
-	dev_dbg(&spi->dev, "DEactivate %u%s\n", gpio, active ? " (low)" : "");
-	gpio_set_value(gpio, !active);
+	/* only deactivate *this* device; sometimes transfers to
+	 * another device may be active when this routine is called.
+	 */
+	mr = spi_readl(as, MR);
+	if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) {
+		mr = SPI_BFINS(PCS, 0xf, mr);
+		spi_writel(as, MR, mr);
+	}
+
+	dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
+			gpio, active ? " (low)" : "",
+			mr);
+
+	if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+		gpio_set_value(gpio, !active);
 }
 
 /*
@@ -140,6 +174,7 @@
 
 	/* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
 	 * mechanism might help avoid the IRQ latency between transfers
+	 * (and improve the nCS0 errata handling on at91rm9200 chips)
 	 *
 	 * We're also waiting for ENDRX before we start the next
 	 * transfer because we need to handle some difficult timing
@@ -169,33 +204,62 @@
 {
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 	struct spi_message	*msg;
-	u32			mr;
+	struct spi_device	*spi;
 
 	BUG_ON(as->current_transfer);
 
 	msg = list_entry(as->queue.next, struct spi_message, queue);
+	spi = msg->spi;
 
-	/* Select the chip */
-	mr = spi_readl(as, MR);
-	mr = SPI_BFINS(PCS, ~(1 << msg->spi->chip_select), mr);
-	spi_writel(as, MR, mr);
-	cs_activate(msg->spi);
+	dev_dbg(master->cdev.dev, "start message %p for %s\n",
+			msg, spi->dev.bus_id);
+
+	/* select chip if it's not still active */
+	if (as->stay) {
+		if (as->stay != spi) {
+			cs_deactivate(as, as->stay);
+			cs_activate(as, spi);
+		}
+		as->stay = NULL;
+	} else
+		cs_activate(as, spi);
 
 	atmel_spi_next_xfer(master, msg);
 }
 
-static void
+/*
+ * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
+ *  - The buffer is either valid for CPU access, else NULL
+ *  - If the buffer is valid, so is its DMA addresss
+ *
+ * This driver manages the dma addresss unless message->is_dma_mapped.
+ */
+static int
 atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
 {
+	struct device	*dev = &as->pdev->dev;
+
 	xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
-	if (xfer->tx_buf)
-		xfer->tx_dma = dma_map_single(&as->pdev->dev,
+	if (xfer->tx_buf) {
+		xfer->tx_dma = dma_map_single(dev,
 				(void *) xfer->tx_buf, xfer->len,
 				DMA_TO_DEVICE);
-	if (xfer->rx_buf)
-		xfer->rx_dma = dma_map_single(&as->pdev->dev,
+		if (dma_mapping_error(xfer->tx_dma))
+			return -ENOMEM;
+	}
+	if (xfer->rx_buf) {
+		xfer->rx_dma = dma_map_single(dev,
 				xfer->rx_buf, xfer->len,
 				DMA_FROM_DEVICE);
+		if (dma_mapping_error(xfer->tx_dma)) {
+			if (xfer->tx_buf)
+				dma_unmap_single(dev,
+						xfer->tx_dma, xfer->len,
+						DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+	}
+	return 0;
 }
 
 static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
@@ -211,9 +275,13 @@
 
 static void
 atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
-		   struct spi_message *msg, int status)
+		struct spi_message *msg, int status, int stay)
 {
-	cs_deactivate(msg->spi);
+	if (!stay || status < 0)
+		cs_deactivate(as, msg->spi);
+	else
+		as->stay = msg->spi;
+
 	list_del(&msg->queue);
 	msg->status = status;
 
@@ -303,7 +371,7 @@
 		/* Clear any overrun happening while cleaning up */
 		spi_readl(as, SR);
 
-		atmel_spi_msg_done(master, as, msg, -EIO);
+		atmel_spi_msg_done(master, as, msg, -EIO, 0);
 	} else if (pending & SPI_BIT(ENDRX)) {
 		ret = IRQ_HANDLED;
 
@@ -321,12 +389,13 @@
 
 			if (msg->transfers.prev == &xfer->transfer_list) {
 				/* report completed message */
-				atmel_spi_msg_done(master, as, msg, 0);
+				atmel_spi_msg_done(master, as, msg, 0,
+						xfer->cs_change);
 			} else {
 				if (xfer->cs_change) {
-					cs_deactivate(msg->spi);
+					cs_deactivate(as, msg->spi);
 					udelay(1);
-					cs_activate(msg->spi);
+					cs_activate(as, msg->spi);
 				}
 
 				/*
@@ -350,6 +419,7 @@
 	return ret;
 }
 
+/* the spi->mode bits understood by this driver: */
 #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
 
 static int atmel_spi_setup(struct spi_device *spi)
@@ -388,6 +458,14 @@
 		return -EINVAL;
 	}
 
+	/* see notes above re chipselect */
+	if (cpu_is_at91rm9200()
+			&& spi->chip_select == 0
+			&& (spi->mode & SPI_CS_HIGH)) {
+		dev_dbg(&spi->dev, "setup: can't be active-high\n");
+		return -EINVAL;
+	}
+
 	/* speed zero convention is used by some upper layers */
 	bus_hz = clk_get_rate(as->clk);
 	if (spi->max_speed_hz) {
@@ -397,8 +475,9 @@
 		scbr = ((bus_hz + spi->max_speed_hz - 1)
 			/ spi->max_speed_hz);
 		if (scbr >= (1 << SPI_SCBR_SIZE)) {
-			dev_dbg(&spi->dev, "setup: %d Hz too slow, scbr %u\n",
-					spi->max_speed_hz, scbr);
+			dev_dbg(&spi->dev,
+				"setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+				spi->max_speed_hz, scbr, bus_hz/255);
 			return -EINVAL;
 		}
 	} else
@@ -423,6 +502,14 @@
 			return ret;
 		spi->controller_state = (void *)npcs_pin;
 		gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
+	} else {
+		unsigned long		flags;
+
+		spin_lock_irqsave(&as->lock, flags);
+		if (as->stay == spi)
+			as->stay = NULL;
+		cs_deactivate(as, spi);
+		spin_unlock_irqrestore(&as->lock, flags);
 	}
 
 	dev_dbg(&spi->dev,
@@ -464,14 +551,22 @@
 			dev_dbg(&spi->dev, "no protocol options yet\n");
 			return -ENOPROTOOPT;
 		}
+
+		/*
+		 * DMA map early, for performance (empties dcache ASAP) and
+		 * better fault reporting.  This is a DMA-only driver.
+		 *
+		 * NOTE that if dma_unmap_single() ever starts to do work on
+		 * platforms supported by this driver, we would need to clean
+		 * up mappings for previously-mapped transfers.
+		 */
+		if (!msg->is_dma_mapped) {
+			if (atmel_spi_dma_map_xfer(as, xfer) < 0)
+				return -ENOMEM;
+		}
 	}
 
-	/* scrub dcache "early" */
-	if (!msg->is_dma_mapped) {
-		list_for_each_entry(xfer, &msg->transfers, transfer_list)
-			atmel_spi_dma_map_xfer(as, xfer);
-	}
-
+#ifdef VERBOSE
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		dev_dbg(controller,
 			"  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
@@ -479,6 +574,7 @@
 			xfer->tx_buf, xfer->tx_dma,
 			xfer->rx_buf, xfer->rx_dma);
 	}
+#endif
 
 	msg->status = -EINPROGRESS;
 	msg->actual_length = 0;
@@ -494,8 +590,21 @@
 
 static void atmel_spi_cleanup(struct spi_device *spi)
 {
-	if (spi->controller_state)
-		gpio_free((unsigned int)spi->controller_data);
+	struct atmel_spi	*as = spi_master_get_devdata(spi->master);
+	unsigned		gpio = (unsigned) spi->controller_data;
+	unsigned long		flags;
+
+	if (!spi->controller_state)
+		return;
+
+	spin_lock_irqsave(&as->lock, flags);
+	if (as->stay == spi) {
+		as->stay = NULL;
+		cs_deactivate(as, spi);
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+
+	gpio_free(gpio);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -536,6 +645,10 @@
 
 	as = spi_master_get_devdata(master);
 
+	/*
+	 * Scratch buffer is used for throwaway rx and tx data.
+	 * It's coherent to minimize dcache pollution.
+	 */
 	as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
 					&as->buffer_dma, GFP_KERNEL);
 	if (!as->buffer)
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index ae2b1af..c47a650 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -280,6 +280,9 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
 static int au1550_spi_setup(struct spi_device *spi)
 {
 	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
@@ -292,6 +295,12 @@
 		return -EINVAL;
 	}
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (spi->max_speed_hz == 0)
 		spi->max_speed_hz = hw->freq_max;
 	if (spi->max_speed_hz > hw->freq_max
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 11f36be..d2a4b2b 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -270,6 +270,9 @@
 	spin_unlock_irq(&mps->lock);
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
 static int mpc52xx_psc_spi_setup(struct spi_device *spi)
 {
 	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
@@ -279,6 +282,12 @@
 	if (spi->bits_per_word%8)
 		return -EINVAL;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (!cs) {
 		cs = kzalloc(sizeof *cs, GFP_KERNEL);
 		if (!cs)
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
new file mode 100644
index 0000000..6b357cd
--- /dev/null
+++ b/drivers/spi/omap2_mcspi.c
@@ -0,0 +1,1081 @@
+/*
+ * OMAP2 McSPI controller driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ * Author:	Samuel Ortiz <samuel.ortiz@nokia.com> and
+ *		Juha Yrjölä <juha.yrjola@nokia.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
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <linux/spi/spi.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/clock.h>
+
+
+#define OMAP2_MCSPI_MAX_FREQ		48000000
+
+#define OMAP2_MCSPI_REVISION		0x00
+#define OMAP2_MCSPI_SYSCONFIG		0x10
+#define OMAP2_MCSPI_SYSSTATUS		0x14
+#define OMAP2_MCSPI_IRQSTATUS		0x18
+#define OMAP2_MCSPI_IRQENABLE		0x1c
+#define OMAP2_MCSPI_WAKEUPENABLE	0x20
+#define OMAP2_MCSPI_SYST		0x24
+#define OMAP2_MCSPI_MODULCTRL		0x28
+
+/* per-channel banks, 0x14 bytes each, first is: */
+#define OMAP2_MCSPI_CHCONF0		0x2c
+#define OMAP2_MCSPI_CHSTAT0		0x30
+#define OMAP2_MCSPI_CHCTRL0		0x34
+#define OMAP2_MCSPI_TX0			0x38
+#define OMAP2_MCSPI_RX0			0x3c
+
+/* per-register bitmasks: */
+
+#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE	(1 << 0)
+#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET	(1 << 1)
+
+#define OMAP2_MCSPI_SYSSTATUS_RESETDONE	(1 << 0)
+
+#define OMAP2_MCSPI_MODULCTRL_SINGLE	(1 << 0)
+#define OMAP2_MCSPI_MODULCTRL_MS	(1 << 2)
+#define OMAP2_MCSPI_MODULCTRL_STEST	(1 << 3)
+
+#define OMAP2_MCSPI_CHCONF_PHA		(1 << 0)
+#define OMAP2_MCSPI_CHCONF_POL		(1 << 1)
+#define OMAP2_MCSPI_CHCONF_CLKD_MASK	(0x0f << 2)
+#define OMAP2_MCSPI_CHCONF_EPOL		(1 << 6)
+#define OMAP2_MCSPI_CHCONF_WL_MASK	(0x1f << 7)
+#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY	(0x01 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY	(0x02 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_MASK	(0x03 << 12)
+#define OMAP2_MCSPI_CHCONF_DMAW		(1 << 14)
+#define OMAP2_MCSPI_CHCONF_DMAR		(1 << 15)
+#define OMAP2_MCSPI_CHCONF_DPE0		(1 << 16)
+#define OMAP2_MCSPI_CHCONF_DPE1		(1 << 17)
+#define OMAP2_MCSPI_CHCONF_IS		(1 << 18)
+#define OMAP2_MCSPI_CHCONF_TURBO	(1 << 19)
+#define OMAP2_MCSPI_CHCONF_FORCE	(1 << 20)
+
+#define OMAP2_MCSPI_CHSTAT_RXS		(1 << 0)
+#define OMAP2_MCSPI_CHSTAT_TXS		(1 << 1)
+#define OMAP2_MCSPI_CHSTAT_EOT		(1 << 2)
+
+#define OMAP2_MCSPI_CHCTRL_EN		(1 << 0)
+
+
+/* We have 2 DMA channels per CS, one for RX and one for TX */
+struct omap2_mcspi_dma {
+	int dma_tx_channel;
+	int dma_rx_channel;
+
+	int dma_tx_sync_dev;
+	int dma_rx_sync_dev;
+
+	struct completion dma_tx_completion;
+	struct completion dma_rx_completion;
+};
+
+/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+ * cache operations; better heuristics consider wordsize and bitrate.
+ */
+#define DMA_MIN_BYTES			8
+
+
+struct omap2_mcspi {
+	struct work_struct	work;
+	/* lock protects queue and registers */
+	spinlock_t		lock;
+	struct list_head	msg_queue;
+	struct spi_master	*master;
+	struct clk		*ick;
+	struct clk		*fck;
+	/* Virtual base address of the controller */
+	void __iomem		*base;
+	/* SPI1 has 4 channels, while SPI2 has 2 */
+	struct omap2_mcspi_dma	*dma_channels;
+};
+
+struct omap2_mcspi_cs {
+	void __iomem		*base;
+	int			word_len;
+};
+
+static struct workqueue_struct *omap2_mcspi_wq;
+
+#define MOD_REG_BIT(val, mask, set) do { \
+	if (set) \
+		val |= mask; \
+	else \
+		val &= ~mask; \
+} while (0)
+
+static inline void mcspi_write_reg(struct spi_master *master,
+		int idx, u32 val)
+{
+	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+	__raw_writel(val, mcspi->base + idx);
+}
+
+static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
+{
+	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+	return __raw_readl(mcspi->base + idx);
+}
+
+static inline void mcspi_write_cs_reg(const struct spi_device *spi,
+		int idx, u32 val)
+{
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	__raw_writel(val, cs->base +  idx);
+}
+
+static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
+{
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	return __raw_readl(cs->base + idx);
+}
+
+static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
+		int is_read, int enable)
+{
+	u32 l, rw;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+
+	if (is_read) /* 1 is read, 0 write */
+		rw = OMAP2_MCSPI_CHCONF_DMAR;
+	else
+		rw = OMAP2_MCSPI_CHCONF_DMAW;
+
+	MOD_REG_BIT(l, rw, enable);
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+}
+
+static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
+{
+	u32 l;
+
+	l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
+}
+
+static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
+{
+	u32 l;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+}
+
+static void omap2_mcspi_set_master_mode(struct spi_master *master)
+{
+	u32 l;
+
+	/* setup when switching from (reset default) slave mode
+	 * to single-channel master mode
+	 */
+	l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
+}
+
+static unsigned
+omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	struct omap2_mcspi_dma  *mcspi_dma;
+	unsigned int		count, c;
+	unsigned long		base, tx_reg, rx_reg;
+	int			word_len, data_type, element_count;
+	u8			* rx;
+	const u8		* tx;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+	count = xfer->len;
+	c = count;
+	word_len = cs->word_len;
+
+	base = (unsigned long) io_v2p(cs->base);
+	tx_reg = base + OMAP2_MCSPI_TX0;
+	rx_reg = base + OMAP2_MCSPI_RX0;
+	rx = xfer->rx_buf;
+	tx = xfer->tx_buf;
+
+	if (word_len <= 8) {
+		data_type = OMAP_DMA_DATA_TYPE_S8;
+		element_count = count;
+	} else if (word_len <= 16) {
+		data_type = OMAP_DMA_DATA_TYPE_S16;
+		element_count = count >> 1;
+	} else /* word_len <= 32 */ {
+		data_type = OMAP_DMA_DATA_TYPE_S32;
+		element_count = count >> 2;
+	}
+
+	if (tx != NULL) {
+		omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel,
+				data_type, element_count, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				mcspi_dma->dma_tx_sync_dev, 0);
+
+		omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				tx_reg, 0, 0);
+
+		omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
+				OMAP_DMA_AMODE_POST_INC,
+				xfer->tx_dma, 0, 0);
+	}
+
+	if (rx != NULL) {
+		omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
+				data_type, element_count, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				mcspi_dma->dma_rx_sync_dev, 1);
+
+		omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				rx_reg, 0, 0);
+
+		omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
+				OMAP_DMA_AMODE_POST_INC,
+				xfer->rx_dma, 0, 0);
+	}
+
+	if (tx != NULL) {
+		omap_start_dma(mcspi_dma->dma_tx_channel);
+		omap2_mcspi_set_dma_req(spi, 0, 1);
+	}
+
+	if (rx != NULL) {
+		omap_start_dma(mcspi_dma->dma_rx_channel);
+		omap2_mcspi_set_dma_req(spi, 1, 1);
+	}
+
+	if (tx != NULL) {
+		wait_for_completion(&mcspi_dma->dma_tx_completion);
+		dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+	}
+
+	if (rx != NULL) {
+		wait_for_completion(&mcspi_dma->dma_rx_completion);
+		dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
+	}
+	return count;
+}
+
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (!(__raw_readl(reg) & bit)) {
+		if (time_after(jiffies, timeout))
+			return -1;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static unsigned
+omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	unsigned int		count, c;
+	u32			l;
+	void __iomem		*base = cs->base;
+	void __iomem		*tx_reg;
+	void __iomem		*rx_reg;
+	void __iomem		*chstat_reg;
+	int			word_len;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	count = xfer->len;
+	c = count;
+	word_len = cs->word_len;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+
+	/* We store the pre-calculated register addresses on stack to speed
+	 * up the transfer loop. */
+	tx_reg		= base + OMAP2_MCSPI_TX0;
+	rx_reg		= base + OMAP2_MCSPI_RX0;
+	chstat_reg	= base + OMAP2_MCSPI_CHSTAT0;
+
+	if (word_len <= 8) {
+		u8		*rx;
+		const u8	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+
+		do {
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "write-%d %02x\n",
+						word_len, *tx);
+#endif
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+				/* prevent last RX_ONLY read from triggering
+				 * more word i/o: switch to rx+tx
+				 */
+				if (c == 0 && tx == NULL)
+					mcspi_write_cs_reg(spi,
+							OMAP2_MCSPI_CHCONF0, l);
+				*rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "read-%d %02x\n",
+						word_len, *(rx - 1));
+#endif
+			}
+			c -= 1;
+		} while (c);
+	} else if (word_len <= 16) {
+		u16		*rx;
+		const u16	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "write-%d %04x\n",
+						word_len, *tx);
+#endif
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+				/* prevent last RX_ONLY read from triggering
+				 * more word i/o: switch to rx+tx
+				 */
+				if (c == 0 && tx == NULL)
+					mcspi_write_cs_reg(spi,
+							OMAP2_MCSPI_CHCONF0, l);
+				*rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "read-%d %04x\n",
+						word_len, *(rx - 1));
+#endif
+			}
+			c -= 2;
+		} while (c);
+	} else if (word_len <= 32) {
+		u32		*rx;
+		const u32	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "write-%d %04x\n",
+						word_len, *tx);
+#endif
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+				/* prevent last RX_ONLY read from triggering
+				 * more word i/o: switch to rx+tx
+				 */
+				if (c == 0 && tx == NULL)
+					mcspi_write_cs_reg(spi,
+							OMAP2_MCSPI_CHCONF0, l);
+				*rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "read-%d %04x\n",
+						word_len, *(rx - 1));
+#endif
+			}
+			c -= 4;
+		} while (c);
+	}
+
+	/* for TX_ONLY mode, be sure all words have shifted out */
+	if (xfer->rx_buf == NULL) {
+		if (mcspi_wait_for_reg_bit(chstat_reg,
+				OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+			dev_err(&spi->dev, "TXS timed out\n");
+		} else if (mcspi_wait_for_reg_bit(chstat_reg,
+				OMAP2_MCSPI_CHSTAT_EOT) < 0)
+			dev_err(&spi->dev, "EOT timed out\n");
+	}
+out:
+	return count - c;
+}
+
+/* called only when no transfer is active to this device */
+static int omap2_mcspi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct omap2_mcspi_cs *cs = spi->controller_state;
+	struct omap2_mcspi *mcspi;
+	u32 l = 0, div = 0;
+	u8 word_len = spi->bits_per_word;
+
+	mcspi = spi_master_get_devdata(spi->master);
+
+	if (t != NULL && t->bits_per_word)
+		word_len = t->bits_per_word;
+
+	cs->word_len = word_len;
+
+	if (spi->max_speed_hz) {
+		while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div))
+					> spi->max_speed_hz)
+			div++;
+	} else
+		div = 15;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+
+	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
+	 * REVISIT: this controller could support SPI_3WIRE mode.
+	 */
+	l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
+	l |= OMAP2_MCSPI_CHCONF_DPE0;
+
+	/* wordlength */
+	l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
+	l |= (word_len - 1) << 7;
+
+	/* set chipselect polarity; manage with FORCE */
+	if (!(spi->mode & SPI_CS_HIGH))
+		l |= OMAP2_MCSPI_CHCONF_EPOL;	/* active-low; normal */
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_EPOL;
+
+	/* set clock divisor */
+	l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
+	l |= div << 2;
+
+	/* set SPI mode 0..3 */
+	if (spi->mode & SPI_CPOL)
+		l |= OMAP2_MCSPI_CHCONF_POL;
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_POL;
+	if (spi->mode & SPI_CPHA)
+		l |= OMAP2_MCSPI_CHCONF_PHA;
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_PHA;
+
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+
+	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
+			OMAP2_MCSPI_MAX_FREQ / (1 << div),
+			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
+			(spi->mode & SPI_CPOL) ? "inverted" : "normal");
+
+	return 0;
+}
+
+static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data)
+{
+	struct spi_device	*spi = data;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+	complete(&mcspi_dma->dma_rx_completion);
+
+	/* We must disable the DMA RX request */
+	omap2_mcspi_set_dma_req(spi, 1, 0);
+}
+
+static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data)
+{
+	struct spi_device	*spi = data;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+	complete(&mcspi_dma->dma_tx_completion);
+
+	/* We must disable the DMA TX request */
+	omap2_mcspi_set_dma_req(spi, 0, 0);
+}
+
+static int omap2_mcspi_request_dma(struct spi_device *spi)
+{
+	struct spi_master	*master = spi->master;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(master);
+	mcspi_dma = mcspi->dma_channels + spi->chip_select;
+
+	if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX",
+			omap2_mcspi_dma_rx_callback, spi,
+			&mcspi_dma->dma_rx_channel)) {
+		dev_err(&spi->dev, "no RX DMA channel for McSPI\n");
+		return -EAGAIN;
+	}
+
+	if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX",
+			omap2_mcspi_dma_tx_callback, spi,
+			&mcspi_dma->dma_tx_channel)) {
+		omap_free_dma(mcspi_dma->dma_rx_channel);
+		mcspi_dma->dma_rx_channel = -1;
+		dev_err(&spi->dev, "no TX DMA channel for McSPI\n");
+		return -EAGAIN;
+	}
+
+	init_completion(&mcspi_dma->dma_rx_completion);
+	init_completion(&mcspi_dma->dma_tx_completion);
+
+	return 0;
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
+static int omap2_mcspi_setup(struct spi_device *spi)
+{
+	int			ret;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
+	if (spi->bits_per_word == 0)
+		spi->bits_per_word = 8;
+	else if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
+		dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
+			spi->bits_per_word);
+		return -EINVAL;
+	}
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		cs->base = mcspi->base + spi->chip_select * 0x14;
+		spi->controller_state = cs;
+	}
+
+	if (mcspi_dma->dma_rx_channel == -1
+			|| mcspi_dma->dma_tx_channel == -1) {
+		ret = omap2_mcspi_request_dma(spi);
+		if (ret < 0)
+			return ret;
+	}
+
+	clk_enable(mcspi->ick);
+	clk_enable(mcspi->fck);
+	ret =  omap2_mcspi_setup_transfer(spi, NULL);
+	clk_disable(mcspi->fck);
+	clk_disable(mcspi->ick);
+
+	return ret;
+}
+
+static void omap2_mcspi_cleanup(struct spi_device *spi)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+	kfree(spi->controller_state);
+
+	if (mcspi_dma->dma_rx_channel != -1) {
+		omap_free_dma(mcspi_dma->dma_rx_channel);
+		mcspi_dma->dma_rx_channel = -1;
+	}
+	if (mcspi_dma->dma_tx_channel != -1) {
+		omap_free_dma(mcspi_dma->dma_tx_channel);
+		mcspi_dma->dma_tx_channel = -1;
+	}
+}
+
+static void omap2_mcspi_work(struct work_struct *work)
+{
+	struct omap2_mcspi	*mcspi;
+
+	mcspi = container_of(work, struct omap2_mcspi, work);
+	spin_lock_irq(&mcspi->lock);
+
+	clk_enable(mcspi->ick);
+	clk_enable(mcspi->fck);
+
+	/* We only enable one channel at a time -- the one whose message is
+	 * at the head of the queue -- although this controller would gladly
+	 * arbitrate among multiple channels.  This corresponds to "single
+	 * channel" master mode.  As a side effect, we need to manage the
+	 * chipselect with the FORCE bit ... CS != channel enable.
+	 */
+	while (!list_empty(&mcspi->msg_queue)) {
+		struct spi_message		*m;
+		struct spi_device		*spi;
+		struct spi_transfer		*t = NULL;
+		int				cs_active = 0;
+		struct omap2_mcspi_device_config *conf;
+		struct omap2_mcspi_cs		*cs;
+		int				par_override = 0;
+		int				status = 0;
+		u32				chconf;
+
+		m = container_of(mcspi->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mcspi->lock);
+
+		spi = m->spi;
+		conf = spi->controller_data;
+		cs = spi->controller_state;
+
+		omap2_mcspi_set_enable(spi, 1);
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+				status = -EINVAL;
+				break;
+			}
+			if (par_override || t->speed_hz || t->bits_per_word) {
+				par_override = 1;
+				status = omap2_mcspi_setup_transfer(spi, t);
+				if (status < 0)
+					break;
+				if (!t->speed_hz && !t->bits_per_word)
+					par_override = 0;
+			}
+
+			if (!cs_active) {
+				omap2_mcspi_force_cs(spi, 1);
+				cs_active = 1;
+			}
+
+			chconf = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+			chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+			if (t->tx_buf == NULL)
+				chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
+			else if (t->rx_buf == NULL)
+				chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
+			mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, chconf);
+
+			if (t->len) {
+				unsigned	count;
+
+				/* RX_ONLY mode needs dummy data in TX reg */
+				if (t->tx_buf == NULL)
+					__raw_writel(0, cs->base
+							+ OMAP2_MCSPI_TX0);
+
+				if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
+					count = omap2_mcspi_txrx_dma(spi, t);
+				else
+					count = omap2_mcspi_txrx_pio(spi, t);
+				m->actual_length += count;
+
+				if (count != t->len) {
+					status = -EIO;
+					break;
+				}
+			}
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			/* ignore the "leave it on after last xfer" hint */
+			if (t->cs_change) {
+				omap2_mcspi_force_cs(spi, 0);
+				cs_active = 0;
+			}
+		}
+
+		/* Restore defaults if they were overriden */
+		if (par_override) {
+			par_override = 0;
+			status = omap2_mcspi_setup_transfer(spi, NULL);
+		}
+
+		if (cs_active)
+			omap2_mcspi_force_cs(spi, 0);
+
+		omap2_mcspi_set_enable(spi, 0);
+
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock_irq(&mcspi->lock);
+	}
+
+	clk_disable(mcspi->fck);
+	clk_disable(mcspi->ick);
+
+	spin_unlock_irq(&mcspi->lock);
+}
+
+static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct omap2_mcspi	*mcspi;
+	unsigned long		flags;
+	struct spi_transfer	*t;
+
+	m->actual_length = 0;
+	m->status = 0;
+
+	/* reject invalid messages and transfers */
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		const void	*tx_buf = t->tx_buf;
+		void		*rx_buf = t->rx_buf;
+		unsigned	len = t->len;
+
+		if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
+				|| (len && !(rx_buf || tx_buf))
+				|| (t->bits_per_word &&
+					(  t->bits_per_word < 4
+					|| t->bits_per_word > 32))) {
+			dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
+					t->speed_hz,
+					len,
+					tx_buf ? "tx" : "",
+					rx_buf ? "rx" : "",
+					t->bits_per_word);
+			return -EINVAL;
+		}
+		if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) {
+			dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
+					t->speed_hz,
+					OMAP2_MCSPI_MAX_FREQ/(1<<16));
+			return -EINVAL;
+		}
+
+		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
+			continue;
+
+		/* Do DMA mapping "early" for better error reporting and
+		 * dcache use.  Note that if dma_unmap_single() ever starts
+		 * to do real work on ARM, we'd need to clean up mappings
+		 * for previous transfers on *ALL* exits of this loop...
+		 */
+		if (tx_buf != NULL) {
+			t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
+					len, DMA_TO_DEVICE);
+			if (dma_mapping_error(t->tx_dma)) {
+				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+						'T', len);
+				return -EINVAL;
+			}
+		}
+		if (rx_buf != NULL) {
+			t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len,
+					DMA_FROM_DEVICE);
+			if (dma_mapping_error(t->rx_dma)) {
+				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+						'R', len);
+				if (tx_buf != NULL)
+					dma_unmap_single(NULL, t->tx_dma,
+							len, DMA_TO_DEVICE);
+				return -EINVAL;
+			}
+		}
+	}
+
+	mcspi = spi_master_get_devdata(spi->master);
+
+	spin_lock_irqsave(&mcspi->lock, flags);
+	list_add_tail(&m->queue, &mcspi->msg_queue);
+	queue_work(omap2_mcspi_wq, &mcspi->work);
+	spin_unlock_irqrestore(&mcspi->lock, flags);
+
+	return 0;
+}
+
+static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
+{
+	struct spi_master	*master = mcspi->master;
+	u32			tmp;
+
+	clk_enable(mcspi->ick);
+	clk_enable(mcspi->fck);
+
+	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
+			OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
+	do {
+		tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
+	} while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
+
+	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
+			/* (3 << 8) | (2 << 3) | */
+			OMAP2_MCSPI_SYSCONFIG_AUTOIDLE);
+
+	omap2_mcspi_set_master_mode(master);
+
+	clk_disable(mcspi->fck);
+	clk_disable(mcspi->ick);
+	return 0;
+}
+
+static u8 __initdata spi1_rxdma_id [] = {
+	OMAP24XX_DMA_SPI1_RX0,
+	OMAP24XX_DMA_SPI1_RX1,
+	OMAP24XX_DMA_SPI1_RX2,
+	OMAP24XX_DMA_SPI1_RX3,
+};
+
+static u8 __initdata spi1_txdma_id [] = {
+	OMAP24XX_DMA_SPI1_TX0,
+	OMAP24XX_DMA_SPI1_TX1,
+	OMAP24XX_DMA_SPI1_TX2,
+	OMAP24XX_DMA_SPI1_TX3,
+};
+
+static u8 __initdata spi2_rxdma_id[] = {
+	OMAP24XX_DMA_SPI2_RX0,
+	OMAP24XX_DMA_SPI2_RX1,
+};
+
+static u8 __initdata spi2_txdma_id[] = {
+	OMAP24XX_DMA_SPI2_TX0,
+	OMAP24XX_DMA_SPI2_TX1,
+};
+
+static int __init omap2_mcspi_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct omap2_mcspi	*mcspi;
+	struct resource		*r;
+	int			status = 0, i;
+	const u8		*rxdma_id, *txdma_id;
+	unsigned		num_chipselect;
+
+	switch (pdev->id) {
+	case 1:
+		rxdma_id = spi1_rxdma_id;
+		txdma_id = spi1_txdma_id;
+		num_chipselect = 4;
+		break;
+	case 2:
+		rxdma_id = spi2_rxdma_id;
+		txdma_id = spi2_txdma_id;
+		num_chipselect = 2;
+		break;
+	/* REVISIT omap2430 has a third McSPI ... */
+	default:
+		return -EINVAL;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
+	if (master == NULL) {
+		dev_dbg(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	if (pdev->id != -1)
+		master->bus_num = pdev->id;
+
+	master->setup = omap2_mcspi_setup;
+	master->transfer = omap2_mcspi_transfer;
+	master->cleanup = omap2_mcspi_cleanup;
+	master->num_chipselect = num_chipselect;
+
+	dev_set_drvdata(&pdev->dev, master);
+
+	mcspi = spi_master_get_devdata(master);
+	mcspi->master = master;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		status = -ENODEV;
+		goto err1;
+	}
+	if (!request_mem_region(r->start, (r->end - r->start) + 1,
+			pdev->dev.bus_id)) {
+		status = -EBUSY;
+		goto err1;
+	}
+
+	mcspi->base = (void __iomem *) io_p2v(r->start);
+
+	INIT_WORK(&mcspi->work, omap2_mcspi_work);
+
+	spin_lock_init(&mcspi->lock);
+	INIT_LIST_HEAD(&mcspi->msg_queue);
+
+	mcspi->ick = clk_get(&pdev->dev, "mcspi_ick");
+	if (IS_ERR(mcspi->ick)) {
+		dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
+		status = PTR_ERR(mcspi->ick);
+		goto err1a;
+	}
+	mcspi->fck = clk_get(&pdev->dev, "mcspi_fck");
+	if (IS_ERR(mcspi->fck)) {
+		dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
+		status = PTR_ERR(mcspi->fck);
+		goto err2;
+	}
+
+	mcspi->dma_channels = kcalloc(master->num_chipselect,
+			sizeof(struct omap2_mcspi_dma),
+			GFP_KERNEL);
+
+	if (mcspi->dma_channels == NULL)
+		goto err3;
+
+	for (i = 0; i < num_chipselect; i++) {
+		mcspi->dma_channels[i].dma_rx_channel = -1;
+		mcspi->dma_channels[i].dma_rx_sync_dev = rxdma_id[i];
+		mcspi->dma_channels[i].dma_tx_channel = -1;
+		mcspi->dma_channels[i].dma_tx_sync_dev = txdma_id[i];
+	}
+
+	if (omap2_mcspi_reset(mcspi) < 0)
+		goto err4;
+
+	status = spi_register_master(master);
+	if (status < 0)
+		goto err4;
+
+	return status;
+
+err4:
+	kfree(mcspi->dma_channels);
+err3:
+	clk_put(mcspi->fck);
+err2:
+	clk_put(mcspi->ick);
+err1a:
+	release_mem_region(r->start, (r->end - r->start) + 1);
+err1:
+	spi_master_put(master);
+	return status;
+}
+
+static int __exit omap2_mcspi_remove(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*dma_channels;
+	struct resource		*r;
+
+	master = dev_get_drvdata(&pdev->dev);
+	mcspi = spi_master_get_devdata(master);
+	dma_channels = mcspi->dma_channels;
+
+	clk_put(mcspi->fck);
+	clk_put(mcspi->ick);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, (r->end - r->start) + 1);
+
+	spi_unregister_master(master);
+	kfree(dma_channels);
+
+	return 0;
+}
+
+static struct platform_driver omap2_mcspi_driver = {
+	.driver = {
+		.name =		"omap2_mcspi",
+		.owner =	THIS_MODULE,
+	},
+	.remove =	__exit_p(omap2_mcspi_remove),
+};
+
+
+static int __init omap2_mcspi_init(void)
+{
+	omap2_mcspi_wq = create_singlethread_workqueue(
+				omap2_mcspi_driver.driver.name);
+	if (omap2_mcspi_wq == NULL)
+		return -1;
+	return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);
+}
+subsys_initcall(omap2_mcspi_init);
+
+static void __exit omap2_mcspi_exit(void)
+{
+	platform_driver_unregister(&omap2_mcspi_driver);
+
+	destroy_workqueue(omap2_mcspi_wq);
+}
+module_exit(omap2_mcspi_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index 95183e1..d275c61 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -445,10 +445,19 @@
 	return status;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 static int uwire_setup(struct spi_device *spi)
 {
 	struct uwire_state *ust = spi->controller_state;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (ust == NULL) {
 		ust = kzalloc(sizeof(*ust), GFP_KERNEL);
 		if (ust == NULL)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 9f2c887..e51311b 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1067,6 +1067,9 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
 static int setup(struct spi_device *spi)
 {
 	struct pxa2xx_spi_chip *chip_info = NULL;
@@ -1093,6 +1096,12 @@
 		return -EINVAL;
 	}
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	/* Only alloc on first setup */
 	chip = spi_get_ctldata(spi);
 	if (!chip) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 4831edb..018884d 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -23,6 +23,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/cache.h>
+#include <linux/mutex.h>
 #include <linux/spi/spi.h>
 
 
@@ -185,7 +186,7 @@
 };
 
 static LIST_HEAD(board_list);
-static DECLARE_MUTEX(board_lock);
+static DEFINE_MUTEX(board_lock);
 
 
 /**
@@ -292,9 +293,9 @@
 	bi->n_board_info = n;
 	memcpy(bi->board_info, info, n * sizeof *info);
 
-	down(&board_lock);
+	mutex_lock(&board_lock);
 	list_add_tail(&bi->list, &board_list);
-	up(&board_lock);
+	mutex_unlock(&board_lock);
 	return 0;
 }
 
@@ -308,7 +309,7 @@
 	struct boardinfo	*bi;
 	struct device		*dev = master->cdev.dev;
 
-	down(&board_lock);
+	mutex_lock(&board_lock);
 	list_for_each_entry(bi, &board_list, list) {
 		struct spi_board_info	*chip = bi->board_info;
 		unsigned		n;
@@ -330,7 +331,7 @@
 			(void) spi_new_device(master, chip);
 		}
 	}
-	up(&board_lock);
+	mutex_unlock(&board_lock);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 88425e1..0c85c98 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -187,12 +187,10 @@
 
 	bitbang = spi_master_get_devdata(spi->master);
 
-	/* REVISIT: some systems will want to support devices using lsb-first
-	 * bit encodings on the wire.  In pure software that would be trivial,
-	 * just bitbang_txrx_le_cphaX() routines shifting the other way, and
-	 * some hardware controllers also have this support.
+	/* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on;
+	 * add those to master->flags, and provide the other support.
 	 */
-	if ((spi->mode & SPI_LSB_FIRST) != 0)
+	if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0)
 		return -EINVAL;
 
 	if (!cs) {
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 656be4a..aee9ad6 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -1163,6 +1163,9 @@
 	return -EINVAL;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 /* On first setup bad values must free chip_data memory since will cause
    spi_new_device to fail. Bad value setup from protocol driver are simply not
    applied and notified to the calling driver. */
@@ -1174,6 +1177,12 @@
 	u32 tmp;
 	int status = 0;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	/* Get controller data */
 	chip_info = spi->controller_data;
 
@@ -1245,21 +1254,6 @@
 
 	/* SPI mode */
 	tmp = spi->mode;
-	if (tmp & SPI_LSB_FIRST) {
-		status = -EINVAL;
-		if (first_setup) {
-			dev_err(&spi->dev,
-				"setup - "
-				"HW doesn't support LSB first transfer\n");
-			goto err_first_setup;
-		} else {
-			dev_err(&spi->dev,
-				"setup - "
-				"HW doesn't support LSB first transfer, "
-				"default to MSB first\n");
-			spi->mode &= ~SPI_LSB_FIRST;
-		}
-	}
 	if (tmp & SPI_CS_HIGH) {
 		u32_EDIT(chip->control,
 				SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH);
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c
new file mode 100644
index 0000000..4ea68ac
--- /dev/null
+++ b/drivers/spi/spi_lm70llp.c
@@ -0,0 +1,361 @@
+/*
+ * spi_lm70llp.c - driver for lm70llp eval board for the LM70 sensor
+ *
+ * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/parport.h>
+#include <linux/sysfs.h>
+#include <linux/workqueue.h>
+
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+
+/*
+ * The LM70 communicates with a host processor using a 3-wire variant of
+ * the SPI/Microwire bus interface. This driver specifically supports an
+ * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel
+ * port to bitbang an SPI-parport bridge.  Accordingly, this is an SPI
+ * master controller driver.  The hwmon/lm70 driver is a "SPI protocol
+ * driver", layered on top of this one and usable without the lm70llp.
+ *
+ * The LM70 is a temperature sensor chip from National Semiconductor; its
+ * datasheet is available at http://www.national.com/pf/LM/LM70.html
+ *
+ * Also see Documentation/spi/spi-lm70llp.  The SPI<->parport code here is
+ * (heavily) based on spi-butterfly by David Brownell.
+ *
+ * The LM70 LLP connects to the PC parallel port in the following manner:
+ *
+ *   Parallel                 LM70 LLP
+ *     Port      Direction   JP2 Header
+ *  -----------  ---------  ------------
+ *      D0    2      -         -
+ *      D1    3     -->      V+   5
+ *      D2    4     -->      V+   5
+ *      D3    5     -->      V+   5
+ *      D4    6     -->      V+   5
+ *      D5    7     -->      nCS  8
+ *      D6    8     -->      SCLK 3
+ *      D7    9     -->      SI/O 5
+ *     GND   25      -       GND  7
+ *    Select 13     <--      SI/O 1
+ *
+ * Note that parport pin 13 actually gets inverted by the transistor
+ * arrangement which lets either the parport or the LM70 drive the
+ * SI/SO signal.
+ */
+
+#define DRVNAME		"spi-lm70llp"
+
+#define lm70_INIT	0xBE
+#define SIO		0x10
+#define nCS		0x20
+#define SCLK		0x40
+
+/*-------------------------------------------------------------------------*/
+
+struct spi_lm70llp {
+	struct spi_bitbang	bitbang;
+	struct parport		*port;
+	struct pardevice	*pd;
+	struct spi_device	*spidev_lm70;
+	struct spi_board_info	info;
+	struct class_device	*cdev;
+};
+
+/* REVISIT : ugly global ; provides "exclusive open" facility */
+static struct spi_lm70llp *lm70llp;
+
+
+/*-------------------------------------------------------------------*/
+
+static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
+{
+	return spi->controller_data;
+}
+
+/*---------------------- LM70 LLP eval board-specific inlines follow */
+
+/* NOTE:  we don't actually need to reread the output values, since they'll
+ * still be what we wrote before.  Plus, going through parport builds in
+ * a ~1ms/operation delay; these SPI transfers could easily be faster.
+ */
+
+static inline void deassertCS(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data | nCS);
+}
+
+static inline void assertCS(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data & ~nCS);
+}
+
+static inline void clkHigh(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data | SCLK);
+}
+
+static inline void clkLow(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data & ~SCLK);
+}
+
+/*------------------------- SPI-LM70-specific inlines ----------------------*/
+
+static inline void spidelay(unsigned d)
+{
+	udelay(d);
+}
+
+static inline void setsck(struct spi_device *s, int is_on)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(s);
+
+	if (is_on)
+		clkHigh(pp);
+	else
+		clkLow(pp);
+}
+
+static inline void setmosi(struct spi_device *s, int is_on)
+{
+	/* FIXME update D7 ... this way we can put the chip
+	 * into shutdown mode and read the manufacturer ID,
+	 * but we can't put it back into operational mode.
+	 */
+}
+
+/*
+ * getmiso:
+ * Why do we return 0 when the SIO line is high and vice-versa?
+ * The fact is, the lm70 eval board from NS (which this driver drives),
+ * is wired in just such a way : when the lm70's SIO goes high, a transistor
+ * switches it to low reflecting this on the parport (pin 13), and vice-versa.
+ */
+static inline int getmiso(struct spi_device *s)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(s);
+	return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1 );
+}
+/*--------------------------------------------------------------------*/
+
+#define EXPAND_BITBANG_TXRX 1
+#include <linux/spi/spi_bitbang.h>
+
+static void lm70_chipselect(struct spi_device *spi, int value)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(spi);
+
+	if (value)
+		assertCS(pp);
+	else
+		deassertCS(pp);
+}
+
+/*
+ * Our actual bitbanger routine.
+ */
+static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
+{
+	static u32 sio=0;
+	static int first_time=1;
+
+	/* First time: perform SPI bitbang and return the LSB of
+	 * the result of the SPI call.
+	 */
+	if (first_time) {
+		sio = bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+		first_time=0;
+		return (sio & 0x00ff);
+	}
+	/* Return the MSB of the result of the SPI call */
+	else {
+		first_time=1;
+		return (sio >> 8);
+	}
+}
+
+static void spi_lm70llp_attach(struct parport *p)
+{
+	struct pardevice	*pd;
+	struct spi_lm70llp	*pp;
+	struct spi_master	*master;
+	int			status;
+
+	if (lm70llp) {
+		printk(KERN_WARNING
+			"%s: spi_lm70llp instance already loaded. Aborting.\n",
+			DRVNAME);
+		return;
+	}
+
+	/* TODO:  this just _assumes_ a lm70 is there ... no probe;
+	 * the lm70 driver could verify it, reading the manf ID.
+	 */
+
+	master = spi_alloc_master(p->physport->dev, sizeof *pp);
+	if (!master) {
+		status = -ENOMEM;
+		goto out_fail;
+	}
+	pp = spi_master_get_devdata(master);
+
+	master->bus_num = -1;	/* dynamic alloc of a bus number */
+	master->num_chipselect = 1;
+
+	/*
+	 * SPI and bitbang hookup.
+	 */
+	pp->bitbang.master = spi_master_get(master);
+	pp->bitbang.chipselect = lm70_chipselect;
+	pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
+	pp->bitbang.flags = SPI_3WIRE;
+
+	/*
+	 * Parport hookup
+	 */
+	pp->port = p;
+	pd = parport_register_device(p, DRVNAME,
+			NULL, NULL, NULL,
+			PARPORT_FLAG_EXCL, pp);
+	if (!pd) {
+		status = -ENOMEM;
+		goto out_free_master;
+	}
+	pp->pd = pd;
+
+	status = parport_claim(pd);
+	if (status < 0)
+		goto out_parport_unreg;
+
+	/*
+	 * Start SPI ...
+	 */
+	status = spi_bitbang_start(&pp->bitbang);
+	if (status < 0) {
+		printk(KERN_WARNING
+			"%s: spi_bitbang_start failed with status %d\n",
+			DRVNAME, status);
+		goto out_off_and_release;
+	}
+
+	/*
+	 * The modalias name MUST match the device_driver name
+	 * for the bus glue code to match and subsequently bind them.
+	 * We are binding to the generic drivers/hwmon/lm70.c device
+	 * driver.
+	 */
+	strcpy(pp->info.modalias, "lm70");
+	pp->info.max_speed_hz = 6 * 1000 * 1000;
+	pp->info.chip_select = 0;
+	pp->info.mode = SPI_3WIRE | SPI_MODE_0;
+
+	/* power up the chip, and let the LM70 control SI/SO */
+	parport_write_data(pp->port, lm70_INIT);
+
+	/* Enable access to our primary data structure via
+	 * the board info's (void *)controller_data.
+	 */
+	pp->info.controller_data = pp;
+	pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
+	if (pp->spidev_lm70)
+		dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
+				pp->spidev_lm70->dev.bus_id);
+	else {
+		printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME);
+		status = -ENODEV;
+		goto out_bitbang_stop;
+	}
+	pp->spidev_lm70->bits_per_word = 16;
+
+	lm70llp = pp;
+
+	return;
+
+out_bitbang_stop:
+	spi_bitbang_stop(&pp->bitbang);
+out_off_and_release:
+	/* power down */
+	parport_write_data(pp->port, 0);
+	mdelay(10);
+	parport_release(pp->pd);
+out_parport_unreg:
+	parport_unregister_device(pd);
+out_free_master:
+	(void) spi_master_put(master);
+out_fail:
+	pr_info("%s: spi_lm70llp probe fail, status %d\n", DRVNAME, status);
+}
+
+static void spi_lm70llp_detach(struct parport *p)
+{
+	struct spi_lm70llp		*pp;
+
+	if (!lm70llp || lm70llp->port != p)
+		return;
+
+	pp = lm70llp;
+	spi_bitbang_stop(&pp->bitbang);
+
+	/* power down */
+	parport_write_data(pp->port, 0);
+	msleep(10);
+
+	parport_release(pp->pd);
+	parport_unregister_device(pp->pd);
+
+	(void) spi_master_put(pp->bitbang.master);
+
+	lm70llp = NULL;
+}
+
+
+static struct parport_driver spi_lm70llp_drv = {
+	.name =		DRVNAME,
+	.attach =	spi_lm70llp_attach,
+	.detach =	spi_lm70llp_detach,
+};
+
+static int __init init_spi_lm70llp(void)
+{
+	return parport_register_driver(&spi_lm70llp_drv);
+}
+module_init(init_spi_lm70llp);
+
+static void __exit cleanup_spi_lm70llp(void)
+{
+	parport_unregister_driver(&spi_lm70llp_drv);
+}
+module_exit(cleanup_spi_lm70llp);
+
+MODULE_AUTHOR("Kaiwan N Billimoria <kaiwan@designergraphix.com>");
+MODULE_DESCRIPTION(
+	"Parport adapter for the National Semiconductor LM70 LLP eval board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index e9798bf..3295cfcc 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -47,6 +47,7 @@
 #define	SPMODE_ENABLE		(1 << 24)
 #define	SPMODE_LEN(x)		((x) << 20)
 #define	SPMODE_PM(x)		((x) << 16)
+#define	SPMODE_OP		(1 << 14)
 
 /*
  * Default for SPI Mode:
@@ -85,6 +86,11 @@
 	unsigned nsecs;		/* (clock cycle time)/2 */
 
 	u32 sysclk;
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+
+	bool qe_mode;
+
 	void (*activate_cs) (u8 cs, u8 polarity);
 	void (*deactivate_cs) (u8 cs, u8 polarity);
 };
@@ -103,7 +109,7 @@
 void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \
 {									  \
 	type * rx = mpc83xx_spi->rx;					  \
-	*rx++ = (type)data;						  \
+	*rx++ = (type)(data >> mpc83xx_spi->rx_shift);			  \
 	mpc83xx_spi->rx = rx;						  \
 }
 
@@ -114,7 +120,7 @@
 	const type * tx = mpc83xx_spi->tx;			\
 	if (!tx)						\
 		return 0;					\
-	data = *tx++;						\
+	data = *tx++ << mpc83xx_spi->tx_shift;			\
 	mpc83xx_spi->tx = tx;					\
 	return data;						\
 }
@@ -158,6 +164,12 @@
 
 		if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) {
 			u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64);
+			if (pm > 0x0f) {
+				printk(KERN_WARNING "MPC83xx SPI: SPICLK can't be less then a SYSCLK/1024!\n"
+						"Requested SPICLK is %d Hz. Will use %d Hz instead.\n",
+						spi->max_speed_hz, mpc83xx_spi->sysclk / 1024);
+				pm = 0x0f;
+			}
 			regval |= SPMODE_PM(pm) | SPMODE_DIV16;
 		} else {
 			u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4);
@@ -197,12 +209,22 @@
 	    || ((bits_per_word > 16) && (bits_per_word != 32)))
 		return -EINVAL;
 
+	mpc83xx_spi->rx_shift = 0;
+	mpc83xx_spi->tx_shift = 0;
 	if (bits_per_word <= 8) {
 		mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
 		mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+		if (mpc83xx_spi->qe_mode) {
+			mpc83xx_spi->rx_shift = 16;
+			mpc83xx_spi->tx_shift = 24;
+		}
 	} else if (bits_per_word <= 16) {
 		mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16;
 		mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16;
+		if (mpc83xx_spi->qe_mode) {
+			mpc83xx_spi->rx_shift = 16;
+			mpc83xx_spi->tx_shift = 16;
+		}
 	} else if (bits_per_word <= 32) {
 		mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32;
 		mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32;
@@ -232,12 +254,21 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 static int mpc83xx_spi_setup(struct spi_device *spi)
 {
 	struct spi_bitbang *bitbang;
 	struct mpc83xx_spi *mpc83xx_spi;
 	int retval;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (!spi->max_speed_hz)
 		return -EINVAL;
 
@@ -371,7 +402,6 @@
 		ret = -ENODEV;
 		goto free_master;
 	}
-
 	mpc83xx_spi = spi_master_get_devdata(master);
 	mpc83xx_spi->bitbang.master = spi_master_get(master);
 	mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect;
@@ -380,9 +410,17 @@
 	mpc83xx_spi->sysclk = pdata->sysclk;
 	mpc83xx_spi->activate_cs = pdata->activate_cs;
 	mpc83xx_spi->deactivate_cs = pdata->deactivate_cs;
+	mpc83xx_spi->qe_mode = pdata->qe_mode;
 	mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
 	mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
 
+	mpc83xx_spi->rx_shift = 0;
+	mpc83xx_spi->tx_shift = 0;
+	if (mpc83xx_spi->qe_mode) {
+		mpc83xx_spi->rx_shift = 16;
+		mpc83xx_spi->tx_shift = 24;
+	}
+
 	mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup;
 	init_completion(&mpc83xx_spi->done);
 
@@ -417,6 +455,9 @@
 
 	/* Enable SPI interface */
 	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+	if (pdata->qe_mode)
+		regval |= SPMODE_OP;
+
 	mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
 
 	ret = spi_bitbang_start(&mpc83xx_spi->bitbang);
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index d5a710f..7071ff8 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -146,6 +146,9 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 static int s3c24xx_spi_setup(struct spi_device *spi)
 {
 	int ret;
@@ -153,8 +156,11 @@
 	if (!spi->bits_per_word)
 		spi->bits_per_word = 8;
 
-	if ((spi->mode & SPI_LSB_FIRST) != 0)
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
 		return -EINVAL;
+	}
 
 	ret = s3c24xx_spi_setupxfer(spi, NULL);
 	if (ret < 0) {
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
new file mode 100644
index 0000000..08e981c
--- /dev/null
+++ b/drivers/spi/spi_txx9.c
@@ -0,0 +1,474 @@
+/*
+ * spi_txx9.c - TXx9 SPI controller driver.
+ *
+ * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ *
+ * Convert to generic SPI framework - Atsushi Nemoto (anemo@mba.ocn.ne.jp)
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <asm/gpio.h>
+
+
+#define SPI_FIFO_SIZE 4
+
+#define TXx9_SPMCR		0x00
+#define TXx9_SPCR0		0x04
+#define TXx9_SPCR1		0x08
+#define TXx9_SPFS		0x0c
+#define TXx9_SPSR		0x14
+#define TXx9_SPDR		0x18
+
+/* 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 Control 0 */
+#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
+
+
+struct txx9spi {
+	struct workqueue_struct	*workqueue;
+	struct work_struct work;
+	spinlock_t lock;	/* protect 'queue' */
+	struct list_head queue;
+	wait_queue_head_t waitq;
+	void __iomem *membase;
+	int irq;
+	int baseclk;
+	struct clk *clk;
+	u32 max_speed_hz, min_speed_hz;
+	int last_chipselect;
+	int last_chipselect_val;
+};
+
+static u32 txx9spi_rd(struct txx9spi *c, int reg)
+{
+	return __raw_readl(c->membase + reg);
+}
+static void txx9spi_wr(struct txx9spi *c, u32 val, int reg)
+{
+	__raw_writel(val, c->membase + reg);
+}
+
+static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c,
+		int on, unsigned int cs_delay)
+{
+	int val = (spi->mode & SPI_CS_HIGH) ? on : !on;
+	if (on) {
+		/* deselect the chip with cs_change hint in last transfer */
+		if (c->last_chipselect >= 0)
+			gpio_set_value(c->last_chipselect,
+					!c->last_chipselect_val);
+		c->last_chipselect = spi->chip_select;
+		c->last_chipselect_val = val;
+	} else {
+		c->last_chipselect = -1;
+		ndelay(cs_delay);	/* CS Hold Time */
+	}
+	gpio_set_value(spi->chip_select, val);
+	ndelay(cs_delay);	/* CS Setup Time / CS Recovery Time */
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS	(SPI_CS_HIGH|SPI_CPOL|SPI_CPHA)
+
+static int txx9spi_setup(struct spi_device *spi)
+{
+	struct txx9spi *c = spi_master_get_devdata(spi->master);
+	u8 bits_per_word;
+
+	if (spi->mode & ~MODEBITS)
+		return -EINVAL;
+
+	if (!spi->max_speed_hz
+			|| spi->max_speed_hz > c->max_speed_hz
+			|| spi->max_speed_hz < c->min_speed_hz)
+		return -EINVAL;
+
+	bits_per_word = spi->bits_per_word ? : 8;
+	if (bits_per_word != 8 && bits_per_word != 16)
+		return -EINVAL;
+
+	if (gpio_direction_output(spi->chip_select,
+			!(spi->mode & SPI_CS_HIGH))) {
+		dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n");
+		return -EINVAL;
+	}
+
+	/* deselect chip */
+	spin_lock(&c->lock);
+	txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz);
+	spin_unlock(&c->lock);
+
+	return 0;
+}
+
+static irqreturn_t txx9spi_interrupt(int irq, void *dev_id)
+{
+	struct txx9spi *c = dev_id;
+
+	/* disable rx intr */
+	txx9spi_wr(c, txx9spi_rd(c, TXx9_SPCR0) & ~TXx9_SPCR0_RBSIE,
+			TXx9_SPCR0);
+	wake_up(&c->waitq);
+	return IRQ_HANDLED;
+}
+
+static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
+{
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t;
+	unsigned int cs_delay;
+	unsigned int cs_change = 1;
+	int status = 0;
+	u32 mcr;
+	u32 prev_speed_hz = 0;
+	u8 prev_bits_per_word = 0;
+
+	/* CS setup/hold/recovery time in nsec */
+	cs_delay = 100 + (NSEC_PER_SEC / 2) / spi->max_speed_hz;
+
+	mcr = txx9spi_rd(c, TXx9_SPMCR);
+	if (unlikely((mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE)) {
+		dev_err(&spi->dev, "Bad mode.\n");
+		status = -EIO;
+		goto exit;
+	}
+	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+
+	/* enter config mode */
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+	txx9spi_wr(c, TXx9_SPCR0_SBOS
+			| ((spi->mode & SPI_CPOL) ? TXx9_SPCR0_SPOL : 0)
+			| ((spi->mode & SPI_CPHA) ? TXx9_SPCR0_SPHA : 0)
+			| 0x08,
+			TXx9_SPCR0);
+
+	list_for_each_entry (t, &m->transfers, transfer_list) {
+		const void *txbuf = t->tx_buf;
+		void *rxbuf = t->rx_buf;
+		u32 data;
+		unsigned int len = t->len;
+		unsigned int wsize;
+		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+		bits_per_word = bits_per_word ? : 8;
+		wsize = bits_per_word >> 3; /* in bytes */
+
+		if (prev_speed_hz != speed_hz
+				|| prev_bits_per_word != bits_per_word) {
+			u32 n = (c->baseclk + speed_hz - 1) / speed_hz;
+			if (n < 1)
+				n = 1;
+			else if (n > 0xff)
+				n = 0xff;
+			/* enter config mode */
+			txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,
+					TXx9_SPMCR);
+			txx9spi_wr(c, (n << 8) | bits_per_word, TXx9_SPCR1);
+			/* enter active mode */
+			txx9spi_wr(c, mcr | TXx9_SPMCR_ACTIVE, TXx9_SPMCR);
+
+			prev_speed_hz = speed_hz;
+			prev_bits_per_word = bits_per_word;
+		}
+
+		if (cs_change)
+			txx9spi_cs_func(spi, c, 1, cs_delay);
+		cs_change = t->cs_change;
+		while (len) {
+			unsigned int count = SPI_FIFO_SIZE;
+			int i;
+			u32 cr0;
+
+			if (len < count * wsize)
+				count = len / wsize;
+			/* now tx must be idle... */
+			while (!(txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_SIDLE))
+				cpu_relax();
+			cr0 = txx9spi_rd(c, TXx9_SPCR0);
+			cr0 &= ~TXx9_SPCR0_RXIFL_MASK;
+			cr0 |= (count - 1) << 12;
+			/* enable rx intr */
+			cr0 |= TXx9_SPCR0_RBSIE;
+			txx9spi_wr(c, cr0, TXx9_SPCR0);
+			/* send */
+			for (i = 0; i < count; i++) {
+				if (txbuf) {
+					data = (wsize == 1)
+						? *(const u8 *)txbuf
+						: *(const u16 *)txbuf;
+					txx9spi_wr(c, data, TXx9_SPDR);
+					txbuf += wsize;
+				} else
+					txx9spi_wr(c, 0, TXx9_SPDR);
+			}
+			/* wait all rx data */
+			wait_event(c->waitq,
+				txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_RBSI);
+			/* receive */
+			for (i = 0; i < count; i++) {
+				data = txx9spi_rd(c, TXx9_SPDR);
+				if (rxbuf) {
+					if (wsize == 1)
+						*(u8 *)rxbuf = data;
+					else
+						*(u16 *)rxbuf = data;
+					rxbuf += wsize;
+				}
+			}
+			len -= count * wsize;
+		}
+		m->actual_length += t->len;
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (!cs_change)
+			continue;
+		if (t->transfer_list.next == &m->transfers)
+			break;
+		/* sometimes a short mid-message deselect of the chip
+		 * may be needed to terminate a mode or command
+		 */
+		txx9spi_cs_func(spi, c, 0, cs_delay);
+	}
+
+exit:
+	m->status = status;
+	m->complete(m->context);
+
+	/* normally deactivate chipselect ... unless no error and
+	 * cs_change has hinted that the next message will probably
+	 * be for this chip too.
+	 */
+	if (!(status == 0 && cs_change))
+		txx9spi_cs_func(spi, c, 0, cs_delay);
+
+	/* enter config mode */
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+}
+
+static void txx9spi_work(struct work_struct *work)
+{
+	struct txx9spi *c = container_of(work, struct txx9spi, work);
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->lock, flags);
+	while (!list_empty(&c->queue)) {
+		struct spi_message *m;
+
+		m = container_of(c->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irqrestore(&c->lock, flags);
+
+		txx9spi_work_one(c, m);
+
+		spin_lock_irqsave(&c->lock, flags);
+	}
+	spin_unlock_irqrestore(&c->lock, flags);
+}
+
+static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct spi_master *master = spi->master;
+	struct txx9spi *c = spi_master_get_devdata(master);
+	struct spi_transfer *t;
+	unsigned long flags;
+
+	m->actual_length = 0;
+
+	/* check each transfer's parameters */
+	list_for_each_entry (t, &m->transfers, transfer_list) {
+		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+		bits_per_word = bits_per_word ? : 8;
+		if (!t->tx_buf && !t->rx_buf && t->len)
+			return -EINVAL;
+		if (bits_per_word != 8 && bits_per_word != 16)
+			return -EINVAL;
+		if (t->len & ((bits_per_word >> 3) - 1))
+			return -EINVAL;
+		if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
+			return -EINVAL;
+	}
+
+	spin_lock_irqsave(&c->lock, flags);
+	list_add_tail(&m->queue, &c->queue);
+	queue_work(c->workqueue, &c->work);
+	spin_unlock_irqrestore(&c->lock, flags);
+
+	return 0;
+}
+
+static int __init txx9spi_probe(struct platform_device *dev)
+{
+	struct spi_master *master;
+	struct txx9spi *c;
+	struct resource *res;
+	int ret = -ENODEV;
+	u32 mcr;
+
+	master = spi_alloc_master(&dev->dev, sizeof(*c));
+	if (!master)
+		return ret;
+	c = spi_master_get_devdata(master);
+	c->irq = -1;
+	platform_set_drvdata(dev, master);
+
+	INIT_WORK(&c->work, txx9spi_work);
+	spin_lock_init(&c->lock);
+	INIT_LIST_HEAD(&c->queue);
+	init_waitqueue_head(&c->waitq);
+
+	c->clk = clk_get(&dev->dev, "spi-baseclk");
+	if (IS_ERR(c->clk)) {
+		ret = PTR_ERR(c->clk);
+		c->clk = NULL;
+		goto exit;
+	}
+	ret = clk_enable(c->clk);
+	if (ret) {
+		clk_put(c->clk);
+		c->clk = NULL;
+		goto exit;
+	}
+	c->baseclk = clk_get_rate(c->clk);
+	c->min_speed_hz = (c->baseclk + 0xff - 1) / 0xff;
+	c->max_speed_hz = c->baseclk;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit;
+	c->membase = ioremap(res->start, res->end - res->start + 1);
+	if (!c->membase)
+		goto exit;
+
+	/* enter config mode */
+	mcr = txx9spi_rd(c, TXx9_SPMCR);
+	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+
+	c->irq = platform_get_irq(dev, 0);
+	if (c->irq < 0)
+		goto exit;
+	ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c);
+	if (ret) {
+		c->irq = -1;
+		goto exit;
+	}
+
+	c->workqueue = create_singlethread_workqueue(master->cdev.dev->bus_id);
+	if (!c->workqueue)
+		goto exit;
+	c->last_chipselect = -1;
+
+	dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
+		 (unsigned long long)res->start, c->irq,
+		 (c->baseclk + 500000) / 1000000);
+
+	master->bus_num = dev->id;
+	master->setup = txx9spi_setup;
+	master->transfer = txx9spi_transfer;
+	master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
+
+	ret = spi_register_master(master);
+	if (ret)
+		goto exit;
+	return 0;
+exit:
+	if (c->workqueue)
+		destroy_workqueue(c->workqueue);
+	if (c->irq >= 0)
+		free_irq(c->irq, c);
+	if (c->membase)
+		iounmap(c->membase);
+	if (c->clk) {
+		clk_disable(c->clk);
+		clk_put(c->clk);
+	}
+	platform_set_drvdata(dev, NULL);
+	spi_master_put(master);
+	return ret;
+}
+
+static int __exit txx9spi_remove(struct platform_device *dev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
+	struct txx9spi *c = spi_master_get_devdata(master);
+
+	spi_unregister_master(master);
+	platform_set_drvdata(dev, NULL);
+	destroy_workqueue(c->workqueue);
+	free_irq(c->irq, c);
+	iounmap(c->membase);
+	clk_disable(c->clk);
+	clk_put(c->clk);
+	spi_master_put(master);
+	return 0;
+}
+
+static struct platform_driver txx9spi_driver = {
+	.remove = __exit_p(txx9spi_remove),
+	.driver = {
+		.name = "txx9spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init txx9spi_init(void)
+{
+	return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
+}
+subsys_initcall(txx9spi_init);
+
+static void __exit txx9spi_exit(void)
+{
+	platform_driver_unregister(&txx9spi_driver);
+}
+module_exit(txx9spi_exit);
+
+MODULE_DESCRIPTION("TXx9 SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d04242a..38b60ad 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -181,7 +181,8 @@
 		}
 		if (u_tmp->tx_buf) {
 			k_tmp->tx_buf = buf;
-			if (copy_from_user(buf, (const u8 __user *)u_tmp->tx_buf,
+			if (copy_from_user(buf, (const u8 __user *)
+						(ptrdiff_t) u_tmp->tx_buf,
 					u_tmp->len))
 				goto done;
 		}
@@ -213,7 +214,8 @@
 	buf = spidev->buffer;
 	for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
 		if (u_tmp->rx_buf) {
-			if (__copy_to_user((u8 __user *)u_tmp->rx_buf, buf,
+			if (__copy_to_user((u8 __user *)
+					(ptrdiff_t) u_tmp->rx_buf, buf,
 					u_tmp->len)) {
 				status = -EFAULT;
 				goto done;
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c
new file mode 100644
index 0000000..6da58ca
--- /dev/null
+++ b/drivers/spi/tle62x0.c
@@ -0,0 +1,328 @@
+/*
+ * tle62x0.c -- support Infineon TLE62x0 driver chips
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks, <ben@simtec.co.uk>
+ *
+ * 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/device.h>
+#include <linux/kernel.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/tle62x0.h>
+
+
+#define CMD_READ	0x00
+#define CMD_SET		0xff
+
+#define DIAG_NORMAL	0x03
+#define DIAG_OVERLOAD	0x02
+#define DIAG_OPEN	0x01
+#define DIAG_SHORTGND	0x00
+
+struct tle62x0_state {
+	struct spi_device	*us;
+	struct mutex		lock;
+	unsigned int		nr_gpio;
+	unsigned int		gpio_state;
+
+	unsigned char		tx_buff[4];
+	unsigned char		rx_buff[4];
+};
+
+static int to_gpio_num(struct device_attribute *attr);
+
+static inline int tle62x0_write(struct tle62x0_state *st)
+{
+	unsigned char *buff = st->tx_buff;
+	unsigned int gpio_state = st->gpio_state;
+
+	buff[0] = CMD_SET;
+
+	if (st->nr_gpio == 16) {
+		buff[1] = gpio_state >> 8;
+		buff[2] = gpio_state;
+	} else {
+		buff[1] = gpio_state;
+	}
+
+	dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
+		buff[0], buff[1], buff[2]);
+
+	return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
+}
+
+static inline int tle62x0_read(struct tle62x0_state *st)
+{
+	unsigned char *txbuff = st->tx_buff;
+	struct spi_transfer xfer = {
+		.tx_buf		= txbuff,
+		.rx_buf		= st->rx_buff,
+		.len		= (st->nr_gpio * 2) / 8,
+	};
+	struct spi_message msg;
+
+	txbuff[0] = CMD_READ;
+	txbuff[1] = 0x00;
+	txbuff[2] = 0x00;
+	txbuff[3] = 0x00;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	return spi_sync(st->us, &msg);
+}
+
+static unsigned char *decode_fault(unsigned int fault_code)
+{
+	fault_code &= 3;
+
+	switch (fault_code) {
+	case DIAG_NORMAL:
+		return "N";
+	case DIAG_OVERLOAD:
+		return "V";
+	case DIAG_OPEN:
+		return "O";
+	case DIAG_SHORTGND:
+		return "G";
+	}
+
+	return "?";
+}
+
+static ssize_t tle62x0_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	char *bp = buf;
+	unsigned char *buff = st->rx_buff;
+	unsigned long fault = 0;
+	int ptr;
+	int ret;
+
+	mutex_lock(&st->lock);
+	ret = tle62x0_read(st);
+
+	dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
+
+	for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
+		fault <<= 8;
+		fault  |= ((unsigned long)buff[ptr]);
+
+		dev_dbg(dev, "byte %d is %02x\n", ptr, buff[ptr]);
+	}
+
+	for (ptr = 0; ptr < st->nr_gpio; ptr++) {
+		bp += sprintf(bp, "%s ", decode_fault(fault >> (ptr * 2)));
+	}
+
+	*bp++ = '\n';
+
+	mutex_unlock(&st->lock);
+	return bp - buf;
+}
+
+static DEVICE_ATTR(status_show, S_IRUGO, tle62x0_status_show, NULL);
+
+static ssize_t tle62x0_gpio_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	int gpio_num = to_gpio_num(attr);
+	int value;
+
+	mutex_lock(&st->lock);
+	value = (st->gpio_state >> gpio_num) & 1;
+	mutex_unlock(&st->lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d", value);
+}
+
+static ssize_t tle62x0_gpio_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t len)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	int gpio_num = to_gpio_num(attr);
+	unsigned long val;
+	char *endp;
+
+	val = simple_strtoul(buf, &endp, 0);
+	if (buf == endp)
+		return -EINVAL;
+
+	dev_dbg(dev, "setting gpio %d to %ld\n", gpio_num, val);
+
+	mutex_lock(&st->lock);
+
+	if (val)
+		st->gpio_state |= 1 << gpio_num;
+	else
+		st->gpio_state &= ~(1 << gpio_num);
+
+	tle62x0_write(st);
+	mutex_unlock(&st->lock);
+
+	return len;
+}
+
+static DEVICE_ATTR(gpio1, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio2, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio3, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio4, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio5, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio6, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio7, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio8, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio9, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio10, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio11, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio12, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio13, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio14, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio15, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio16, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+
+static struct device_attribute *gpio_attrs[] = {
+	[0]		= &dev_attr_gpio1,
+	[1]		= &dev_attr_gpio2,
+	[2]		= &dev_attr_gpio3,
+	[3]		= &dev_attr_gpio4,
+	[4]		= &dev_attr_gpio5,
+	[5]		= &dev_attr_gpio6,
+	[6]		= &dev_attr_gpio7,
+	[7]		= &dev_attr_gpio8,
+	[8]		= &dev_attr_gpio9,
+	[9]		= &dev_attr_gpio10,
+	[10]		= &dev_attr_gpio11,
+	[11]		= &dev_attr_gpio12,
+	[12]		= &dev_attr_gpio13,
+	[13]		= &dev_attr_gpio14,
+	[14]		= &dev_attr_gpio15,
+	[15]		= &dev_attr_gpio16
+};
+
+static int to_gpio_num(struct device_attribute *attr)
+{
+	int ptr;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(gpio_attrs); ptr++) {
+		if (gpio_attrs[ptr] == attr)
+			return ptr;
+	}
+
+	return -1;
+}
+
+static int __devinit tle62x0_probe(struct spi_device *spi)
+{
+	struct tle62x0_state *st;
+	struct tle62x0_pdata *pdata;
+	int ptr;
+	int ret;
+
+	pdata = spi->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&spi->dev, "no device data specified\n");
+		return -EINVAL;
+	}
+
+	st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
+	if (st == NULL) {
+		dev_err(&spi->dev, "no memory for device state\n");
+		return -ENOMEM;
+	}
+
+	st->us = spi;
+	st->nr_gpio = pdata->gpio_count;
+	st->gpio_state = pdata->init_state;
+
+	mutex_init(&st->lock);
+
+	ret = device_create_file(&spi->dev, &dev_attr_status_show);
+	if (ret) {
+		dev_err(&spi->dev, "cannot create status attribute\n");
+		goto err_status;
+	}
+
+	for (ptr = 0; ptr < pdata->gpio_count; ptr++) {
+		ret = device_create_file(&spi->dev, gpio_attrs[ptr]);
+		if (ret) {
+			dev_err(&spi->dev, "cannot create gpio attribute\n");
+			goto err_gpios;
+		}
+	}
+
+	/* tle62x0_write(st); */
+	spi_set_drvdata(spi, st);
+	return 0;
+
+ err_gpios:
+	for (; ptr > 0; ptr--)
+		device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+	device_remove_file(&spi->dev, &dev_attr_status_show);
+
+ err_status:
+	kfree(st);
+	return ret;
+}
+
+static int __devexit tle62x0_remove(struct spi_device *spi)
+{
+	struct tle62x0_state *st = spi_get_drvdata(spi);
+	int ptr;
+
+	for (ptr = 0; ptr < st->nr_gpio; ptr++)
+		device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+	kfree(st);
+	return 0;
+}
+
+static struct spi_driver tle62x0_driver = {
+	.driver = {
+		.name	= "tle62x0",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tle62x0_probe,
+	.remove		= __devexit_p(tle62x0_remove),
+};
+
+static __init int tle62x0_init(void)
+{
+	return spi_register_driver(&tle62x0_driver);
+}
+
+static __exit void tle62x0_exit(void)
+{
+	spi_unregister_driver(&tle62x0_driver);
+}
+
+module_init(tle62x0_init);
+module_exit(tle62x0_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("TLE62x0 SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
new file mode 100644
index 0000000..f0bf9a6
--- /dev/null
+++ b/drivers/spi/xilinx_spi.c
@@ -0,0 +1,434 @@
+/*
+ * xilinx_spi.c
+ *
+ * Xilinx SPI controller driver (master mode only)
+ *
+ * Author: MontaVista Software, Inc.
+ *	source@mvista.com
+ *
+ * 2002-2007 (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/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/io.h>
+
+#include <syslib/virtex_devices.h>
+
+#define XILINX_SPI_NAME "xspi"
+
+/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
+ * Product Specification", DS464
+ */
+#define XSPI_CR_OFFSET		0x62	/* 16-bit Control Register */
+
+#define XSPI_CR_ENABLE		0x02
+#define XSPI_CR_MASTER_MODE	0x04
+#define XSPI_CR_CPOL		0x08
+#define XSPI_CR_CPHA		0x10
+#define XSPI_CR_MODE_MASK	(XSPI_CR_CPHA | XSPI_CR_CPOL)
+#define XSPI_CR_TXFIFO_RESET	0x20
+#define XSPI_CR_RXFIFO_RESET	0x40
+#define XSPI_CR_MANUAL_SSELECT	0x80
+#define XSPI_CR_TRANS_INHIBIT	0x100
+
+#define XSPI_SR_OFFSET		0x67	/* 8-bit Status Register */
+
+#define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
+#define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
+#define XSPI_SR_TX_EMPTY_MASK	0x04	/* Transmit FIFO is empty */
+#define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
+#define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
+
+#define XSPI_TXD_OFFSET		0x6b	/* 8-bit Data Transmit Register */
+#define XSPI_RXD_OFFSET		0x6f	/* 8-bit Data Receive Register */
+
+#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */
+
+/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
+ * IPIF registers are 32 bit
+ */
+#define XIPIF_V123B_DGIER_OFFSET	0x1c	/* IPIF global int enable reg */
+#define XIPIF_V123B_GINTR_ENABLE	0x80000000
+
+#define XIPIF_V123B_IISR_OFFSET		0x20	/* IPIF interrupt status reg */
+#define XIPIF_V123B_IIER_OFFSET		0x28	/* IPIF interrupt enable reg */
+
+#define XSPI_INTR_MODE_FAULT		0x01	/* Mode fault error */
+#define XSPI_INTR_SLAVE_MODE_FAULT	0x02	/* Selected as slave while
+						 * disabled */
+#define XSPI_INTR_TX_EMPTY		0x04	/* TxFIFO is empty */
+#define XSPI_INTR_TX_UNDERRUN		0x08	/* TxFIFO was underrun */
+#define XSPI_INTR_RX_FULL		0x10	/* RxFIFO is full */
+#define XSPI_INTR_RX_OVERRUN		0x20	/* RxFIFO was overrun */
+
+#define XIPIF_V123B_RESETR_OFFSET	0x40	/* IPIF reset register */
+#define XIPIF_V123B_RESET_MASK		0x0a	/* the value to write */
+
+struct xilinx_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem	*regs;	/* virt. address of the control registers */
+
+	u32		irq;
+
+	u32		speed_hz; /* SCK has a fixed frequency of speed_hz Hz */
+
+	u8 *rx_ptr;		/* pointer in the Tx buffer */
+	const u8 *tx_ptr;	/* pointer in the Rx buffer */
+	int remaining_bytes;	/* the number of bytes left to transfer */
+};
+
+static void xspi_init_hw(void __iomem *regs_base)
+{
+	/* Reset the SPI device */
+	out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET,
+		 XIPIF_V123B_RESET_MASK);
+	/* Disable all the interrupts just in case */
+	out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0);
+	/* Enable the global IPIF interrupt */
+	out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET,
+		 XIPIF_V123B_GINTR_ENABLE);
+	/* Deselect the slave on the SPI bus */
+	out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff);
+	/* Disable the transmitter, enable Manual Slave Select Assertion,
+	 * put SPI controller into master mode, and enable it */
+	out_be16(regs_base + XSPI_CR_OFFSET,
+		 XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT
+		 | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE);
+}
+
+static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
+{
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+	if (is_on == BITBANG_CS_INACTIVE) {
+		/* Deselect the slave on the SPI bus */
+		out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff);
+	} else if (is_on == BITBANG_CS_ACTIVE) {
+		/* Set the SPI clock phase and polarity */
+		u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET)
+			 & ~XSPI_CR_MODE_MASK;
+		if (spi->mode & SPI_CPHA)
+			cr |= XSPI_CR_CPHA;
+		if (spi->mode & SPI_CPOL)
+			cr |= XSPI_CR_CPOL;
+		out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+
+		/* We do not check spi->max_speed_hz here as the SPI clock
+		 * frequency is not software programmable (the IP block design
+		 * parameter)
+		 */
+
+		/* Activate the chip select */
+		out_be32(xspi->regs + XSPI_SSR_OFFSET,
+			 ~(0x0001 << spi->chip_select));
+	}
+}
+
+/* spi_bitbang requires custom setup_transfer() to be defined if there is a
+ * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
+ * supports just 8 bits per word, and SPI clock can't be changed in software.
+ * Check for 8 bits per word. Chip select delay calculations could be
+ * added here as soon as bitbang_work() can be made aware of the delay value.
+ */
+static int xilinx_spi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	u8 bits_per_word;
+	u32 hz;
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+	bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
+	hz = (t) ? t->speed_hz : spi->max_speed_hz;
+	if (bits_per_word != 8) {
+		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+			__FUNCTION__, bits_per_word);
+		return -EINVAL;
+	}
+
+	if (hz && xspi->speed_hz > hz) {
+		dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
+			__FUNCTION__, hz);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
+static int xilinx_spi_setup(struct spi_device *spi)
+{
+	struct spi_bitbang *bitbang;
+	struct xilinx_spi *xspi;
+	int retval;
+
+	xspi = spi_master_get_devdata(spi->master);
+	bitbang = &xspi->bitbang;
+
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	if (spi->mode & ~MODEBITS) {
+		dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
+			__FUNCTION__, spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
+	retval = xilinx_spi_setup_transfer(spi, NULL);
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
+		__FUNCTION__, spi->mode & MODEBITS, spi->bits_per_word, 0);
+
+	return 0;
+}
+
+static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
+{
+	u8 sr;
+
+	/* Fill the Tx FIFO with as many bytes as possible */
+	sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+	while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
+		if (xspi->tx_ptr) {
+			out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++);
+		} else {
+			out_8(xspi->regs + XSPI_TXD_OFFSET, 0);
+		}
+		xspi->remaining_bytes--;
+		sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+	}
+}
+
+static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+	u32 ipif_ier;
+	u16 cr;
+
+	/* We get here with transmitter inhibited */
+
+	xspi->tx_ptr = t->tx_buf;
+	xspi->rx_ptr = t->rx_buf;
+	xspi->remaining_bytes = t->len;
+	INIT_COMPLETION(xspi->done);
+
+	xilinx_spi_fill_tx_fifo(xspi);
+
+	/* Enable the transmit empty interrupt, which we use to determine
+	 * progress on the transmission.
+	 */
+	ipif_ier = in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET);
+	out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET,
+		 ipif_ier | XSPI_INTR_TX_EMPTY);
+
+	/* Start the transfer by not inhibiting the transmitter any longer */
+	cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT;
+	out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+
+	wait_for_completion(&xspi->done);
+
+	/* Disable the transmit empty interrupt */
+	out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier);
+
+	return t->len - xspi->remaining_bytes;
+}
+
+
+/* This driver supports single master mode only. Hence Tx FIFO Empty
+ * is the only interrupt we care about.
+ * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
+ * Fault are not to happen.
+ */
+static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+{
+	struct xilinx_spi *xspi = dev_id;
+	u32 ipif_isr;
+
+	/* Get the IPIF interrupts, and clear them immediately */
+	ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr);
+
+	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
+		u16 cr;
+		u8 sr;
+
+		/* A transmit has just completed. Process received data and
+		 * check for more data to transmit. Always inhibit the
+		 * transmitter while the Isr refills the transmit register/FIFO,
+		 * or make sure it is stopped if we're done.
+		 */
+		cr = in_be16(xspi->regs + XSPI_CR_OFFSET);
+		out_be16(xspi->regs + XSPI_CR_OFFSET,
+			 cr | XSPI_CR_TRANS_INHIBIT);
+
+		/* Read out all the data from the Rx FIFO */
+		sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+		while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
+			u8 data;
+
+			data = in_8(xspi->regs + XSPI_RXD_OFFSET);
+			if (xspi->rx_ptr) {
+				*xspi->rx_ptr++ = data;
+			}
+			sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+		}
+
+		/* See if there is more data to send */
+		if (xspi->remaining_bytes > 0) {
+			xilinx_spi_fill_tx_fifo(xspi);
+			/* Start the transfer by not inhibiting the
+			 * transmitter any longer
+			 */
+			out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+		} else {
+			/* No more data to send.
+			 * Indicate the transfer is completed.
+			 */
+			complete(&xspi->done);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __init xilinx_spi_probe(struct platform_device *dev)
+{
+	int ret = 0;
+	struct spi_master *master;
+	struct xilinx_spi *xspi;
+	struct xspi_platform_data *pdata;
+	struct resource *r;
+
+	/* Get resources(memory, IRQ) associated with the device */
+	master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi));
+
+	if (master == NULL) {
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(dev, master);
+	pdata = dev->dev.platform_data;
+
+	if (pdata == NULL) {
+		ret = -ENODEV;
+		goto put_master;
+	}
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENODEV;
+		goto put_master;
+	}
+
+	xspi = spi_master_get_devdata(master);
+	xspi->bitbang.master = spi_master_get(master);
+	xspi->bitbang.chipselect = xilinx_spi_chipselect;
+	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
+	xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
+	xspi->bitbang.master->setup = xilinx_spi_setup;
+	init_completion(&xspi->done);
+
+	if (!request_mem_region(r->start,
+			r->end - r->start + 1, XILINX_SPI_NAME)) {
+		ret = -ENXIO;
+		goto put_master;
+	}
+
+	xspi->regs = ioremap(r->start, r->end - r->start + 1);
+	if (xspi->regs == NULL) {
+		ret = -ENOMEM;
+		goto put_master;
+	}
+
+	xspi->irq = platform_get_irq(dev, 0);
+	if (xspi->irq < 0) {
+		ret = -ENXIO;
+		goto unmap_io;
+	}
+
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->num_chipselect;
+	xspi->speed_hz = pdata->speed_hz;
+
+	/* SPI controller initializations */
+	xspi_init_hw(xspi->regs);
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+	if (ret != 0)
+		goto unmap_io;
+
+	ret = spi_bitbang_start(&xspi->bitbang);
+	if (ret != 0) {
+		dev_err(&dev->dev, "spi_bitbang_start FAILED\n");
+		goto free_irq;
+	}
+
+	dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+			r->start, (u32)xspi->regs, xspi->irq);
+
+	return ret;
+
+free_irq:
+	free_irq(xspi->irq, xspi);
+unmap_io:
+	iounmap(xspi->regs);
+put_master:
+	spi_master_put(master);
+	return ret;
+}
+
+static int __devexit xilinx_spi_remove(struct platform_device *dev)
+{
+	struct xilinx_spi *xspi;
+	struct spi_master *master;
+
+	master = platform_get_drvdata(dev);
+	xspi = spi_master_get_devdata(master);
+
+	spi_bitbang_stop(&xspi->bitbang);
+	free_irq(xspi->irq, xspi);
+	iounmap(xspi->regs);
+	platform_set_drvdata(dev, 0);
+	spi_master_put(xspi->bitbang.master);
+
+	return 0;
+}
+
+static struct platform_driver xilinx_spi_driver = {
+	.probe	= xilinx_spi_probe,
+	.remove	= __devexit_p(xilinx_spi_remove),
+	.driver = {
+		.name = XILINX_SPI_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init xilinx_spi_init(void)
+{
+	return platform_driver_register(&xilinx_spi_driver);
+}
+module_init(xilinx_spi_init);
+
+static void __exit xilinx_spi_exit(void)
+{
+	platform_driver_unregister(&xilinx_spi_driver);
+}
+module_exit(xilinx_spi_exit);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION("Xilinx SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig
index dd1d6a5..5f98f67 100644
--- a/drivers/telephony/Kconfig
+++ b/drivers/telephony/Kconfig
@@ -2,11 +2,9 @@
 # Telephony device configuration
 #
 
-menu "Telephony Support"
+menuconfig PHONE
+	tristate "Telephony support"
 	depends on HAS_IOMEM
-
-config PHONE
-	tristate "Linux telephony support"
 	---help---
 	  Say Y here if you have a telephony card, which for example allows
 	  you to use a regular phone for voice-over-IP applications.
@@ -17,9 +15,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called phonedev.
 
+if PHONE
+
 config PHONE_IXJ
 	tristate "QuickNet Internet LineJack/PhoneJack support"
-	depends on PHONE
+	depends ISA || PCI
 	---help---
 	  Say M if you have a telephony card manufactured by Quicknet
 	  Technologies, Inc.  These include the Internet PhoneJACK and
@@ -44,5 +44,4 @@
 	  cards manufactured by Quicknet Technologies, Inc.  This changes the
 	  card initialization code to work with the card manager daemon.
 
-endmenu
-
+endif # PHONE
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 071b967..7dd7354 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -16,7 +16,7 @@
 	boolean
 	default y if USB_ARCH_HAS_OHCI
 	default y if USB_ARCH_HAS_EHCI
-	default y if PCMCIA				# sl811_cs
+	default y if PCMCIA && !M32R			# sl811_cs
 	default y if ARM				# SL-811
 	default PCI
 
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 4973e14..8f04665 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -1168,6 +1168,7 @@
 	struct uea_softc *sc = data;
 	int ret = -EAGAIN;
 
+	set_freezable();
 	uea_enters(INS_TO_USBDEV(sc));
 	while (!kthread_should_stop()) {
 		if (ret < 0 || sc->reset)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 50e7901..fd74c50 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2728,6 +2728,7 @@
 
 static int hub_thread(void *__unused)
 {
+	set_freezable();
 	do {
 		hub_events();
 		wait_event_interruptible(khubd_wait,
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 8712ef9..be7a1bd 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3434,6 +3434,9 @@
 	allow_signal(SIGKILL);
 	allow_signal(SIGUSR1);
 
+	/* Allow the thread to be frozen */
+	set_freezable();
+
 	/* Arrange for userspace references to be interpreted as kernel
 	 * pointers.  That way we can pass a kernel pointer to a routine
 	 * that expects a __user pointer and it will work okay. */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index bef8bcd..28842d2 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -311,8 +311,6 @@
 	struct Scsi_Host *host = us_to_host(us);
 	int autopm_rc;
 
-	current->flags |= PF_NOFREEZE;
-
 	for(;;) {
 		US_DEBUGP("*** thread sleeping.\n");
 		if(down_interruptible(&us->sema))
@@ -920,6 +918,7 @@
 	printk(KERN_DEBUG
 		"usb-storage: device found at %d\n", us->pusb_dev->devnum);
 
+	set_freezable();
 	/* Wait for the timeout to expire or for a disconnect */
 	if (delay_use > 0) {
 		printk(KERN_DEBUG "usb-storage: waiting for device "
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 0dda73d..7f907fb 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -60,7 +60,7 @@
 static u_long videomemorysize;
 
 static struct fb_info fb_info;
-static u32 mc68x328fb_pseudo_palette[17];
+static u32 mc68x328fb_pseudo_palette[16];
 
 static struct fb_var_screeninfo mc68x328fb_default __initdata = {
 	.red =		{ 0, 8, 0 },
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 403dac7..0c5644bb 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -812,7 +812,7 @@
 
 config FB_EPSON1355
 	bool "Epson 1355 framebuffer support"
-	depends on (FB = y) && (SUPERH || ARCH_CEIVA)
+	depends on (FB = y) && ARCH_CEIVA
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -1790,8 +1790,8 @@
 	  adaptor, found on some IBM System P (pSeries) machines.
 
 config FB_PS3
-	bool "PS3 GPU framebuffer driver"
-	depends on (FB = y) && PS3_PS3AV
+	tristate "PS3 GPU framebuffer driver"
+	depends on FB && PS3_PS3AV
 	select FB_SYS_FILLRECT
 	select FB_SYS_COPYAREA
 	select FB_SYS_IMAGEBLIT
@@ -1820,6 +1820,10 @@
 	  framebuffer. ML300 carries a 640*480 LCD display on the board,
 	  ML403 uses a standard DB15 VGA connector.
 
+if ARCH_OMAP
+	source "drivers/video/omap/Kconfig"
+endif
+
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bd8b052..a562f9d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -113,6 +113,7 @@
 obj-$(CONFIG_FB_PS3)		  += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
+obj-$(CONFIG_FB_OMAP)             += omap/
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h
index 90e7df2..685a754 100644
--- a/drivers/video/aty/ati_ids.h
+++ b/drivers/video/aty/ati_ids.h
@@ -204,6 +204,7 @@
 #define PCI_CHIP_RV280_5961		0x5961
 #define PCI_CHIP_RV280_5962		0x5962
 #define PCI_CHIP_RV280_5964		0x5964
+#define PCI_CHIP_RS485_5975		0x5975
 #define PCI_CHIP_RV280_5C61		0x5C61
 #define PCI_CHIP_RV280_5C63		0x5C63
 #define PCI_CHIP_R423_5D57              0x5D57
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 2fbff63..ef330e3 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -541,7 +541,7 @@
 #endif /* CONFIG_FB_ATY_CT */
 
 
-static u32 pseudo_palette[17];
+static u32 pseudo_palette[16];
 
 #ifdef CONFIG_FB_ATY_GX
 static char *aty_gx_ram[8] __devinitdata = {
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 2349e71..47ca62f 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -153,6 +153,8 @@
 	/* Mobility 9200 (M9+) */
 	CHIP_DEF(PCI_CHIP_RV280_5C61,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
 	CHIP_DEF(PCI_CHIP_RV280_5C63,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/*Mobility Xpress 200 */
+	CHIP_DEF(PCI_CHIP_RS485_5975,	R300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
 	/* 9200 */
 	CHIP_DEF(PCI_CHIP_RV280_5960,	RV280,	CHIP_HAS_CRTC2),
 	CHIP_DEF(PCI_CHIP_RV280_5961,	RV280,	CHIP_HAS_CRTC2),
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 7ebffcd..7c922c7 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -301,7 +301,7 @@
 	void __iomem		*bios_seg;
 	int			fp_bios_start;
 
-	u32			pseudo_palette[17];
+	u32			pseudo_palette[16];
 	struct { u8 red, green, blue, pad; }
 				palette[256];
 
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index d3b8a6b..4964396 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -118,6 +118,22 @@
 	help
 	  Low-level framebuffer-based console driver.
 
+config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
+       bool "Map the console to the primary display device"
+       depends on FRAMEBUFFER_CONSOLE
+       default n
+       ---help---
+         If this option is selected, the framebuffer console will
+         automatically select the primary display device (if the architecture
+	 supports this feature).  Otherwise, the framebuffer console will
+         always select the first framebuffer driver that is loaded. The latter
+         is the default behavior.
+
+	 You can always override the automatic selection of the primary device
+	 by using the fbcon=map: boot option.
+
+	 If unsure, select n.
+
 config FRAMEBUFFER_CONSOLE_ROTATION
        bool "Framebuffer Console Rotation"
        depends on FRAMEBUFFER_CONSOLE
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 73813c6..decfdc8 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -75,6 +75,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/crc32.h> /* For counting font checksums */
+#include <asm/fb.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -125,6 +126,8 @@
 static int last_fb_vc = MAX_NR_CONSOLES - 1;
 static int fbcon_is_default = 1; 
 static int fbcon_has_exited;
+static int primary_device = -1;
+static int map_override;
 
 /* font data */
 static char fontname[40];
@@ -152,6 +155,7 @@
 #define DEFAULT_CURSOR_BLINK_RATE	(20)
 
 static int vbl_cursor_cnt;
+static int fbcon_cursor_noblink;
 
 #define divides(a, b)	((!(a) || (b)%(a)) ? 0 : 1)
 
@@ -188,16 +192,14 @@
 static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx,
 			    int dy, int dx, int height, int width, u_int y_break);
 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			   struct vc_data *vc);
-static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			      int unit);
+			   int unit);
 static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
 			      int line, int count, int dy);
 static void fbcon_modechanged(struct fb_info *info);
 static void fbcon_set_all_vcs(struct fb_info *info);
 static void fbcon_start(void);
 static void fbcon_exit(void);
-static struct class_device *fbcon_class_device;
+static struct device *fbcon_device;
 
 #ifdef CONFIG_MAC
 /*
@@ -441,7 +443,8 @@
 	struct fbcon_ops *ops = info->fbcon_par;
 
 	if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
-	    !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
+	    !(ops->flags & FBCON_FLAGS_CURSOR_TIMER) &&
+	    !fbcon_cursor_noblink) {
 		if (!info->queue.func)
 			INIT_WORK(&info->queue, fb_flashcursor);
 
@@ -495,13 +498,17 @@
 		
 		if (!strncmp(options, "map:", 4)) {
 			options += 4;
-			if (*options)
+			if (*options) {
 				for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
 					if (!options[j])
 						j = 0;
 					con2fb_map_boot[i] =
 						(options[j++]-'0') % FB_MAX;
 				}
+
+				map_override = 1;
+			}
+
 			return 1;
 		}
 
@@ -736,7 +743,9 @@
 
 	if (!err) {
 		info->fbcon_par = ops;
-		set_blitting_type(vc, info);
+
+		if (vc)
+			set_blitting_type(vc, info);
 	}
 
 	if (err) {
@@ -798,11 +807,7 @@
 
 	ops->flags |= FBCON_FLAGS_INIT;
 	ops->graphics = 0;
-
-	if (vc)
-		fbcon_set_disp(info, &info->var, vc);
-	else
-		fbcon_preset_disp(info, &info->var, unit);
+	fbcon_set_disp(info, &info->var, unit);
 
 	if (show_logo) {
 		struct vc_data *fg_vc = vc_cons[fg_console].d;
@@ -1107,6 +1112,9 @@
 	if (var_to_display(p, &info->var, info))
 		return;
 
+	if (!info->fbcon_par)
+		con2fb_acquire_newinfo(vc, info, vc->vc_num, -1);
+
 	/* If we are not the first console on this
 	   fb, copy the font from that console */
 	t = &fb_display[fg_console];
@@ -1349,6 +1357,11 @@
 	if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
 		return;
 
+	if (vc->vc_cursor_type & 0x10)
+		fbcon_del_cursor_timer(info);
+	else
+		fbcon_add_cursor_timer(info);
+
 	ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
@@ -1368,36 +1381,29 @@
 static int scrollback_max = 0;
 static int scrollback_current = 0;
 
-/*
- * If no vc is existent yet, just set struct display
- */
-static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			      int unit)
-{
-	struct display *p = &fb_display[unit];
-	struct display *t = &fb_display[fg_console];
-
-	if (var_to_display(p, var, info))
-		return;
-
-	p->fontdata = t->fontdata;
-	p->userfont = t->userfont;
-	if (p->userfont)
-		REFCOUNT(p->fontdata)++;
-}
-
 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			   struct vc_data *vc)
+			   int unit)
 {
-	struct display *p = &fb_display[vc->vc_num], *t;
-	struct vc_data **default_mode = vc->vc_display_fg;
-	struct vc_data *svc = *default_mode;
+	struct display *p, *t;
+	struct vc_data **default_mode, *vc;
+	struct vc_data *svc;
 	struct fbcon_ops *ops = info->fbcon_par;
 	int rows, cols, charcnt = 256;
 
+	p = &fb_display[unit];
+
 	if (var_to_display(p, var, info))
 		return;
+
+	vc = vc_cons[unit].d;
+
+	if (!vc)
+		return;
+
+	default_mode = vc->vc_display_fg;
+	svc = *default_mode;
 	t = &fb_display[svc->vc_num];
+
 	if (!vc->vc_font.data) {
 		vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
 		vc->vc_font.width = (*default_mode)->vc_font.width;
@@ -1704,6 +1710,56 @@
 	}
 }
 
+static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
+			struct display *p, int line, int count, int ycount)
+{
+	int offset = ycount * vc->vc_cols;
+	unsigned short *d = (unsigned short *)
+	    (vc->vc_origin + vc->vc_size_row * line);
+	unsigned short *s = d + offset;
+	struct fbcon_ops *ops = info->fbcon_par;
+
+	while (count--) {
+		unsigned short *start = s;
+		unsigned short *le = advance_row(s, 1);
+		unsigned short c;
+		int x = 0;
+
+		do {
+			c = scr_readw(s);
+
+			if (c == scr_readw(d)) {
+				if (s > start) {
+					ops->bmove(vc, info, line + ycount, x,
+						   line, x, 1, s-start);
+					x += s - start + 1;
+					start = s + 1;
+				} else {
+					x++;
+					start++;
+				}
+			}
+
+			scr_writew(c, d);
+			console_conditional_schedule();
+			s++;
+			d++;
+		} while (s < le);
+		if (s > start)
+			ops->bmove(vc, info, line + ycount, x, line, x, 1,
+				   s-start);
+		console_conditional_schedule();
+		if (ycount > 0)
+			line++;
+		else {
+			line--;
+			/* NOTE: We subtract two lines from these pointers */
+			s -= vc->vc_size_row;
+			d -= vc->vc_size_row;
+		}
+	}
+}
+
 static void fbcon_redraw(struct vc_data *vc, struct display *p,
 			 int line, int count, int offset)
 {
@@ -1789,7 +1845,6 @@
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
-	struct fbcon_ops *ops = info->fbcon_par;
 	int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
 
 	if (fbcon_is_inactive(vc, info))
@@ -1813,10 +1868,15 @@
 			goto redraw_up;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
-			ops->bmove(vc, info, t + count, 0, t, 0,
-				    b - t - count, vc->vc_cols);
-			ops->clear(vc, info, b - count, 0, count,
-				  vc->vc_cols);
+			fbcon_redraw_blit(vc, info, p, t, b - t - count,
+				     count);
+			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							(b - count)),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
 			break;
 
 		case SCROLL_WRAP_MOVE:
@@ -1899,9 +1959,15 @@
 			goto redraw_down;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
-			ops->bmove(vc, info, t, 0, t + count, 0,
-				    b - t - count, vc->vc_cols);
-			ops->clear(vc, info, t, 0, count, vc->vc_cols);
+			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
+				     -count);
+			fbcon_clear(vc, t, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							t),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
 			break;
 
 		case SCROLL_WRAP_MOVE:
@@ -2937,9 +3003,48 @@
 	return found;
 }
 
-static int fbcon_fb_unregistered(int idx)
+#ifdef CONFIG_VT_HW_CONSOLE_BINDING
+static int fbcon_unbind(void)
 {
-	int i;
+	int ret;
+
+	ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
+				fbcon_is_default);
+	return ret;
+}
+#else
+static inline int fbcon_unbind(void)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
+
+static int fbcon_fb_unbind(int idx)
+{
+	int i, new_idx = -1, ret = 0;
+
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
+		if (con2fb_map[i] != idx &&
+		    con2fb_map[i] != -1) {
+			new_idx = i;
+			break;
+		}
+	}
+
+	if (new_idx != -1) {
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
+			if (con2fb_map[i] == idx)
+				set_con2fb_map(i, new_idx, 0);
+		}
+	} else
+		ret = fbcon_unbind();
+
+	return ret;
+}
+
+static int fbcon_fb_unregistered(struct fb_info *info)
+{
+	int i, idx = info->node;
 
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (con2fb_map[i] == idx)
@@ -2967,12 +3072,48 @@
 	if (!num_registered_fb)
 		unregister_con_driver(&fb_con);
 
+
+	if (primary_device == idx)
+		primary_device = -1;
+
 	return 0;
 }
 
-static int fbcon_fb_registered(int idx)
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
+static void fbcon_select_primary(struct fb_info *info)
 {
-	int ret = 0, i;
+	if (!map_override && primary_device == -1 &&
+	    fb_is_primary_device(info)) {
+		int i;
+
+		printk(KERN_INFO "fbcon: %s (fb%i) is primary device\n",
+		       info->fix.id, info->node);
+		primary_device = info->node;
+
+		for (i = first_fb_vc; i <= last_fb_vc; i++)
+			con2fb_map_boot[i] = primary_device;
+
+		if (con_is_bound(&fb_con)) {
+			printk(KERN_INFO "fbcon: Remapping primary device, "
+			       "fb%i, to tty %i-%i\n", info->node,
+			       first_fb_vc + 1, last_fb_vc + 1);
+			info_idx = primary_device;
+		}
+	}
+
+}
+#else
+static inline void fbcon_select_primary(struct fb_info *info)
+{
+	return;
+}
+#endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
+
+static int fbcon_fb_registered(struct fb_info *info)
+{
+	int ret = 0, i, idx = info->node;
+
+	fbcon_select_primary(info);
 
 	if (info_idx == -1) {
 		for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -2986,8 +3127,7 @@
 			ret = fbcon_takeover(1);
 	} else {
 		for (i = first_fb_vc; i <= last_fb_vc; i++) {
-			if (con2fb_map_boot[i] == idx &&
-			    con2fb_map[i] == -1)
+			if (con2fb_map_boot[i] == idx)
 				set_con2fb_map(i, idx, 0);
 		}
 	}
@@ -3034,12 +3174,7 @@
 		mode = fb_find_nearest_mode(fb_display[i].mode,
 					    &info->modelist);
 		fb_videomode_to_var(&var, mode);
-
-		if (vc)
-			fbcon_set_disp(info, &var, vc);
-		else
-			fbcon_preset_disp(info, &var, i);
-
+		fbcon_set_disp(info, &var, vc->vc_num);
 	}
 }
 
@@ -3114,11 +3249,14 @@
 		mode = event->data;
 		ret = fbcon_mode_deleted(info, mode);
 		break;
+	case FB_EVENT_FB_UNBIND:
+		ret = fbcon_fb_unbind(info->node);
+		break;
 	case FB_EVENT_FB_REGISTERED:
-		ret = fbcon_fb_registered(info->node);
+		ret = fbcon_fb_registered(info);
 		break;
 	case FB_EVENT_FB_UNREGISTERED:
-		ret = fbcon_fb_unregistered(info->node);
+		ret = fbcon_fb_unregistered(info);
 		break;
 	case FB_EVENT_SET_CONSOLE_MAP:
 		con2fb = event->data;
@@ -3179,8 +3317,9 @@
 	.notifier_call	= fbcon_event_notify,
 };
 
-static ssize_t store_rotate(struct class_device *class_device,
-			    const char *buf, size_t count)
+static ssize_t store_rotate(struct device *device,
+			    struct device_attribute *attr, const char *buf,
+			    size_t count)
 {
 	struct fb_info *info;
 	int rotate, idx;
@@ -3203,8 +3342,9 @@
 	return count;
 }
 
-static ssize_t store_rotate_all(struct class_device *class_device,
-				const char *buf, size_t count)
+static ssize_t store_rotate_all(struct device *device,
+				struct device_attribute *attr,const char *buf,
+				size_t count)
 {
 	struct fb_info *info;
 	int rotate, idx;
@@ -3227,7 +3367,8 @@
 	return count;
 }
 
-static ssize_t show_rotate(struct class_device *class_device, char *buf)
+static ssize_t show_rotate(struct device *device,
+			   struct device_attribute *attr,char *buf)
 {
 	struct fb_info *info;
 	int rotate = 0, idx;
@@ -3248,20 +3389,86 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
 }
 
-static struct class_device_attribute class_device_attrs[] = {
+static ssize_t show_cursor_blink(struct device *device,
+				 struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info;
+	struct fbcon_ops *ops;
+	int idx, blink = -1;
+
+	if (fbcon_has_exited)
+		return 0;
+
+	acquire_console_sem();
+	idx = con2fb_map[fg_console];
+
+	if (idx == -1 || registered_fb[idx] == NULL)
+		goto err;
+
+	info = registered_fb[idx];
+	ops = info->fbcon_par;
+
+	if (!ops)
+		goto err;
+
+	blink = (ops->flags & FBCON_FLAGS_CURSOR_TIMER) ? 1 : 0;
+err:
+	release_console_sem();
+	return snprintf(buf, PAGE_SIZE, "%d\n", blink);
+}
+
+static ssize_t store_cursor_blink(struct device *device,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct fb_info *info;
+	int blink, idx;
+	char **last = NULL;
+
+	if (fbcon_has_exited)
+		return count;
+
+	acquire_console_sem();
+	idx = con2fb_map[fg_console];
+
+	if (idx == -1 || registered_fb[idx] == NULL)
+		goto err;
+
+	info = registered_fb[idx];
+
+	if (!info->fbcon_par)
+		goto err;
+
+	blink = simple_strtoul(buf, last, 0);
+
+	if (blink) {
+		fbcon_cursor_noblink = 0;
+		fbcon_add_cursor_timer(info);
+	} else {
+		fbcon_cursor_noblink = 1;
+		fbcon_del_cursor_timer(info);
+	}
+
+err:
+	release_console_sem();
+	return count;
+}
+
+static struct device_attribute device_attrs[] = {
 	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
 	__ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all),
+	__ATTR(cursor_blink, S_IRUGO|S_IWUSR, show_cursor_blink,
+	       store_cursor_blink),
 };
 
-static int fbcon_init_class_device(void)
+static int fbcon_init_device(void)
 {
 	int i, error = 0;
 
 	fbcon_has_sysfs = 1;
 
-	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
-		error = class_device_create_file(fbcon_class_device,
-						 &class_device_attrs[i]);
+	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+		error = device_create_file(fbcon_device, &device_attrs[i]);
 
 		if (error)
 			break;
@@ -3269,8 +3476,7 @@
 
 	if (error) {
 		while (--i >= 0)
-			class_device_remove_file(fbcon_class_device,
-						 &class_device_attrs[i]);
+			device_remove_file(fbcon_device, &device_attrs[i]);
 
 		fbcon_has_sysfs = 0;
 	}
@@ -3356,16 +3562,15 @@
 
 	acquire_console_sem();
 	fb_register_client(&fbcon_event_notifier);
-	fbcon_class_device =
-	    class_device_create(fb_class, NULL, MKDEV(0, 0), NULL, "fbcon");
+	fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon");
 
-	if (IS_ERR(fbcon_class_device)) {
-		printk(KERN_WARNING "Unable to create class_device "
+	if (IS_ERR(fbcon_device)) {
+		printk(KERN_WARNING "Unable to create device "
 		       "for fbcon; errno = %ld\n",
-		       PTR_ERR(fbcon_class_device));
-		fbcon_class_device = NULL;
+		       PTR_ERR(fbcon_device));
+		fbcon_device = NULL;
 	} else
-		fbcon_init_class_device();
+		fbcon_init_device();
 
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
 		con2fb_map[i] = -1;
@@ -3379,14 +3584,13 @@
 
 #ifdef MODULE
 
-static void __exit fbcon_deinit_class_device(void)
+static void __exit fbcon_deinit_device(void)
 {
 	int i;
 
 	if (fbcon_has_sysfs) {
-		for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-			class_device_remove_file(fbcon_class_device,
-						 &class_device_attrs[i]);
+		for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+			device_remove_file(fbcon_device, &device_attrs[i]);
 
 		fbcon_has_sysfs = 0;
 	}
@@ -3396,8 +3600,8 @@
 {
 	acquire_console_sem();
 	fb_unregister_client(&fbcon_event_notifier);
-	fbcon_deinit_class_device();
-	class_device_destroy(fb_class, MKDEV(0, 0));
+	fbcon_deinit_device();
+	device_destroy(fb_class, MKDEV(0, 0));
 	fbcon_exit();
 	release_console_sem();
 	unregister_con_driver(&fb_con);
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 8b76273..b0be7ea 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -94,7 +94,7 @@
 struct fb_info_control {
 	struct fb_info		info;
 	struct fb_par_control	par;
-	u32			pseudo_palette[17];
+	u32			pseudo_palette[16];
 		
 	struct cmap_regs	__iomem *cmap_regs;
 	unsigned long		cmap_regs_phys;
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 94a66c2..e23324d 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -1068,15 +1068,18 @@
 		out8(0x3C9, green >> 10);
 		out8(0x3C9, blue >> 10);
 
-	} else if (bpp == 16)	// RGB 565
-		((u32 *) info->pseudo_palette)[regno] =
-		    (red & 0xF800) |
-		    ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-	else if (bpp == 32)	// ARGB 8888
-		((u32 *) info->pseudo_palette)[regno] =
-		    ((transp & 0xFF00) << 16) |
-		    ((red & 0xFF00) << 8) |
-		    ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+	} else if (regno < 16) {
+		if (bpp == 16)	// RGB 565
+			((u32 *) info->pseudo_palette)[regno] =
+				(red & 0xF800) |
+				((green & 0xFC00) >> 5) |
+				((blue & 0xF800) >> 11);
+		else if (bpp == 32)	// ARGB 8888
+			((u32 *) info->pseudo_palette)[regno] =
+				((transp & 0xFF00) << 16) |
+				((red & 0xFF00) << 8) |
+				((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+	}
 
 	return 0;
 }
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index ca2c54c..33be46c 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -63,23 +63,12 @@
 
 struct epson1355_par {
 	unsigned long reg_addr;
+	u32 pseudo_palette[16];
 };
 
 /* ------------------------------------------------------------------------- */
 
-#ifdef CONFIG_SUPERH
-
-static inline u8 epson1355_read_reg(int index)
-{
-	return ctrl_inb(par.reg_addr + index);
-}
-
-static inline void epson1355_write_reg(u8 data, int index)
-{
-	ctrl_outb(data, par.reg_addr + index);
-}
-
-#elif defined(CONFIG_ARM)
+#if defined(CONFIG_ARM)
 
 # ifdef CONFIG_ARCH_CEIVA
 #  include <asm/arch/hardware.h>
@@ -289,7 +278,7 @@
 	struct epson1355_par *par = info->par;
 
 	switch (blank_mode) {
-	case FB_BLANK_UNBLANKING:
+	case FB_BLANK_UNBLANK:
 	case FB_BLANK_NORMAL:
 		lcd_enable(par, 1);
 		backlight_enable(1);
@@ -635,7 +624,7 @@
 		goto bail;
 	}
 
-	info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(struct epson1355_par), &dev->dev);
 	if (!info) {
 		rc = -ENOMEM;
 		goto bail;
@@ -648,7 +637,7 @@
 		rc = -ENOMEM;
 		goto bail;
 	}
-	info->pseudo_palette = (void *)(default_par + 1);
+	info->pseudo_palette = default_par->pseudo_palette;
 
 	info->screen_base = ioremap(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
 	if (!info->screen_base) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 38c2e25..215ac57 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -33,18 +33,11 @@
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/efi.h>
-
-#if defined(__mc68000__) || defined(CONFIG_APUS)
-#include <asm/setup.h>
-#endif
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
 #include <linux/fb.h>
 
+#include <asm/fb.h>
+
+
     /*
      *  Frame buffer device initialization and setup routines
      */
@@ -411,10 +404,146 @@
 	}
 }
 
+static int fb_show_logo_line(struct fb_info *info, int rotate,
+			     const struct linux_logo *logo, int y,
+			     unsigned int n)
+{
+	u32 *palette = NULL, *saved_pseudo_palette = NULL;
+	unsigned char *logo_new = NULL, *logo_rotate = NULL;
+	struct fb_image image;
+
+	/* Return if the frame buffer is not mapped or suspended */
+	if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
+	    info->flags & FBINFO_MODULE)
+		return 0;
+
+	image.depth = 8;
+	image.data = logo->data;
+
+	if (fb_logo.needs_cmapreset)
+		fb_set_logocmap(info, logo);
+
+	if (fb_logo.needs_truepalette ||
+	    fb_logo.needs_directpalette) {
+		palette = kmalloc(256 * 4, GFP_KERNEL);
+		if (palette == NULL)
+			return 0;
+
+		if (fb_logo.needs_truepalette)
+			fb_set_logo_truepalette(info, logo, palette);
+		else
+			fb_set_logo_directpalette(info, logo, palette);
+
+		saved_pseudo_palette = info->pseudo_palette;
+		info->pseudo_palette = palette;
+	}
+
+	if (fb_logo.depth <= 4) {
+		logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
+		if (logo_new == NULL) {
+			kfree(palette);
+			if (saved_pseudo_palette)
+				info->pseudo_palette = saved_pseudo_palette;
+			return 0;
+		}
+		image.data = logo_new;
+		fb_set_logo(info, logo, logo_new, fb_logo.depth);
+	}
+
+	image.dx = 0;
+	image.dy = y;
+	image.width = logo->width;
+	image.height = logo->height;
+
+	if (rotate) {
+		logo_rotate = kmalloc(logo->width *
+				      logo->height, GFP_KERNEL);
+		if (logo_rotate)
+			fb_rotate_logo(info, logo_rotate, &image, rotate);
+	}
+
+	fb_do_show_logo(info, &image, rotate, n);
+
+	kfree(palette);
+	if (saved_pseudo_palette != NULL)
+		info->pseudo_palette = saved_pseudo_palette;
+	kfree(logo_new);
+	kfree(logo_rotate);
+	return logo->height;
+}
+
+
+#ifdef CONFIG_FB_LOGO_EXTRA
+
+#define FB_LOGO_EX_NUM_MAX 10
+static struct logo_data_extra {
+	const struct linux_logo *logo;
+	unsigned int n;
+} fb_logo_ex[FB_LOGO_EX_NUM_MAX];
+static unsigned int fb_logo_ex_num;
+
+void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
+{
+	if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
+		return;
+
+	fb_logo_ex[fb_logo_ex_num].logo = logo;
+	fb_logo_ex[fb_logo_ex_num].n = n;
+	fb_logo_ex_num++;
+}
+
+static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
+				  unsigned int yres)
+{
+	unsigned int i;
+
+	/* FIXME: logo_ex supports only truecolor fb. */
+	if (info->fix.visual != FB_VISUAL_TRUECOLOR)
+		fb_logo_ex_num = 0;
+
+	for (i = 0; i < fb_logo_ex_num; i++) {
+		height += fb_logo_ex[i].logo->height;
+		if (height > yres) {
+			height -= fb_logo_ex[i].logo->height;
+			fb_logo_ex_num = i;
+			break;
+		}
+	}
+	return height;
+}
+
+static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+	unsigned int i;
+
+	for (i = 0; i < fb_logo_ex_num; i++)
+		y += fb_show_logo_line(info, rotate,
+				       fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
+
+	return y;
+}
+
+#else /* !CONFIG_FB_LOGO_EXTRA */
+
+static inline int fb_prepare_extra_logos(struct fb_info *info,
+					 unsigned int height,
+					 unsigned int yres)
+{
+	return height;
+}
+
+static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+	return y;
+}
+
+#endif /* CONFIG_FB_LOGO_EXTRA */
+
+
 int fb_prepare_logo(struct fb_info *info, int rotate)
 {
 	int depth = fb_get_color_depth(&info->var, &info->fix);
-	int yres;
+	unsigned int yres;
 
 	memset(&fb_logo, 0, sizeof(struct logo_data));
 
@@ -456,7 +585,7 @@
 	if (!fb_logo.logo) {
 		return 0;
 	}
-	
+
 	if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
 		yres = info->var.yres;
 	else
@@ -473,75 +602,20 @@
 	else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
 		fb_logo.depth = 4;
 	else
-		fb_logo.depth = 1;		
-	return fb_logo.logo->height;
+		fb_logo.depth = 1;
+
+	return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
 }
 
 int fb_show_logo(struct fb_info *info, int rotate)
 {
-	u32 *palette = NULL, *saved_pseudo_palette = NULL;
-	unsigned char *logo_new = NULL, *logo_rotate = NULL;
-	struct fb_image image;
+	int y;
 
-	/* Return if the frame buffer is not mapped or suspended */
-	if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING ||
-	    info->flags & FBINFO_MODULE)
-		return 0;
+	y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
+			      num_online_cpus());
+	y = fb_show_extra_logos(info, y, rotate);
 
-	image.depth = 8;
-	image.data = fb_logo.logo->data;
-
-	if (fb_logo.needs_cmapreset)
-		fb_set_logocmap(info, fb_logo.logo);
-
-	if (fb_logo.needs_truepalette || 
-	    fb_logo.needs_directpalette) {
-		palette = kmalloc(256 * 4, GFP_KERNEL);
-		if (palette == NULL)
-			return 0;
-
-		if (fb_logo.needs_truepalette)
-			fb_set_logo_truepalette(info, fb_logo.logo, palette);
-		else
-			fb_set_logo_directpalette(info, fb_logo.logo, palette);
-
-		saved_pseudo_palette = info->pseudo_palette;
-		info->pseudo_palette = palette;
-	}
-
-	if (fb_logo.depth <= 4) {
-		logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height, 
-				   GFP_KERNEL);
-		if (logo_new == NULL) {
-			kfree(palette);
-			if (saved_pseudo_palette)
-				info->pseudo_palette = saved_pseudo_palette;
-			return 0;
-		}
-		image.data = logo_new;
-		fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
-	}
-
-	image.dx = 0;
-	image.dy = 0;
-	image.width = fb_logo.logo->width;
-	image.height = fb_logo.logo->height;
-
-	if (rotate) {
-		logo_rotate = kmalloc(fb_logo.logo->width *
-				      fb_logo.logo->height, GFP_KERNEL);
-		if (logo_rotate)
-			fb_rotate_logo(info, logo_rotate, &image, rotate);
-	}
-
-	fb_do_show_logo(info, &image, rotate, num_online_cpus());
-
-	kfree(palette);
-	if (saved_pseudo_palette != NULL)
-		info->pseudo_palette = saved_pseudo_palette;
-	kfree(logo_new);
-	kfree(logo_rotate);
-	return fb_logo.logo->height;
+	return y;
 }
 #else
 int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
@@ -1155,17 +1229,15 @@
 }
 #endif
 
-static int 
+static int
 fb_mmap(struct file *file, struct vm_area_struct * vma)
 {
 	int fbidx = iminor(file->f_path.dentry->d_inode);
 	struct fb_info *info = registered_fb[fbidx];
 	struct fb_ops *fb = info->fbops;
 	unsigned long off;
-#if !defined(__sparc__) || defined(__sparc_v9__)
 	unsigned long start;
 	u32 len;
-#endif
 
 	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
 		return -EINVAL;
@@ -1180,12 +1252,6 @@
 		return res;
 	}
 
-#if defined(__sparc__) && !defined(__sparc_v9__)
-	/* Should never get here, all fb drivers should have their own
-	   mmap routines */
-	return -EINVAL;
-#else
-	/* !sparc32... */
 	lock_kernel();
 
 	/* frame buffer memory */
@@ -1209,50 +1275,11 @@
 	vma->vm_pgoff = off >> PAGE_SHIFT;
 	/* This is an IO map - tell maydump to skip this VMA */
 	vma->vm_flags |= VM_IO | VM_RESERVED;
-#if defined(__mc68000__)
-#if defined(CONFIG_SUN3)
-	pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
-#elif defined(CONFIG_MMU)
-	if (CPU_IS_020_OR_030)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
-	if (CPU_IS_040_OR_060) {
-		pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
-		/* Use no-cache mode, serialized */
-		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
-	}
-#endif
-#elif defined(__powerpc__)
-	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__)
-	/* Caching is off in the I/O space quadrant by design.  */
-#elif defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#elif defined(__mips__) || defined(__sparc_v9__)
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#elif defined(__hppa__)
-	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-#elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
-	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-#elif defined(__avr32__)
-	vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
-				      & ~_PAGE_CACHABLE)
-				     | (_PAGE_BUFFER | _PAGE_DIRTY));
-#elif defined(__ia64__)
-	if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
-		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-	else
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#else
-#warning What do we have to do here??
-#endif
+	fb_pgprotect(file, vma, off);
 	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
 	return 0;
-#endif /* !sparc32 */
 }
 
 static int
@@ -1388,17 +1415,34 @@
  *
  *	Returns negative errno on error, or zero for success.
  *
+ *      This function will also notify the framebuffer console
+ *      to release the driver.
+ *
+ *      This is meant to be called within a driver's module_exit()
+ *      function. If this is called outside module_exit(), ensure
+ *      that the driver implements fb_open() and fb_release() to
+ *      check that no processes are using the device.
  */
 
 int
 unregister_framebuffer(struct fb_info *fb_info)
 {
 	struct fb_event event;
-	int i;
+	int i, ret = 0;
 
 	i = fb_info->node;
-	if (!registered_fb[i])
-		return -EINVAL;
+	if (!registered_fb[i]) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	event.info = fb_info;
+	ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+
+	if (ret) {
+		ret = -EINVAL;
+		goto done;
+	}
 
 	if (fb_info->pixmap.addr &&
 	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
@@ -1410,7 +1454,8 @@
 	device_destroy(fb_class, MKDEV(FB_MAJOR, i));
 	event.info = fb_info;
 	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
-	return 0;
+done:
+	return ret;
 }
 
 /**
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 70ff55b..6c91c61 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -195,13 +195,15 @@
 static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                          u_int transp, struct fb_info *info)
 {
-	if (regno > info->cmap.len)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
+	if (regno < 16) {
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
 
-	((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
+		((u32*)(info->pseudo_palette))[regno] = (red << 16) |
+			(green << 8) | blue;
+	}
+
 	return 0;
 }
 
@@ -237,7 +239,7 @@
 	if (!zorro_request_device(z,"fm2fb"))
 		return -ENXIO;
 
-	info = framebuffer_alloc(256 * sizeof(u32), &z->dev);
+	info = framebuffer_alloc(16 * sizeof(u32), &z->dev);
 	if (!info) {
 		zorro_release_device(z);
 		return -ENOMEM;
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index bf0e60b..b9b572b 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -86,7 +86,7 @@
 
 static int ypan, ywrap;
 
-static uint32_t pseudo_palette[256];
+static uint32_t pseudo_palette[16];
 
 static char *mode_option __initdata = NULL;
 
@@ -854,8 +854,7 @@
 	green >>= 8;
 	blue >>= 8;
 
-	switch (info->var.bits_per_pixel) {
-	case 8:
+	if (info->var.bits_per_pixel <= 8) {
 		/* wait for the color map FIFO to have a free entry */
 		for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
 			udelay(10);
@@ -864,23 +863,25 @@
 			return 1;
 		}
 		gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
-		break;
-	case 15:
-	case 16:
-		red >>= 3;
-		green >>= 3;
-		blue >>= 3;
-		pseudo_palette[regno] =
-			(red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset);
-		break;
-	case 32:
-		pseudo_palette[regno] =
-			(red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset);
-		break;
+	} else if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 15:
+		case 16:
+			red >>= 3;
+			green >>= 3;
+			blue >>= 3;
+			pseudo_palette[regno] =
+				(red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue << info->var.blue.offset);
+			break;
+		case 32:
+			pseudo_palette[regno] =
+				(red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue << info->var.blue.offset);
+			break;
+		}
 	}
 
 	return 0;
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 889e4ea..328ae6c 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -266,7 +266,7 @@
 	struct i810fb_i2c_chan   chan[3];
 	struct mutex		 open_lock;
 	unsigned int		 use_count;
-	u32 pseudo_palette[17];
+	u32 pseudo_palette[16];
 	unsigned long mmio_start_phys;
 	u8 __iomem *mmio_start_virtual;
 	u8 *edid;
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 80b94c1..6148300 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -302,7 +302,7 @@
 	u32 ring_lockup;
 
 	/* palette */
-	u32 pseudo_palette[17];
+	u32 pseudo_palette[16];
 
 	/* chip info */
 	int pci_chipset;
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 9397bce..da219c0 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -10,6 +10,11 @@
 
 if LOGO
 
+config FB_LOGO_EXTRA
+	bool
+	depends on FB
+	default y if SPU_BASE
+
 config LOGO_LINUX_MONO
 	bool "Standard black and white Linux logo"
 	default y
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index b985dfa..a5fc4ed 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -14,6 +14,8 @@
 obj-$(CONFIG_LOGO_SUPERH_CLUT224)	+= logo_superh_clut224.o
 obj-$(CONFIG_LOGO_M32R_CLUT224)		+= logo_m32r_clut224.o
 
+obj-$(CONFIG_SPU_BASE)			+= logo_spe_clut224.o
+
 # How to generate logo's
 
 # Use logo-cfiles to retrieve list of .c files to be built
diff --git a/drivers/video/logo/logo_spe_clut224.ppm b/drivers/video/logo/logo_spe_clut224.ppm
new file mode 100644
index 0000000..d36ad62
--- /dev/null
+++ b/drivers/video/logo/logo_spe_clut224.ppm
@@ -0,0 +1,283 @@
+P3
+40 40
+255
+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  2 2 2  6 6 6
+15 15 15  21 21 21  19 19 19  14 14 14  6 6 6  2 2 2
+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  2 2 2  21 21 21  55 55 55
+56 56 56  54 54 54  53 53 53  60 60 60  56 56 56  25 25 25
+6 6 6  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  2 2 2  27 27 27  62 62 62  17 17 19
+2 2 6  2 2 6  2 2 6  2 2 6  16 16 18  57 57 57
+45 45 45  8 8 8  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 1  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  16 16 16  62 62 62  8 8 10  2 2 6
+2 2 6  2 2 6  2 2 6  12 12 14  67 67 67  16 16 17
+45 45 45  41 41 41  4 4 4  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  2 2 2  35 35 35  40 40 40  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  15 15 17  70 70 70  27 27 27
+3 3 6  62 62 62  20 20 20  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  4 4 4  58 58 58  12 12 14  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  4 4 7  4 4 7  2 2 6
+2 2 6  34 34 36  40 40 40  3 3 3  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  7 7 7  64 64 64  2 2 6  5 5 5  17 17 17
+3 3 6  2 2 6  2 2 6  15 15 15  21 21 21  7 7 10
+2 2 6  8 8 10  62 62 62  6 6 6  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  7 7 7  66 66 66  5 5 8  122 122 122  122 122 122
+9 9 11  3 3 6  104 96 81  179 179 179  122 122 122  13 13 13
+2 2 6  2 2 6  67 67 67  10 10 10  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  7 7 7  65 65 65  41 41 43  152 149 142  192 191 189
+48 48 49  23 23 24  228 210 210  86 86 86  192 191 189  59 59 61
+2 2 6  2 2 6  64 64 64  14 14 14  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 1  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  7 7 7  66 66 66  59 59 59  59 59 61  86 86 86
+99 84 50  78 66 28  152 149 142  5 5 8  122 122 122  104 96 81
+2 2 6  2 2 6  67 67 67  14 14 14  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  5 5 5  63 63 63  24 24 24  152 149 142  175 122 13
+238 184 12  220 170 13  226 181 52  112 86 32  194 165 151  46 46 47
+2 2 6  2 2 6  65 65 65  17 17 17  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  5 5 5  59 59 59  21 21 21  175 122 13  231 174 11
+240 192 13  237 183 61  240 192 13  240 192 13  234 179 16  81 64 9
+2 2 6  2 2 6  63 63 63  25 25 25  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  5 5 5  54 54 54  51 48 39  189 138 9  238 184 12
+240 192 13  240 192 13  240 192 13  215 161 11  207 152 19  81 64 9
+16 16 18  5 5 8  40 40 40  44 44 44  4 4 4  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  5 5 5  59 59 59  27 27 27  126 107 64  187 136 12
+220 170 13  201 147 20  189 138 9  198 154 46  199 182 125  70 70 70
+27 27 27  104 96 81  12 12 14  70 70 70  16 16 16  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  17 17 17  70 70 70  12 12 12  168 168 168  174 135 135
+175 122 13  175 122 13  178 151 83  192 191 189  233 233 233  179 179 179
+3 3 6  29 29 31  3 3 6  41 41 41  44 44 44  5 5 5
+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
+8 8 8  53 53 53  44 44 44  59 59 59  238 238 238  192 191 189
+192 191 189  192 191 189  221 205 205  240 240 240  253 253 253  253 253 253
+70 70 70  2 2 6  2 2 6  5 5 8  67 67 67  22 22 22
+2 2 2  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  5 5 5
+38 38 38  56 56 56  7 7 9  221 205 205  253 253 253  233 233 233
+221 205 205  233 233 233  251 251 251  253 253 253  253 253 253  253 253 253
+192 191 189  2 2 6  2 2 6  2 2 6  25 25 25  64 64 64
+15 15 15  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  2 2 2  27 27 27
+66 66 66  7 7 9  86 86 86  252 252 252  253 253 253  253 253 253
+252 252 252  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+244 244 244  19 19 21  2 2 6  2 2 6  2 2 6  38 38 38
+54 54 54  10 10 10  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  14 14 14  62 62 62
+10 10 12  3 3 6  122 122 122  235 235 235  251 251 251  248 248 248
+235 235 235  248 248 248  252 252 252  246 246 246  233 233 233  237 228 228
+223 207 207  70 70 70  2 2 6  2 2 6  2 2 6  2 2 6
+46 46 47  38 38 38  4 4 4  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  2 2 2  33 33 33  44 44 44
+4 4 7  9 9 11  168 168 168  240 240 240  252 252 252  252 252 252
+246 246 246  253 253 253  253 253 253  251 251 251  245 241 241  233 233 233
+221 205 205  192 191 189  29 29 31  27 27 27  9 9 12  2 2 6
+3 3 6  65 65 65  15 15 15  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  6 6 6  59 59 59  19 19 21
+24 24 24  86 86 86  249 249 249  253 253 253  253 253 253  253 253 253
+253 253 253  228 210 210  241 230 230  253 253 253  253 253 253  253 253 253
+251 251 251  228 210 210  152 149 142  5 5 8  27 27 27  4 4 7
+2 2 6  46 46 47  34 34 34  2 2 2  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  16 16 16  67 67 67  19 19 21
+12 12 14  223 207 207  254 20 20  254 20 20  253 127 127  242 223 223
+254 20 20  253 127 127  254 48 48  242 223 223  254 86 86  254 20 20
+254 20 20  253 137 137  233 233 233  32 32 32  35 35 35  23 23 24
+2 2 6  15 15 15  60 60 60  6 6 6  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  4 4 4  38 38 38  48 48 49  22 22 22
+86 86 86  253 253 253  254 20 20  241 230 230  227 216 186  253 137 137
+253 137 137  253 253 253  253 137 137  253 137 137  254 48 48  253 253 253
+253 253 253  253 253 253  253 253 253  62 62 62  2 2 6  23 23 24
+2 2 6  2 2 6  62 62 62  17 17 17  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  14 14 14  70 70 70  14 14 14  16 16 18
+179 179 179  253 253 253  227 216 186  254 48 48  240 219 160  253 127 127
+254 20 20  253 137 137  254 86 86  231 203 141  254 20 20  254 20 20
+253 137 137  253 253 253  253 253 253  104 96 81  2 2 6  23 23 24
+2 2 6  2 2 6  46 46 47  27 27 27  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  4 4 4  39 39 39  42 42 43  19 19 21  13 13 13
+228 210 210  242 223 223  253 253 253  242 223 223  253 127 127  253 127 127
+253 127 127  253 127 127  253 137 137  253 253 253  254 48 48  253 253 253
+228 210 210  253 253 253  253 253 253  122 122 122  2 2 6  19 19 19
+2 2 6  2 2 6  39 39 39  38 38 38  3 3 3  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  8 8 8  60 60 60  3 3 6  33 33 33  38 38 38
+253 137 137  254 86 86  253 137 137  254 86 86  253 137 137  209 197 168
+253 127 127  253 253 253  253 253 253  253 253 253  253 127 127  254 86 86
+254 86 86  253 137 137  253 253 253  122 122 122  2 2 6  17 17 17
+2 2 6  2 2 6  34 34 36  42 42 43  3 3 3  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  13 13 13  59 59 59  2 2 6  9 9 12  56 56 56
+252 252 252  240 219 160  253 137 137  240 219 160  253 253 253  237 228 228
+254 86 86  253 253 253  253 253 253  253 253 253  253 253 253  242 223 223
+227 216 186  249 249 249  253 253 253  122 122 122  16 16 17  17 17 17
+12 12 14  3 3 6  39 39 39  38 38 38  3 3 3  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  2 2 2
+5 5 5  22 22 22  104 96 81  187 136 12  207 152 19  51 48 39
+221 205 205  253 253 253  253 253 253  253 253 253  253 253 253  240 240 240
+250 247 243  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  250 247 243  240 219 160  99 84 50  5 5 8  2 2 6
+7 7 9  46 46 47  58 58 58  35 35 35  3 3 3  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  8 8 8  33 33 33
+58 58 58  86 86 86  170 136 53  239 182 13  246 190 14  220 170 13
+44 38 29  179 179 179  253 253 253  253 253 253  253 253 253  240 240 240
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  240 219 160  240 192 13  112 86 32  2 2 6  2 2 6
+3 3 6  41 33 20  220 170 13  53 53 53  4 4 4  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  2 2 2  32 32 32  150 116 44
+215 161 11  215 161 11  228 170 11  245 188 14  246 190 14  246 190 14
+187 136 12  9 9 11  122 122 122  251 251 251  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+248 248 248  211 196 135  239 182 13  175 122 13  6 5 6  2 2 6
+16 14 12  187 136 12  238 184 12  84 78 65  10 10 10  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  4 4 4  53 53 53  207 152 19
+242 185 13  245 188 14  246 190 14  246 190 14  246 190 14  246 190 14
+240 192 13  81 64 9  2 2 6  86 86 86  244 244 244  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+233 233 233  199 182 125  231 174 11  207 152 19  175 122 13  175 122 13
+201 147 20  239 182 13  244 187 14  150 116 44  35 35 35  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  5 5 5  53 53 53  201 147 20
+242 185 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  220 170 13  13 11 10  2 2 6  152 149 142  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+235 235 235  199 182 125  228 170 11  234 177 12  226 168 11  226 168 11
+234 177 12  246 190 14  246 190 14  234 179 16  126 107 64  36 36 36
+6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  3 3 3  48 48 49  189 142 35
+242 185 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  140 112 39  36 36 36  192 191 189  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+192 191 189  112 86 32  226 168 11  244 187 14  244 187 14  244 187 14
+245 188 14  246 190 14  246 190 14  246 190 14  242 185 13  150 116 44
+27 27 27  2 2 2  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  58 58 58  189 142 35
+239 182 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  239 188 14  209 197 168  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  252 252 252  168 168 168
+16 16 18  97 67 8  228 170 11  245 188 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  244 187 14  198 154 46
+35 35 35  3 3 3  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  13 13 13  84 78 65  215 161 11
+244 187 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  238 184 12  187 136 12  168 168 168  244 244 244
+253 253 253  252 252 252  240 240 240  179 179 179  67 67 67  2 2 6
+2 2 6  97 67 8  228 170 11  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  245 188 14  234 177 12  189 142 35  86 77 61
+16 16 16  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  13 13 13  103 92 56  207 152 19
+228 170 11  234 177 12  239 182 13  242 186 14  245 188 14  246 190 14
+246 190 14  246 190 14  239 182 13  189 138 9  41 33 20  10 10 12
+30 30 31  23 23 24  5 5 8  2 2 6  2 2 6  2 2 6
+4 4 6  112 86 32  215 161 11  245 188 14  246 190 14  245 188 14
+239 182 13  228 170 11  189 142 35  104 96 81  48 48 49  17 17 17
+2 2 2  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  5 5 5  39 39 39  103 92 56
+141 109 44  175 122 13  187 136 12  189 138 9  207 152 19  228 170 11
+239 182 13  239 182 13  215 161 11  175 122 13  41 33 20  2 2 6
+15 15 17  20 20 22  20 20 22  20 20 22  20 20 22  8 8 10
+4 4 6  97 67 8  189 138 9  231 174 11  239 182 13  226 168 11
+189 138 9  126 107 64  59 59 59  21 21 21  5 5 5  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  5 5 5  17 17 17
+34 34 34  57 57 57  84 78 65  103 92 56  125 101 41  140 112 39
+175 122 13  175 122 13  175 122 13  97 67 8  72 67 58  84 78 65
+60 60 60  56 56 56  56 56 56  56 56 56  57 57 57  65 65 65
+86 86 86  95 73 34  175 122 13  187 136 12  187 136 12  175 122 13
+103 92 56  41 41 41  10 10 10  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
+2 2 2  4 4 4  12 12 12  24 24 24  40 40 40  70 70 70
+86 77 61  95 73 34  88 72 41  72 67 58  36 36 36  10 10 10
+5 5 5  5 5 5  5 5 5  4 4 4  5 5 5  6 6 6
+22 22 22  61 61 59  88 72 41  112 86 32  112 86 32  84 78 65
+32 32 32  6 6 6  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  3 3 3  10 10 10
+21 21 21  33 33 33  31 31 31  16 16 16  2 2 2  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+2 2 2  12 12 12  30 30 31  40 40 40  32 32 32  16 16 16
+2 2 2  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
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index f7d647d..aa8c714 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -170,7 +170,7 @@
 };
 
 static struct fb_info fb_info;
-static u32 pseudo_palette[17];
+static u32 pseudo_palette[16];
 static int inverse   = 0;
 static int vidtest   = 0;
 
@@ -529,56 +529,63 @@
 	if (regno >= fb_info->cmap.len)
 		return 1;
 
-	switch (fb_info->var.bits_per_pixel) {
-	case 1:
-		/* We shouldn't get here */
-		break;
-	case 2:
-	case 4:
-	case 8:
-		if (macfb_setpalette)
-			macfb_setpalette(regno, red, green, blue, fb_info);
-		else
-			return 1;
-		break;
-	case 16:
-		if (fb_info->var.red.offset == 10) {
-			/* 1:5:5:5 */
-			((u32*) (fb_info->pseudo_palette))[regno] =
+	if (fb_info->var.bits_per_pixel <= 8) {
+		switch (fb_info->var.bits_per_pixel) {
+		case 1:
+			/* We shouldn't get here */
+			break;
+		case 2:
+		case 4:
+		case 8:
+			if (macfb_setpalette)
+				macfb_setpalette(regno, red, green, blue,
+						 fb_info);
+			else
+				return 1;
+			break;
+		}
+	} else if (regno < 16) {
+		switch (fb_info->var.bits_per_pixel) {
+		case 16:
+			if (fb_info->var.red.offset == 10) {
+				/* 1:5:5:5 */
+				((u32*) (fb_info->pseudo_palette))[regno] =
 					((red   & 0xf800) >>  1) |
 					((green & 0xf800) >>  6) |
 					((blue  & 0xf800) >> 11) |
 					((transp != 0) << 15);
-		} else {
-			/* 0:5:6:5 */
-			((u32*) (fb_info->pseudo_palette))[regno] =
+			} else {
+				/* 0:5:6:5 */
+				((u32*) (fb_info->pseudo_palette))[regno] =
 					((red   & 0xf800)      ) |
 					((green & 0xfc00) >>  5) |
 					((blue  & 0xf800) >> 11);
+			}
+			break;
+			/* I'm pretty sure that one or the other of these
+			   doesn't exist on 68k Macs */
+		case 24:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((u32 *)(fb_info->pseudo_palette))[regno] =
+				(red   << fb_info->var.red.offset)   |
+				(green << fb_info->var.green.offset) |
+				(blue  << fb_info->var.blue.offset);
+			break;
+		case 32:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((u32 *)(fb_info->pseudo_palette))[regno] =
+				(red   << fb_info->var.red.offset)   |
+				(green << fb_info->var.green.offset) |
+				(blue  << fb_info->var.blue.offset);
+			break;
 		}
-		break;	
-		/* I'm pretty sure that one or the other of these
-		   doesn't exist on 68k Macs */
-	case 24:
-		red   >>= 8;
-		green >>= 8;
-		blue  >>= 8;
-		((u32 *)(fb_info->pseudo_palette))[regno] =
-			(red   << fb_info->var.red.offset)   |
-			(green << fb_info->var.green.offset) |
-			(blue  << fb_info->var.blue.offset);
-		break;
-	case 32:
-		red   >>= 8;
-		green >>= 8;
-		blue  >>= 8;
-		((u32 *)(fb_info->pseudo_palette))[regno] =
-			(red   << fb_info->var.red.offset)   |
-			(green << fb_info->var.green.offset) |
-			(blue  << fb_info->var.blue.offset);
-		break;
-    }
-    return 0;
+	}
+
+	return 0;
 }
 
 static struct fb_ops macfb_ops = {
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index ab21495..083f603 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -369,9 +369,8 @@
  *
  */
 
-int __devinit mac_find_mode(struct fb_var_screeninfo *var,
-			    struct fb_info *info, const char *mode_option,
-			    unsigned int default_bpp)
+int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+		  const char *mode_option, unsigned int default_bpp)
 {
     const struct fb_videomode *db = NULL;
     unsigned int dbsize = 0;
diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h
index babeb81..b86ba08 100644
--- a/drivers/video/macmodes.h
+++ b/drivers/video/macmodes.h
@@ -55,10 +55,10 @@
 extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
 			    int *cmode);
 extern int mac_map_monitor_sense(int sense);
-extern int __devinit mac_find_mode(struct fb_var_screeninfo *var,
-				   struct fb_info *info,
-				   const char *mode_option,
-				   unsigned int default_bpp);
+extern int mac_find_mode(struct fb_var_screeninfo *var,
+			 struct fb_info *info,
+			 const char *mode_option,
+			 unsigned int default_bpp);
 
 
     /*
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index c57aaad..3660d26 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -91,7 +91,6 @@
 	for (i = 0; i < 16; i++) {
 		pal[i] = i * 0x11111111U;
 	}
-	pal[i] = 0xFFFFFFFF;
 }
 
 static inline void matrox_cfb8_pal(u_int32_t* pal) {
@@ -100,7 +99,6 @@
 	for (i = 0; i < 16; i++) {
 		pal[i] = i * 0x01010101U;
 	}
-	pal[i] = 0x0F0F0F0F;
 }
 
 static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area);
@@ -145,13 +143,10 @@
 					ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit;
 				}
 				break;
-		case 16:	if (ACCESS_FBINFO(fbcon).var.green.length == 5) {
+		case 16:	if (ACCESS_FBINFO(fbcon).var.green.length == 5)
 					maccess = 0xC0000001;
-					ACCESS_FBINFO(cmap[16]) = 0x7FFF7FFF;
-				} else {
+				else
 					maccess = 0x40000001;
-					ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
-				}
 				mopmode = M_OPMODE_16BPP;
 				if (accel) {
 					ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
@@ -161,7 +156,6 @@
 				break;
 		case 24:	maccess = 0x00000003;
 				mopmode = M_OPMODE_24BPP;
-				ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
 				if (accel) {
 					ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
 					ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect;
@@ -170,7 +164,6 @@
 				break;
 		case 32:	maccess = 0x00000002;
 				mopmode = M_OPMODE_32BPP;
-				ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
 				if (accel) {
 					ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
 					ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 886e475..86ca7b1 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -679,6 +679,8 @@
 		mga_outb(M_DAC_VAL, blue);
 		break;
 	case 16:
+		if (regno >= 16)
+			break;
 		{
 			u_int16_t col =
 				(red << ACCESS_FBINFO(fbcon).var.red.offset)     |
@@ -690,6 +692,8 @@
 		break;
 	case 24:
 	case 32:
+		if (regno >= 16)
+			break;
 		ACCESS_FBINFO(cmap[regno]) =
 			(red   << ACCESS_FBINFO(fbcon).var.red.offset)   |
 			(green << ACCESS_FBINFO(fbcon).var.green.offset) |
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 9c25c2f..d59577c 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -518,7 +518,7 @@
 					dll:1;
 				      } memory;
 			      } values;
-	u_int32_t cmap[17];
+	u_int32_t cmap[16];
 };
 
 #define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 03ae55b..4b3344e 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -163,11 +163,6 @@
 	ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004;
 }
 
-static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info) {
-	/* no acceleration for secondary head... */
-	m2info->cmap[16] = 0xFFFFFFFF;
-}
-
 static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
 		struct fb_var_screeninfo* var) {
 	unsigned int pos;
@@ -385,7 +380,6 @@
 			}
 		}
 		up_read(&ACCESS_FBINFO(altout).lock);
-		matroxfb_dh_cfbX_init(m2info);
 	}
 	m2info->initialized = 1;
 	return 0;
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
index 1771776..1005582 100644
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ b/drivers/video/matrox/matroxfb_crtc2.h
@@ -28,7 +28,7 @@
 
 	unsigned int		interlaced:1;
 
-	u_int32_t cmap[17];
+	u_int32_t cmap[16];
 };
 
 #endif /* __MATROXFB_CRTC2_H__ */
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index aff11bb..d1a1054 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -150,8 +150,7 @@
 		M = pll & 0xFF;
 		N = (pll >> 8) & 0xFF;
 		if (((par->Chipset & 0xfff0) == 0x0290) ||
-			((par->Chipset & 0xfff0) == 0x0390) ||
-			((par->Chipset & 0xfff0) == 0x02E0)) {
+		    ((par->Chipset & 0xfff0) == 0x0390)) {
 			MB = 1;
 			NB = 1;
 		} else {
@@ -161,7 +160,7 @@
 		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
 
 		pll = NV_RD32(par->PMC, 0x4000);
-		P = (pll >> 16) & 0x03;
+		P = (pll >> 16) & 0x07;
 		pll = NV_RD32(par->PMC, 0x4004);
 		M = pll & 0xFF;
 		N = (pll >> 8) & 0xFF;
@@ -892,11 +891,17 @@
 		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
 		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
 		break;
+	case NV_ARCH_40:
+		if (!par->FlatPanel)
+			state->control = NV_RD32(par->PRAMDAC0, 0x0580) &
+				0xeffffeff;
+		/* fallthrough */
 	case NV_ARCH_10:
 	case NV_ARCH_20:
 	case NV_ARCH_30:
 	default:
-		if ((par->Chipset & 0xfff0) == 0x0240) {
+		if ((par->Chipset & 0xfff0) == 0x0240 ||
+		    (par->Chipset & 0xfff0) == 0x03d0) {
 			state->arbitration0 = 256;
 			state->arbitration1 = 0x0480;
 		} else if (((par->Chipset & 0xffff) == 0x01A0) ||
@@ -939,7 +944,7 @@
 
 void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 {
-	int i;
+	int i, j;
 
 	NV_WR32(par->PMC, 0x0140, 0x00000000);
 	NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
@@ -951,7 +956,8 @@
 	NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
 
 	if (par->Architecture == NV_ARCH_04) {
-		NV_WR32(par->PFB, 0x0200, state->config);
+		if (state)
+			NV_WR32(par->PFB, 0x0200, state->config);
 	} else if ((par->Architecture < NV_ARCH_40) ||
 		   (par->Chipset & 0xfff0) == 0x0040) {
 		for (i = 0; i < 8; i++) {
@@ -964,8 +970,9 @@
 
 		if (((par->Chipset & 0xfff0) == 0x0090) ||
 		    ((par->Chipset & 0xfff0) == 0x01D0) ||
-		    ((par->Chipset & 0xfff0) == 0x02E0) ||
-		    ((par->Chipset & 0xfff0) == 0x0290))
+		    ((par->Chipset & 0xfff0) == 0x0290) ||
+		    ((par->Chipset & 0xfff0) == 0x0390) ||
+		    ((par->Chipset & 0xfff0) == 0x03D0))
 			regions = 15;
 		for(i = 0; i < regions; i++) {
 			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
@@ -1206,16 +1213,20 @@
 			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
 		} else {
 			if (par->Architecture >= NV_ARCH_40) {
-				u32 tmp;
-
 				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
 				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
 				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
 				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+				NV_WR32(par->PGRAPH, 0x0bc4,
+					NV_RD32(par->PGRAPH, 0x0bc4) |
+					0x00008000);
 
-				tmp = NV_RD32(par->REGS, 0x1540) & 0xff;
-				for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++);
-				NV_WR32(par->PGRAPH, 0x5000, i);
+				j = NV_RD32(par->REGS, 0x1540) & 0xff;
+
+				if (j) {
+					for (i = 0; !(j & 1); j >>= 1, i++);
+					NV_WR32(par->PGRAPH, 0x5000, i);
+				}
 
 				if ((par->Chipset & 0xfff0) == 0x0040) {
 					NV_WR32(par->PGRAPH, 0x09b0,
@@ -1250,6 +1261,7 @@
 				case 0x0160:
 				case 0x01D0:
 				case 0x0240:
+				case 0x03D0:
 					NV_WR32(par->PMC, 0x1700,
 						NV_RD32(par->PFB, 0x020C));
 					NV_WR32(par->PMC, 0x1704, 0);
@@ -1269,7 +1281,6 @@
 						0x00000108);
 					break;
 				case 0x0220:
-				case 0x0230:
 					NV_WR32(par->PGRAPH, 0x0860, 0);
 					NV_WR32(par->PGRAPH, 0x0864, 0);
 					NV_WR32(par->PRAMDAC, 0x0608,
@@ -1277,8 +1288,8 @@
 						0x00100000);
 					break;
 				case 0x0090:
-				case 0x02E0:
 				case 0x0290:
+				case 0x0390:
 					NV_WR32(par->PRAMDAC, 0x0608,
 						NV_RD32(par->PRAMDAC, 0x0608) |
 						0x00100000);
@@ -1355,8 +1366,9 @@
 			} else {
 				if (((par->Chipset & 0xfff0) == 0x0090) ||
 				    ((par->Chipset & 0xfff0) == 0x01D0) ||
-				    ((par->Chipset & 0xfff0) == 0x02E0) ||
-				    ((par->Chipset & 0xfff0) == 0x0290)) {
+				    ((par->Chipset & 0xfff0) == 0x0290) ||
+				    ((par->Chipset & 0xfff0) == 0x0390) ||
+				    ((par->Chipset & 0xfff0) == 0x03D0)) {
 					for (i = 0; i < 60; i++) {
 						NV_WR32(par->PGRAPH,
 							0x0D00 + i*4,
@@ -1407,8 +1419,8 @@
 				} else {
 					if ((par->Chipset & 0xfff0) == 0x0090 ||
 					    (par->Chipset & 0xfff0) == 0x01D0 ||
-					    (par->Chipset & 0xfff0) == 0x02E0 ||
-					    (par->Chipset & 0xfff0) == 0x0290) {
+					    (par->Chipset & 0xfff0) == 0x0290 ||
+					    (par->Chipset & 0xfff0) == 0x0390) {
 						NV_WR32(par->PGRAPH, 0x0DF0,
 							NV_RD32(par->PFB, 0x0200));
 						NV_WR32(par->PGRAPH, 0x0DF4,
@@ -1495,6 +1507,12 @@
 	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
 	NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
 	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
+
+    if (!state) {
+	    par->CurrentState = NULL;
+	    return;
+    }
+
 	if (par->Architecture >= NV_ARCH_10) {
 		if (par->twoHeads) {
 			NV_WR32(par->PCRTC0, 0x0860, state->head);
@@ -1566,6 +1584,9 @@
 	VGA_WR08(par->PCIO, 0x03D5, state->interlace);
 
 	if (!par->FlatPanel) {
+		if (par->Architecture >= NV_ARCH_40)
+			NV_WR32(par->PRAMDAC0, 0x0580, state->control);
+
 		NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
 		NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
 		if (par->twoHeads)
@@ -1631,6 +1652,9 @@
 	state->scale = NV_RD32(par->PRAMDAC, 0x0848);
 	state->config = NV_RD32(par->PFB, 0x0200);
 
+	if (par->Architecture >= NV_ARCH_40 && !par->FlatPanel)
+		state->control  = NV_RD32(par->PRAMDAC0, 0x0580);
+
 	if (par->Architecture >= NV_ARCH_10) {
 		if (par->twoHeads) {
 			state->head = NV_RD32(par->PCRTC0, 0x0860);
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 707e2c8..82579d3 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -166,11 +166,13 @@
 static int NVIsConnected(struct nvidia_par *par, int output)
 {
 	volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
-	u32 reg52C, reg608;
+	u32 reg52C, reg608, dac0_reg608 = 0;
 	int present;
 
-	if (output)
-		PRAMDAC += 0x800;
+	if (output) {
+	    dac0_reg608 = NV_RD32(PRAMDAC, 0x0608);
+	    PRAMDAC += 0x800;
+	}
 
 	reg52C = NV_RD32(PRAMDAC, 0x052C);
 	reg608 = NV_RD32(PRAMDAC, 0x0608);
@@ -194,8 +196,8 @@
 	else
 		printk("nvidiafb: CRTC%i analog not found\n", output);
 
-	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
-		0x0000EFFF);
+	if (output)
+	    NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608);
 
 	NV_WR32(PRAMDAC, 0x052C, reg52C);
 	NV_WR32(PRAMDAC, 0x0608, reg608);
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
index 38f7cc0..2fdf77e 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/nvidia/nv_type.h
@@ -86,6 +86,7 @@
 	u32 timingV;
 	u32 displayV;
 	u32 crtcSync;
+	u32 control;
 } RIVA_HW_STATE;
 
 struct riva_regs {
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 41f6365..a7fe214 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -674,6 +674,7 @@
 		info->fbops->fb_sync = nvidiafb_sync;
 		info->pixmap.scan_align = 4;
 		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		info->flags |= FBINFO_READS_FAST;
 		NVResetGraphics(info);
 	} else {
 		info->fbops->fb_imageblit = cfb_imageblit;
@@ -682,6 +683,7 @@
 		info->fbops->fb_sync = NULL;
 		info->pixmap.scan_align = 1;
 		info->flags |= FBINFO_HWACCEL_DISABLED;
+		info->flags &= ~FBINFO_READS_FAST;
 	}
 
 	par->cursor_reset = 1;
@@ -1193,7 +1195,8 @@
 
 	printk(KERN_INFO PFX "Device ID: %x \n", id);
 
-	if ((id & 0xfff0) == 0x00f0) {
+	if ((id & 0xfff0) == 0x00f0 ||
+	    (id & 0xfff0) == 0x02e0) {
 		/* pci-e */
 		id = NV_RD32(par->REGS, 0x1800);
 
@@ -1238,18 +1241,16 @@
 	case 0x0040:		/* GeForce 6800 */
 	case 0x00C0:		/* GeForce 6800 */
 	case 0x0120:		/* GeForce 6800 */
-	case 0x0130:
 	case 0x0140:		/* GeForce 6600 */
 	case 0x0160:		/* GeForce 6200 */
 	case 0x01D0:		/* GeForce 7200, 7300, 7400 */
-	case 0x02E0:		/* GeForce 7300 GT */
 	case 0x0090:		/* GeForce 7800 */
 	case 0x0210:		/* GeForce 6800 */
 	case 0x0220:		/* GeForce 6200 */
-	case 0x0230:
 	case 0x0240:		/* GeForce 6100 */
 	case 0x0290:		/* GeForce 7900 */
 	case 0x0390:		/* GeForce 7600 */
+	case 0x03D0:
 		arch = NV_ARCH_40;
 		break;
 	case 0x0020:		/* TNT, TNT2 */
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 885b428..452433d 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -271,7 +271,7 @@
 		return;
 	}
 
-	size = sizeof(struct fb_info) + sizeof(u32) * 17;
+	size = sizeof(struct fb_info) + sizeof(u32) * 16;
 
 	info = kmalloc(size, GFP_ATOMIC);
 	
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
new file mode 100644
index 0000000..7f4d25b
--- /dev/null
+++ b/drivers/video/omap/Kconfig
@@ -0,0 +1,58 @@
+config FB_OMAP
+	tristate "OMAP frame buffer support (EXPERIMENTAL)"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+          Frame buffer driver for OMAP based boards.
+
+config FB_OMAP_BOOTLOADER_INIT
+	bool "Check bootloader initializaion"
+	depends on FB_OMAP
+	help
+	  Say Y here if you want to enable checking if the bootloader has
+	  already initialized the display controller. In this case the
+	  driver will skip the initialization.
+
+config FB_OMAP_CONSISTENT_DMA_SIZE
+	int "Consistent DMA memory size (MB)"
+	depends on FB_OMAP
+	range 1 14
+	default 2
+	help
+	  Increase the DMA consistent memory size according to your video
+	  memory needs, for example if you want to use multiple planes.
+	  The size must be 2MB aligned.
+	  If unsure say 1.
+
+config FB_OMAP_DMA_TUNE
+        bool "Set DMA SDRAM access priority high"
+        depends on FB_OMAP && ARCH_OMAP1
+        help
+          On systems in which video memory is in system memory
+          (SDRAM) this will speed up graphics DMA operations.
+          If you have such a system and want to use rotation
+          answer yes. Answer no if you have a dedicated video
+          memory, or don't use any of the accelerated features.
+
+config FB_OMAP_LCDC_EXTERNAL
+	bool "External LCD controller support"
+	depends on FB_OMAP
+	help
+	  Say Y here, if you want to have support for boards with an
+	  external LCD controller connected to the SoSSI/RFBI interface.
+
+config FB_OMAP_LCDC_HWA742
+	bool "Epson HWA742 LCD controller support"
+	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+	help
+	  Say Y here if you want to have support for the external
+	  Epson HWA742 LCD controller.
+
+config FB_OMAP_LCDC_BLIZZARD
+	bool "Epson Blizzard LCD controller support"
+	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+	help
+	  Say Y here if you want to have support for the external
+	  Epson Blizzard LCD controller.
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
new file mode 100644
index 0000000..99da8b6
--- /dev/null
+++ b/drivers/video/omap/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile for the new OMAP framebuffer device driver
+#
+
+obj-$(CONFIG_FB_OMAP) += omapfb.o
+
+objs-yy := omapfb_main.o
+
+objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o
+objs-y$(CONFIG_ARCH_OMAP2) += dispc.o
+
+objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
+objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
+
+objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
+objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
+
+objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
+objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
+objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
+objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
+objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
+objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
+objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o
+
+omapfb-objs := $(objs-yy)
+
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
new file mode 100644
index 0000000..e682940
--- /dev/null
+++ b/drivers/video/omap/blizzard.c
@@ -0,0 +1,1568 @@
+/*
+ * Epson Blizzard LCD controller driver
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Authors:     Juha Yrjola   <juha.yrjola@nokia.com>
+ *	        Imre Deak     <imre.deak@nokia.com>
+ * YUV support: Jussi Laako   <jussi.laako@nokia.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.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/blizzard.h>
+
+#include "dispc.h"
+
+#define MODULE_NAME				"blizzard"
+
+#define BLIZZARD_REV_CODE			0x00
+#define BLIZZARD_CONFIG				0x02
+#define BLIZZARD_PLL_DIV			0x04
+#define BLIZZARD_PLL_LOCK_RANGE			0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0		0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1		0x0a
+#define BLIZZARD_PLL_MODE			0x0c
+#define BLIZZARD_CLK_SRC			0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE		0x10
+#define BLIZZARD_MEM_BANK0_STATUS		0x14
+#define BLIZZARD_HDISP				0x2a
+#define BLIZZARD_HNDP				0x2c
+#define BLIZZARD_VDISP0				0x2e
+#define BLIZZARD_VDISP1				0x30
+#define BLIZZARD_VNDP				0x32
+#define BLIZZARD_HSW				0x34
+#define BLIZZARD_VSW				0x38
+#define BLIZZARD_DISPLAY_MODE			0x68
+#define BLIZZARD_INPUT_WIN_X_START_0		0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT		0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT		0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0		0x92
+#define BLIZZARD_POWER_SAVE			0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS		0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND	0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE	0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE	0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY		0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD			0x00
+#define BLIZZARD_SRC_BLT_LCD			0x06
+
+#define BLIZZARD_COLOR_RGB565			0x01
+#define BLIZZARD_COLOR_YUV420			0x09
+
+#define BLIZZARD_VERSION_S1D13745		0x01	/* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744		0x02	/* Blizzard */
+
+#define BLIZZARD_AUTO_UPDATE_TIME		(HZ / 20)
+
+/* Reserve 4 request slots for requests in irq context */
+#define REQ_POOL_SIZE			24
+#define IRQ_REQ_POOL_SIZE		4
+
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE	0
+#define REQ_PENDING	1
+
+struct blizzard_reg_list {
+	int	start;
+	int	end;
+};
+
+/* These need to be saved / restored separately from the rest. */
+static struct blizzard_reg_list blizzard_pll_regs[] = {
+	{
+		.start	= 0x04,		/* Don't save PLL ctrl (0x0C) */
+		.end	= 0x0a,
+	},
+	{
+		.start	= 0x0e,		/* Clock configuration */
+		.end	= 0x0e,
+	},
+};
+
+static struct blizzard_reg_list blizzard_gen_regs[] = {
+	{
+		.start	= 0x18,		/* SDRAM control */
+		.end	= 0x20,
+	},
+	{
+		.start	= 0x28,		/* LCD Panel configuration */
+		.end	= 0x5a,		/* HSSI interface, TV configuration */
+	},
+};
+
+static u8 blizzard_reg_cache[0x5a / 2];
+
+struct update_param {
+	int	plane;
+	int	x, y, width, height;
+	int	out_x, out_y;
+	int	out_width, out_height;
+	int	color_mode;
+	int	bpp;
+	int	flags;
+};
+
+struct blizzard_request {
+	struct list_head entry;
+	unsigned int	 flags;
+
+	int		 (*handler)(struct blizzard_request *req);
+	void		 (*complete)(void *data);
+	void		 *complete_data;
+
+	union {
+		struct update_param	update;
+		struct completion	*sync;
+	} par;
+};
+
+struct plane_info {
+	unsigned long offset;
+	int pos_x, pos_y;
+	int width, height;
+	int out_width, out_height;
+	int scr_width;
+	int color_mode;
+	int bpp;
+};
+
+struct blizzard_struct {
+	enum omapfb_update_mode	update_mode;
+	enum omapfb_update_mode	update_mode_before_suspend;
+
+	struct timer_list	auto_update_timer;
+	int			stop_auto_update;
+	struct omapfb_update_window	auto_update_window;
+	int			enabled_planes;
+	int			vid_nonstd_color;
+	int			vid_scaled;
+	int			last_color_mode;
+	int			zoom_on;
+	int			screen_width;
+	int			screen_height;
+	unsigned		te_connected:1;
+	unsigned		vsync_only:1;
+
+	struct plane_info	plane[OMAPFB_PLANE_NUM];
+
+	struct blizzard_request	req_pool[REQ_POOL_SIZE];
+	struct list_head	pending_req_list;
+	struct list_head	free_req_list;
+	struct semaphore	req_sema;
+	spinlock_t		req_lock;
+
+	unsigned long		sys_ck_rate;
+	struct extif_timings	reg_timings, lut_timings;
+
+	u32			max_transmit_size;
+	u32			extif_clk_period;
+	int			extif_clk_div;
+	unsigned long		pix_tx_time;
+	unsigned long		line_upd_time;
+
+	struct omapfb_device	*fbdev;
+	struct lcd_ctrl_extif	*extif;
+	struct lcd_ctrl		*int_ctrl;
+
+	void			(*power_up)(struct device *dev);
+	void			(*power_down)(struct device *dev);
+
+	int			version;
+} blizzard;
+
+struct lcd_ctrl blizzard_ctrl;
+
+static u8 blizzard_read_reg(u8 reg)
+{
+	u8 data;
+
+	blizzard.extif->set_bits_per_cycle(8);
+	blizzard.extif->write_command(&reg, 1);
+	blizzard.extif->read_data(&data, 1);
+
+	return data;
+}
+
+static void blizzard_write_reg(u8 reg, u8 val)
+{
+	blizzard.extif->set_bits_per_cycle(8);
+	blizzard.extif->write_command(&reg, 1);
+	blizzard.extif->write_data(&val, 1);
+}
+
+static void blizzard_restart_sdram(void)
+{
+	unsigned long tmo;
+
+	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
+	udelay(50);
+	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1);
+	tmo = jiffies + msecs_to_jiffies(200);
+	while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {
+		if (time_after(jiffies, tmo)) {
+			dev_err(blizzard.fbdev->dev,
+					"s1d1374x: SDRAM not ready");
+			break;
+		}
+		msleep(1);
+	}
+}
+
+static void blizzard_stop_sdram(void)
+{
+	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
+}
+
+/* Wait until the last window was completely written into the controllers
+ * SDRAM and we can start transferring the next window.
+ */
+static void blizzard_wait_line_buffer(void)
+{
+	unsigned long tmo = jiffies + msecs_to_jiffies(30);
+
+	while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) {
+		if (time_after(jiffies, tmo)) {
+			if (printk_ratelimit())
+				dev_err(blizzard.fbdev->dev,
+					"s1d1374x: line buffer not ready\n");
+			break;
+		}
+	}
+}
+
+/* Wait until the YYC color space converter is idle. */
+static void blizzard_wait_yyc(void)
+{
+	unsigned long tmo = jiffies + msecs_to_jiffies(30);
+
+	while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) {
+		if (time_after(jiffies, tmo)) {
+			if (printk_ratelimit())
+				dev_err(blizzard.fbdev->dev,
+					"s1d1374x: YYC not ready\n");
+			break;
+		}
+	}
+}
+
+static void disable_overlay(void)
+{
+	blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT,
+				BLIZZARD_SRC_DISABLE_OVERLAY);
+}
+
+static void set_window_regs(int x_start, int y_start, int x_end, int y_end,
+			    int x_out_start, int y_out_start,
+			    int x_out_end, int y_out_end, int color_mode,
+			    int zoom_off, int flags)
+{
+	u8 tmp[18];
+	u8 cmd;
+
+	x_end--;
+	y_end--;
+	tmp[0] = x_start;
+	tmp[1] = x_start >> 8;
+	tmp[2] = y_start;
+	tmp[3] = y_start >> 8;
+	tmp[4] = x_end;
+	tmp[5] = x_end >> 8;
+	tmp[6] = y_end;
+	tmp[7] = y_end >> 8;
+
+	x_out_end--;
+	y_out_end--;
+	tmp[8]  = x_out_start;
+	tmp[9]  = x_out_start >> 8;
+	tmp[10] = y_out_start;
+	tmp[11] = y_out_start >> 8;
+	tmp[12] = x_out_end;
+	tmp[13] = x_out_end >> 8;
+	tmp[14] = y_out_end;
+	tmp[15] = y_out_end >> 8;
+
+	tmp[16] = color_mode;
+	if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745)
+		tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+	else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY)
+		tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE;
+	else
+		tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
+				BLIZZARD_SRC_WRITE_LCD :
+				BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+	blizzard.extif->set_bits_per_cycle(8);
+	cmd = BLIZZARD_INPUT_WIN_X_START_0;
+	blizzard.extif->write_command(&cmd, 1);
+	blizzard.extif->write_data(tmp, 18);
+}
+
+static void enable_tearsync(int y, int width, int height, int screen_height,
+			    int out_height, int force_vsync)
+{
+	u8 b;
+
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+	b |= 1 << 3;
+	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+
+	if (likely(blizzard.vsync_only || force_vsync)) {
+		blizzard.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if (width * blizzard.pix_tx_time < blizzard.line_upd_time) {
+		blizzard.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if ((width * blizzard.pix_tx_time / 1000) * height <
+	    (y + out_height) * (blizzard.line_upd_time / 1000)) {
+		blizzard.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	blizzard.extif->enable_tearsync(1, y + 1);
+}
+
+static void disable_tearsync(void)
+{
+	u8 b;
+
+	blizzard.extif->enable_tearsync(0, 0);
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+	b &= ~(1 << 3);
+	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+}
+
+static inline void set_extif_timings(const struct extif_timings *t);
+
+static inline struct blizzard_request *alloc_req(void)
+{
+	unsigned long flags;
+	struct blizzard_request *req;
+	int req_flags = 0;
+
+	if (!in_interrupt())
+		down(&blizzard.req_sema);
+	else
+		req_flags = REQ_FROM_IRQ_POOL;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+	BUG_ON(list_empty(&blizzard.free_req_list));
+	req = list_entry(blizzard.free_req_list.next,
+			 struct blizzard_request, entry);
+	list_del(&req->entry);
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+	INIT_LIST_HEAD(&req->entry);
+	req->flags = req_flags;
+
+	return req;
+}
+
+static inline void free_req(struct blizzard_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+
+	list_del(&req->entry);
+	list_add(&req->entry, &blizzard.free_req_list);
+	if (!(req->flags & REQ_FROM_IRQ_POOL))
+		up(&blizzard.req_sema);
+
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+}
+
+static void process_pending_requests(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+
+	while (!list_empty(&blizzard.pending_req_list)) {
+		struct blizzard_request *req;
+		void (*complete)(void *);
+		void *complete_data;
+
+		req = list_entry(blizzard.pending_req_list.next,
+				 struct blizzard_request, entry);
+		spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+		if (req->handler(req) == REQ_PENDING)
+			return;
+
+		complete = req->complete;
+		complete_data = req->complete_data;
+		free_req(req);
+
+		if (complete)
+			complete(complete_data);
+
+		spin_lock_irqsave(&blizzard.req_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+}
+
+static void submit_req_list(struct list_head *head)
+{
+	unsigned long flags;
+	int process = 1;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+	if (likely(!list_empty(&blizzard.pending_req_list)))
+		process = 0;
+	list_splice_init(head, blizzard.pending_req_list.prev);
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+	if (process)
+		process_pending_requests();
+}
+
+static void request_complete(void *data)
+{
+	struct blizzard_request	*req = (struct blizzard_request *)data;
+	void			(*complete)(void *);
+	void			*complete_data;
+
+	complete = req->complete;
+	complete_data = req->complete_data;
+
+	free_req(req);
+
+	if (complete)
+		complete(complete_data);
+
+	process_pending_requests();
+}
+
+
+static int do_full_screen_update(struct blizzard_request *req)
+{
+	int i;
+	int flags;
+
+	for (i = 0; i < 3; i++) {
+		struct plane_info *p = &blizzard.plane[i];
+		if (!(blizzard.enabled_planes & (1 << i))) {
+			blizzard.int_ctrl->enable_plane(i, 0);
+			continue;
+		}
+		dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n",
+			p->width, p->height);
+		blizzard.int_ctrl->setup_plane(i,
+				OMAPFB_CHANNEL_OUT_LCD, p->offset,
+				p->scr_width, p->pos_x, p->pos_y,
+				p->width, p->height,
+				p->color_mode);
+		blizzard.int_ctrl->enable_plane(i, 1);
+	}
+
+	dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n",
+		blizzard.screen_width, blizzard.screen_height);
+	blizzard_wait_line_buffer();
+	flags = req->par.update.flags;
+	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+		enable_tearsync(0, blizzard.screen_width,
+				blizzard.screen_height,
+				blizzard.screen_height,
+				blizzard.screen_height,
+				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+	else
+		disable_tearsync();
+
+	set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height,
+			0, 0, blizzard.screen_width, blizzard.screen_height,
+			BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags);
+	blizzard.zoom_on = 0;
+
+	blizzard.extif->set_bits_per_cycle(16);
+	/* set_window_regs has left the register index at the right
+	 * place, so no need to set it here.
+	 */
+	blizzard.extif->transfer_area(blizzard.screen_width,
+				      blizzard.screen_height,
+				      request_complete, req);
+	return REQ_PENDING;
+}
+
+/* Setup all planes with an overlapping area with the update window. */
+static int do_partial_update(struct blizzard_request *req, int plane,
+			     int x, int y, int w, int h,
+			     int x_out, int y_out, int w_out, int h_out,
+			     int wnd_color_mode, int bpp)
+{
+	int i;
+	int gx1, gy1, gx2, gy2;
+	int gx1_out, gy1_out, gx2_out, gy2_out;
+	int color_mode;
+	int flags;
+	int zoom_off;
+
+	/* Global coordinates, relative to pixel 0,0 of the LCD */
+	gx1 = x + blizzard.plane[plane].pos_x;
+	gy1 = y + blizzard.plane[plane].pos_y;
+	gx2 = gx1 + w;
+	gy2 = gy1 + h;
+
+	flags = req->par.update.flags;
+	if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
+		gx1_out = gx1;
+		gy1_out = gy1;
+		gx2_out = gx1 + w * 2;
+		gy2_out = gy1 + h * 2;
+	} else {
+		gx1_out = x_out + blizzard.plane[plane].pos_x;
+		gy1_out = y_out + blizzard.plane[plane].pos_y;
+		gx2_out = gx1_out + w_out;
+		gy2_out = gy1_out + h_out;
+	}
+	zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 &&
+		w == blizzard.screen_width && h == blizzard.screen_height;
+	blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) ||
+			   (w < w_out || h < h_out);
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
+		struct plane_info *p = &blizzard.plane[i];
+		int px1, py1;
+		int px2, py2;
+		int pw, ph;
+		int pposx, pposy;
+		unsigned long offset;
+
+		if (!(blizzard.enabled_planes & (1 << i))  ||
+		    (wnd_color_mode && i != plane)) {
+			blizzard.int_ctrl->enable_plane(i, 0);
+			continue;
+		}
+		/* Plane coordinates */
+		if (i == plane) {
+			/* Plane in which we are doing the update.
+			 * Local coordinates are the one in the update
+			 * request.
+			 */
+			px1 = x;
+			py1 = y;
+			px2 = x + w;
+			py2 = y + h;
+			pposx = 0;
+			pposy = 0;
+		} else {
+			/* Check if this plane has an overlapping part */
+			px1 = gx1 - p->pos_x;
+			py1 = gy1 - p->pos_y;
+			px2 = gx2 - p->pos_x;
+			py2 = gy2 - p->pos_y;
+			if (px1 >= p->width || py1 >= p->height ||
+			    px2 <= 0 || py2 <= 0) {
+				blizzard.int_ctrl->enable_plane(i, 0);
+				continue;
+			}
+			/* Calculate the coordinates for the overlapping
+			 * part in the plane's local coordinates.
+			 */
+			pposx = -px1;
+			pposy = -py1;
+			if (px1 < 0)
+				px1 = 0;
+			if (py1 < 0)
+				py1 = 0;
+			if (px2 > p->width)
+				px2 = p->width;
+			if (py2 > p->height)
+				py2 = p->height;
+			if (pposx < 0)
+				pposx = 0;
+			if (pposy < 0)
+				pposy = 0;
+		}
+		pw = px2 - px1;
+		ph = py2 - py1;
+		offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8;
+		if (wnd_color_mode)
+			/* Window embedded in the plane with a differing
+			 * color mode / bpp. Calculate the number of DMA
+			 * transfer elements in terms of the plane's bpp.
+			 */
+			pw = (pw + 1) * bpp / p->bpp;
+#ifdef VERBOSE
+		dev_dbg(blizzard.fbdev->dev,
+			"plane %d offset %#08lx pposx %d pposy %d "
+			"px1 %d py1 %d pw %d ph %d\n",
+			i, offset, pposx, pposy, px1, py1, pw, ph);
+#endif
+		blizzard.int_ctrl->setup_plane(i,
+				OMAPFB_CHANNEL_OUT_LCD, offset,
+				p->scr_width,
+				pposx, pposy, pw, ph,
+				p->color_mode);
+
+		blizzard.int_ctrl->enable_plane(i, 1);
+	}
+
+	switch (wnd_color_mode) {
+	case OMAPFB_COLOR_YUV420:
+		color_mode = BLIZZARD_COLOR_YUV420;
+		/* Currently only the 16 bits/pixel cycle format is
+		 * supported on the external interface. Adjust the number
+		 * of transfer elements per line for 12bpp format.
+		 */
+		w = (w + 1) * 3 / 4;
+		break;
+	default:
+		color_mode = BLIZZARD_COLOR_RGB565;
+		break;
+	}
+
+	blizzard_wait_line_buffer();
+	if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420)
+		blizzard_wait_yyc();
+	blizzard.last_color_mode = color_mode;
+	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+		enable_tearsync(gy1, w, h,
+				blizzard.screen_height,
+				h_out,
+				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+	else
+		disable_tearsync();
+
+	set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
+			color_mode, zoom_off, flags);
+
+	blizzard.extif->set_bits_per_cycle(16);
+	/* set_window_regs has left the register index at the right
+	 * place, so no need to set it here.
+	 */
+	blizzard.extif->transfer_area(w, h, request_complete, req);
+
+	return REQ_PENDING;
+}
+
+static int send_frame_handler(struct blizzard_request *req)
+{
+	struct update_param *par = &req->par.update;
+	int plane = par->plane;
+
+#ifdef VERBOSE
+	dev_dbg(blizzard.fbdev->dev,
+		"send_frame: x %d y %d w %d h %d "
+		"x_out %d y_out %d w_out %d h_out %d "
+		"color_mode %04x flags %04x planes %01x\n",
+		par->x, par->y, par->width, par->height,
+		par->out_x, par->out_y, par->out_width, par->out_height,
+		par->color_mode, par->flags, blizzard.enabled_planes);
+#endif
+	if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY)
+		disable_overlay();
+
+	if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) ||
+	     (blizzard.enabled_planes & blizzard.vid_scaled))
+		return do_full_screen_update(req);
+
+	return do_partial_update(req, plane, par->x, par->y,
+				 par->width, par->height,
+				 par->out_x, par->out_y,
+				 par->out_width, par->out_height,
+				 par->color_mode, par->bpp);
+}
+
+static void send_frame_complete(void *data)
+{
+}
+
+#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do {	\
+	req = alloc_req();			\
+	req->handler	= send_frame_handler;	\
+	req->complete	= send_frame_complete;	\
+	req->par.update.plane = plane_idx;	\
+	req->par.update.x = _x;			\
+	req->par.update.y = _y;			\
+	req->par.update.width  = _w;		\
+	req->par.update.height = _h;		\
+	req->par.update.out_x = _x_out;		\
+	req->par.update.out_y = _y_out;		\
+	req->par.update.out_width = _w_out;	\
+	req->par.update.out_height = _h_out;	\
+	req->par.update.bpp = bpp;		\
+	req->par.update.color_mode = color_mode;\
+	req->par.update.flags	  = flags;	\
+	list_add_tail(&req->entry, req_head);	\
+} while(0)
+
+static void create_req_list(int plane_idx,
+			    struct omapfb_update_window *win,
+			    struct list_head *req_head)
+{
+	struct blizzard_request *req;
+	int x = win->x;
+	int y = win->y;
+	int width = win->width;
+	int height = win->height;
+	int x_out = win->out_x;
+	int y_out = win->out_y;
+	int width_out = win->out_width;
+	int height_out = win->out_height;
+	int color_mode;
+	int bpp;
+	int flags;
+	unsigned int ystart = y;
+	unsigned int yspan = height;
+	unsigned int ystart_out = y_out;
+	unsigned int yspan_out = height_out;
+
+	flags = win->format & ~OMAPFB_FORMAT_MASK;
+	color_mode = win->format & OMAPFB_FORMAT_MASK;
+	switch (color_mode) {
+	case OMAPFB_COLOR_YUV420:
+		/* Embedded window with different color mode */
+		bpp = 12;
+		/* X, Y, height must be aligned at 2, width at 4 pixels */
+		x &= ~1;
+		y &= ~1;
+		height = yspan = height & ~1;
+		width = width & ~3;
+		break;
+	default:
+		/* Same as the plane color mode */
+		bpp = blizzard.plane[plane_idx].bpp;
+		break;
+	}
+	if (width * height * bpp / 8 > blizzard.max_transmit_size) {
+		yspan = blizzard.max_transmit_size / (width * bpp / 8);
+		yspan_out = yspan * height_out / height;
+		ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
+			 width_out, yspan_out);
+		ystart += yspan;
+		ystart_out += yspan_out;
+		yspan = height - yspan;
+		yspan_out = height_out - yspan_out;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+
+	ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
+		 width_out, yspan_out);
+}
+
+static void auto_update_complete(void *data)
+{
+	if (!blizzard.stop_auto_update)
+		mod_timer(&blizzard.auto_update_timer,
+			  jiffies + BLIZZARD_AUTO_UPDATE_TIME);
+}
+
+static void blizzard_update_window_auto(unsigned long arg)
+{
+	LIST_HEAD(req_list);
+	struct blizzard_request *last;
+	struct omapfb_plane_struct *plane;
+
+	plane = blizzard.fbdev->fb_info[0]->par;
+	create_req_list(plane->idx,
+			&blizzard.auto_update_window, &req_list);
+	last = list_entry(req_list.prev, struct blizzard_request, entry);
+
+	last->complete = auto_update_complete;
+	last->complete_data = NULL;
+
+	submit_req_list(&req_list);
+}
+
+int blizzard_update_window_async(struct fb_info *fbi,
+				 struct omapfb_update_window *win,
+				 void (*complete_callback)(void *arg),
+				 void *complete_callback_data)
+{
+	LIST_HEAD(req_list);
+	struct blizzard_request *last;
+	struct omapfb_plane_struct *plane = fbi->par;
+
+	if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE))
+		return -EINVAL;
+	if (unlikely(!blizzard.te_connected &&
+		     (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC)))
+		return -EINVAL;
+
+	create_req_list(plane->idx, win, &req_list);
+	last = list_entry(req_list.prev, struct blizzard_request, entry);
+
+	last->complete = complete_callback;
+	last->complete_data = (void *)complete_callback_data;
+
+	submit_req_list(&req_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(blizzard_update_window_async);
+
+static int update_full_screen(void)
+{
+	return blizzard_update_window_async(blizzard.fbdev->fb_info[0],
+				     &blizzard.auto_update_window, NULL, NULL);
+
+}
+
+static int blizzard_setup_plane(int plane, int channel_out,
+				  unsigned long offset, int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	struct plane_info *p;
+
+#ifdef VERBOSE
+	dev_dbg(blizzard.fbdev->dev,
+		    "plane %d ch_out %d offset %#08lx scr_width %d "
+		    "pos_x %d pos_y %d width %d height %d color_mode %d\n",
+		    plane, channel_out, offset, screen_width,
+		    pos_x, pos_y, width, height, color_mode);
+#endif
+	if ((unsigned)plane > OMAPFB_PLANE_NUM)
+		return -EINVAL;
+	p = &blizzard.plane[plane];
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUY422:
+		p->bpp = 16;
+		blizzard.vid_nonstd_color &= ~(1 << plane);
+		break;
+	case OMAPFB_COLOR_YUV420:
+		p->bpp = 12;
+		blizzard.vid_nonstd_color |= 1 << plane;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		p->bpp = 16;
+		blizzard.vid_nonstd_color &= ~(1 << plane);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	p->offset = offset;
+	p->pos_x = pos_x;
+	p->pos_y = pos_y;
+	p->width = width;
+	p->height = height;
+	p->scr_width = screen_width;
+	if (!p->out_width)
+		p->out_width = width;
+	if (!p->out_height)
+		p->out_height = height;
+
+	p->color_mode = color_mode;
+
+	return 0;
+}
+
+static int blizzard_set_scale(int plane, int orig_w, int orig_h,
+			      int out_w, int out_h)
+{
+	struct plane_info *p = &blizzard.plane[plane];
+	int r;
+
+	dev_dbg(blizzard.fbdev->dev,
+		"plane %d orig_w %d orig_h %d out_w %d out_h %d\n",
+		plane, orig_w, orig_h, out_w, out_h);
+	if ((unsigned)plane > OMAPFB_PLANE_NUM)
+		return -ENODEV;
+
+	r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h);
+	if (r < 0)
+		return r;
+
+	p->width = orig_w;
+	p->height = orig_h;
+	p->out_width = out_w;
+	p->out_height = out_h;
+	if (orig_w == out_w && orig_h == out_h)
+		blizzard.vid_scaled &= ~(1 << plane);
+	else
+		blizzard.vid_scaled |= 1 << plane;
+
+	return 0;
+}
+
+static int blizzard_enable_plane(int plane, int enable)
+{
+	if (enable)
+		blizzard.enabled_planes |= 1 << plane;
+	else
+		blizzard.enabled_planes &= ~(1 << plane);
+
+	return 0;
+}
+
+static int sync_handler(struct blizzard_request *req)
+{
+	complete(req->par.sync);
+	return REQ_COMPLETE;
+}
+
+static void blizzard_sync(void)
+{
+	LIST_HEAD(req_list);
+	struct blizzard_request *req;
+	struct completion comp;
+
+	req = alloc_req();
+
+	req->handler = sync_handler;
+	req->complete = NULL;
+	init_completion(&comp);
+	req->par.sync = &comp;
+
+	list_add(&req->entry, &req_list);
+	submit_req_list(&req_list);
+
+	wait_for_completion(&comp);
+}
+
+
+static void blizzard_bind_client(struct omapfb_notifier_block *nb)
+{
+	if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) {
+		omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
+	}
+}
+
+static int blizzard_set_update_mode(enum omapfb_update_mode mode)
+{
+	if (unlikely(mode != OMAPFB_MANUAL_UPDATE &&
+		     mode != OMAPFB_AUTO_UPDATE &&
+		     mode != OMAPFB_UPDATE_DISABLED))
+		return -EINVAL;
+
+	if (mode == blizzard.update_mode)
+		return 0;
+
+	dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n",
+			mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
+			(mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
+
+	switch (blizzard.update_mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		blizzard.stop_auto_update = 1;
+		del_timer_sync(&blizzard.auto_update_timer);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	blizzard.update_mode = mode;
+	blizzard_sync();
+	blizzard.stop_auto_update = 0;
+
+	switch (mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		blizzard_update_window_auto(0);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	return 0;
+}
+
+static enum omapfb_update_mode blizzard_get_update_mode(void)
+{
+	return blizzard.update_mode;
+}
+
+static inline void set_extif_timings(const struct extif_timings *t)
+{
+	blizzard.extif->set_timings(t);
+}
+
+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+	int bus_tick = blizzard.extif_clk_period * div;
+	return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 12.2 ns (regs),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 12 ns (regs),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 2*SYSCLK  (regs),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns */
+
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(blizzard.fbdev->dev,
+		  "Blizzard systim %lu ps extif_clk_period %u div %d\n",
+		  systim, blizzard.extif_clk_period, div);
+
+	t = &blizzard.reg_timings;
+	memset(t, 0, sizeof(*t));
+
+	t->clk_div = div;
+
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return blizzard.extif->convert_timings(t);
+}
+
+static int calc_lut_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns */
+
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(blizzard.fbdev->dev,
+		"Blizzard systim %lu ps extif_clk_period %u div %d\n",
+		systim, blizzard.extif_clk_period, div);
+
+	t = &blizzard.lut_timings;
+	memset(t, 0, sizeof(*t));
+
+	t->clk_div = div;
+
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(blizzard.fbdev->dev,
+		 "[lut]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(blizzard.fbdev->dev,
+		 "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return blizzard.extif->convert_timings(t);
+}
+
+static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
+{
+	int max_clk_div;
+	int div;
+
+	blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div);
+	for (div = 1; div <= max_clk_div; div++) {
+		if (calc_reg_timing(sysclk, div) == 0)
+			break;
+	}
+	if (div > max_clk_div) {
+		dev_dbg(blizzard.fbdev->dev, "reg timing failed\n");
+		goto err;
+	}
+	*extif_mem_div = div;
+
+	for (div = 1; div <= max_clk_div; div++) {
+		if (calc_lut_timing(sysclk, div) == 0)
+			break;
+	}
+
+	if (div > max_clk_div)
+		goto err;
+
+	blizzard.extif_clk_div = div;
+
+	return 0;
+err:
+	dev_err(blizzard.fbdev->dev, "can't setup timings\n");
+	return -1;
+}
+
+static void calc_blizzard_clk_rates(unsigned long ext_clk,
+				unsigned long *sys_clk, unsigned long *pix_clk)
+{
+	int pix_clk_src;
+	int sys_div = 0, sys_mul = 0;
+	int pix_div;
+
+	pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC);
+	pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
+	if ((pix_clk_src & (0x3 << 1)) == 0) {
+		/* Source is the PLL */
+		sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1;
+		sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0);
+		sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1)
+				& 0x0f)	<< 11);
+		*sys_clk = ext_clk * sys_mul / sys_div;
+	} else	/* else source is ext clk, or oscillator */
+		*sys_clk = ext_clk;
+
+	*pix_clk = *sys_clk / pix_div;			/* HZ */
+	dev_dbg(blizzard.fbdev->dev,
+		"ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
+		ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
+	dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
+		*sys_clk, *pix_clk);
+}
+
+static int setup_tearsync(unsigned long pix_clk, int extif_div)
+{
+	int hdisp, vdisp;
+	int hndp, vndp;
+	int hsw, vsw;
+	int hs, vs;
+	int hs_pol_inv, vs_pol_inv;
+	int use_hsvs, use_ndp;
+	u8  b;
+
+	hsw = blizzard_read_reg(BLIZZARD_HSW);
+	vsw = blizzard_read_reg(BLIZZARD_VSW);
+	hs_pol_inv = !(hsw & 0x80);
+	vs_pol_inv = !(vsw & 0x80);
+	hsw = hsw & 0x7f;
+	vsw = vsw & 0x3f;
+
+	hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8;
+	vdisp = blizzard_read_reg(BLIZZARD_VDISP0) +
+		((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8);
+
+	hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f;
+	vndp = blizzard_read_reg(BLIZZARD_VNDP);
+
+	/* time to transfer one pixel (16bpp) in ps */
+	blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time;
+	if (blizzard.extif->get_max_tx_rate != NULL) {
+		/* The external interface might have a rate limitation,
+		 * if so, we have to maximize our transfer rate.
+		 */
+		unsigned long min_tx_time;
+		unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate();
+
+		dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n",
+			max_tx_rate);
+		min_tx_time = 1000000000 / (max_tx_rate / 1000);  /* ps */
+		if (blizzard.pix_tx_time < min_tx_time)
+			blizzard.pix_tx_time = min_tx_time;
+	}
+
+	/* time to update one line in ps */
+	blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
+	blizzard.line_upd_time *= 1000;
+	if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time)
+		/* transfer speed too low, we might have to use both
+		 * HS and VS */
+		use_hsvs = 1;
+	else
+		/* decent transfer speed, we'll always use only VS */
+		use_hsvs = 0;
+
+	if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
+		/* HS or'ed with VS doesn't work, use the active high
+		 * TE signal based on HNDP / VNDP */
+		use_ndp = 1;
+		hs_pol_inv = 0;
+		vs_pol_inv = 0;
+		hs = hndp;
+		vs = vndp;
+	} else {
+		/* Use HS or'ed with VS as a TE signal if both are needed
+		 * or VNDP if only vsync is needed. */
+		use_ndp = 0;
+		hs = hsw;
+		vs = vsw;
+		if (!use_hsvs) {
+			hs_pol_inv = 0;
+			vs_pol_inv = 0;
+		}
+	}
+
+	hs = hs * 1000000 / (pix_clk / 1000);		  /* ps */
+	hs *= 1000;
+
+	vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
+	vs *= 1000;
+
+	if (vs <= hs)
+		return -EDOM;
+	/* set VS to 120% of HS to minimize VS detection time */
+	vs = hs * 12 / 10;
+	/* minimize HS too */
+	if (hs > 10000)
+		hs = 10000;
+
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+	b &= ~0x3;
+	b |= use_hsvs ? 1 : 0;
+	b |= (use_ndp && use_hsvs) ? 0 : 2;
+	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+
+	blizzard.vsync_only = !use_hsvs;
+
+	dev_dbg(blizzard.fbdev->dev,
+		"pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
+		pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time);
+	dev_dbg(blizzard.fbdev->dev,
+		"hs %d ps vs %d ps mode %d vsync_only %d\n",
+		hs, vs, b & 0x3, !use_hsvs);
+
+	return blizzard.extif->setup_tearsync(1, hs, vs,
+					      hs_pol_inv, vs_pol_inv,
+					      extif_div);
+}
+
+static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
+{
+	blizzard.int_ctrl->get_caps(plane, caps);
+	caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
+		OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
+		OMAPFB_CAPS_WINDOW_SCALE |
+		OMAPFB_CAPS_WINDOW_OVERLAY;
+	if (blizzard.te_connected)
+		caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
+	caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
+			   (1 << OMAPFB_COLOR_YUV420);
+}
+
+static void _save_regs(struct blizzard_reg_list *list, int cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++, list++) {
+		int reg;
+		for (reg = list->start; reg <= list->end; reg += 2)
+			blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg);
+	}
+}
+
+static void _restore_regs(struct blizzard_reg_list *list, int cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++, list++) {
+		int reg;
+		for (reg = list->start; reg <= list->end; reg += 2)
+			blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]);
+	}
+}
+
+static void blizzard_save_all_regs(void)
+{
+	_save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
+	_save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
+}
+
+static void blizzard_restore_pll_regs(void)
+{
+	_restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
+}
+
+static void blizzard_restore_gen_regs(void)
+{
+	_restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
+}
+
+static void blizzard_suspend(void)
+{
+	u32 l;
+	unsigned long tmo;
+
+	if (blizzard.last_color_mode) {
+		update_full_screen();
+		blizzard_sync();
+	}
+	blizzard.update_mode_before_suspend = blizzard.update_mode;
+	/* the following will disable clocks as well */
+	blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
+
+	blizzard_save_all_regs();
+
+	blizzard_stop_sdram();
+
+	l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
+	/* Standby, Sleep. We assume we use an external clock. */
+	l |= 0x03;
+	blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
+
+	tmo = jiffies + msecs_to_jiffies(100);
+	while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) {
+		if (time_after(jiffies, tmo)) {
+			dev_err(blizzard.fbdev->dev,
+				"s1d1374x: sleep timeout, stopping PLL manually\n");
+			l = blizzard_read_reg(BLIZZARD_PLL_MODE);
+			l &= ~0x03;
+			/* Disable PLL, counter function */
+			l |= 0x2;
+			blizzard_write_reg(BLIZZARD_PLL_MODE, l);
+			break;
+		}
+		msleep(1);
+	}
+
+	if (blizzard.power_down != NULL)
+		blizzard.power_down(blizzard.fbdev->dev);
+}
+
+static void blizzard_resume(void)
+{
+	u32 l;
+
+	if (blizzard.power_up != NULL)
+		blizzard.power_up(blizzard.fbdev->dev);
+
+	l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
+	/* Standby, Sleep */
+	l &= ~0x03;
+	blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
+
+	blizzard_restore_pll_regs();
+	l = blizzard_read_reg(BLIZZARD_PLL_MODE);
+	l &= ~0x03;
+	/* Enable PLL, counter function */
+	l |= 0x1;
+	blizzard_write_reg(BLIZZARD_PLL_MODE, l);
+
+	while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7)))
+		msleep(1);
+
+	blizzard_restart_sdram();
+
+	blizzard_restore_gen_regs();
+
+	/* Enable display */
+	blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01);
+
+	/* the following will enable clocks as necessary */
+	blizzard_set_update_mode(blizzard.update_mode_before_suspend);
+
+	/* Force a background update */
+	blizzard.zoom_on = 1;
+	update_full_screen();
+	blizzard_sync();
+}
+
+static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
+			 struct omapfb_mem_desc *req_vram)
+{
+	int r = 0, i;
+	u8 rev, conf;
+	unsigned long ext_clk;
+	int extif_div;
+	unsigned long sys_clk, pix_clk;
+	struct omapfb_platform_data *omapfb_conf;
+	struct blizzard_platform_data *ctrl_conf;
+
+	blizzard.fbdev = fbdev;
+
+	BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
+
+	blizzard.fbdev = fbdev;
+	blizzard.extif = fbdev->ext_if;
+	blizzard.int_ctrl = fbdev->int_ctrl;
+
+	omapfb_conf = fbdev->dev->platform_data;
+	ctrl_conf = omapfb_conf->ctrl_platform_data;
+	if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
+		dev_err(fbdev->dev, "s1d1374x: missing platform data\n");
+		r = -ENOENT;
+		goto err1;
+	}
+
+	blizzard.power_down = ctrl_conf->power_down;
+	blizzard.power_up = ctrl_conf->power_up;
+
+	spin_lock_init(&blizzard.req_lock);
+
+	if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0)
+		goto err1;
+
+	if ((r = blizzard.extif->init(fbdev)) < 0)
+		goto err2;
+
+	blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key;
+	blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key;
+	blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem;
+	blizzard_ctrl.mmap = blizzard.int_ctrl->mmap;
+
+	ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
+	if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0)
+		goto err3;
+
+	set_extif_timings(&blizzard.reg_timings);
+
+	if (blizzard.power_up != NULL)
+		blizzard.power_up(fbdev->dev);
+
+	calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk);
+
+	if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0)
+		goto err3;
+	set_extif_timings(&blizzard.reg_timings);
+
+	if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) {
+		dev_err(fbdev->dev,
+			"controller not initialized by the bootloader\n");
+		r = -ENODEV;
+		goto err3;
+	}
+
+	if (ctrl_conf->te_connected) {
+		if ((r = setup_tearsync(pix_clk, extif_div)) < 0)
+			goto err3;
+		blizzard.te_connected = 1;
+	}
+
+	rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+	conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+	switch (rev & 0xfc) {
+	case 0x9c:
+		blizzard.version = BLIZZARD_VERSION_S1D13744;
+		pr_info("omapfb: s1d13744 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	case 0xa4:
+		blizzard.version = BLIZZARD_VERSION_S1D13745;
+		pr_info("omapfb: s1d13745 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	default:
+		dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n",
+			rev);
+		r = -ENODEV;
+		goto err3;
+	}
+
+	blizzard.max_transmit_size = blizzard.extif->max_transmit_size;
+
+	blizzard.update_mode = OMAPFB_UPDATE_DISABLED;
+
+	blizzard.auto_update_window.x = 0;
+	blizzard.auto_update_window.y = 0;
+	blizzard.auto_update_window.width = fbdev->panel->x_res;
+	blizzard.auto_update_window.height = fbdev->panel->y_res;
+	blizzard.auto_update_window.out_x = 0;
+	blizzard.auto_update_window.out_x = 0;
+	blizzard.auto_update_window.out_width = fbdev->panel->x_res;
+	blizzard.auto_update_window.out_height = fbdev->panel->y_res;
+	blizzard.auto_update_window.format = 0;
+
+	blizzard.screen_width = fbdev->panel->x_res;
+	blizzard.screen_height = fbdev->panel->y_res;
+
+	init_timer(&blizzard.auto_update_timer);
+	blizzard.auto_update_timer.function = blizzard_update_window_auto;
+	blizzard.auto_update_timer.data = 0;
+
+	INIT_LIST_HEAD(&blizzard.free_req_list);
+	INIT_LIST_HEAD(&blizzard.pending_req_list);
+	for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++)
+		list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list);
+	BUG_ON(i <= IRQ_REQ_POOL_SIZE);
+	sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE);
+
+	return 0;
+err3:
+	if (blizzard.power_down != NULL)
+		blizzard.power_down(fbdev->dev);
+	blizzard.extif->cleanup();
+err2:
+	blizzard.int_ctrl->cleanup();
+err1:
+	return r;
+}
+
+static void blizzard_cleanup(void)
+{
+	blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	blizzard.extif->cleanup();
+	blizzard.int_ctrl->cleanup();
+	if (blizzard.power_down != NULL)
+		blizzard.power_down(blizzard.fbdev->dev);
+}
+
+struct lcd_ctrl blizzard_ctrl = {
+	.name			= "blizzard",
+	.init			= blizzard_init,
+	.cleanup		= blizzard_cleanup,
+	.bind_client		= blizzard_bind_client,
+	.get_caps		= blizzard_get_caps,
+	.set_update_mode	= blizzard_set_update_mode,
+	.get_update_mode	= blizzard_get_update_mode,
+	.setup_plane		= blizzard_setup_plane,
+	.set_scale		= blizzard_set_scale,
+	.enable_plane		= blizzard_enable_plane,
+	.update_window		= blizzard_update_window_async,
+	.sync			= blizzard_sync,
+	.suspend		= blizzard_suspend,
+	.resume			= blizzard_resume,
+};
+
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
new file mode 100644
index 0000000..f4c2343
--- /dev/null
+++ b/drivers/video/omap/dispc.c
@@ -0,0 +1,1502 @@
+/*
+ * OMAP2 display controller support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.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.
+ */
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/board.h>
+
+#include "dispc.h"
+
+#define MODULE_NAME			"dispc"
+
+#define DSS_BASE			0x48050000
+#define DSS_SYSCONFIG			0x0010
+
+#define DISPC_BASE			0x48050400
+
+/* DISPC common */
+#define DISPC_REVISION			0x0000
+#define DISPC_SYSCONFIG			0x0010
+#define DISPC_SYSSTATUS			0x0014
+#define DISPC_IRQSTATUS			0x0018
+#define DISPC_IRQENABLE			0x001C
+#define DISPC_CONTROL			0x0040
+#define DISPC_CONFIG			0x0044
+#define DISPC_CAPABLE			0x0048
+#define DISPC_DEFAULT_COLOR0		0x004C
+#define DISPC_DEFAULT_COLOR1		0x0050
+#define DISPC_TRANS_COLOR0		0x0054
+#define DISPC_TRANS_COLOR1		0x0058
+#define DISPC_LINE_STATUS		0x005C
+#define DISPC_LINE_NUMBER		0x0060
+#define DISPC_TIMING_H			0x0064
+#define DISPC_TIMING_V			0x0068
+#define DISPC_POL_FREQ			0x006C
+#define DISPC_DIVISOR			0x0070
+#define DISPC_SIZE_DIG			0x0078
+#define DISPC_SIZE_LCD			0x007C
+
+#define DISPC_DATA_CYCLE1		0x01D4
+#define DISPC_DATA_CYCLE2		0x01D8
+#define DISPC_DATA_CYCLE3		0x01DC
+
+/* DISPC GFX plane */
+#define DISPC_GFX_BA0			0x0080
+#define DISPC_GFX_BA1			0x0084
+#define DISPC_GFX_POSITION		0x0088
+#define DISPC_GFX_SIZE			0x008C
+#define DISPC_GFX_ATTRIBUTES		0x00A0
+#define DISPC_GFX_FIFO_THRESHOLD	0x00A4
+#define DISPC_GFX_FIFO_SIZE_STATUS	0x00A8
+#define DISPC_GFX_ROW_INC		0x00AC
+#define DISPC_GFX_PIXEL_INC		0x00B0
+#define DISPC_GFX_WINDOW_SKIP		0x00B4
+#define DISPC_GFX_TABLE_BA		0x00B8
+
+/* DISPC Video plane 1/2 */
+#define DISPC_VID1_BASE			0x00BC
+#define DISPC_VID2_BASE			0x014C
+
+/* Offsets into DISPC_VID1/2_BASE */
+#define DISPC_VID_BA0			0x0000
+#define DISPC_VID_BA1			0x0004
+#define DISPC_VID_POSITION		0x0008
+#define DISPC_VID_SIZE			0x000C
+#define DISPC_VID_ATTRIBUTES		0x0010
+#define DISPC_VID_FIFO_THRESHOLD	0x0014
+#define DISPC_VID_FIFO_SIZE_STATUS	0x0018
+#define DISPC_VID_ROW_INC		0x001C
+#define DISPC_VID_PIXEL_INC		0x0020
+#define DISPC_VID_FIR			0x0024
+#define DISPC_VID_PICTURE_SIZE		0x0028
+#define DISPC_VID_ACCU0			0x002C
+#define DISPC_VID_ACCU1			0x0030
+
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_H0		0x0034
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_HV0		0x0038
+/* 5 elements in 4 byte increments */
+#define DISPC_VID_CONV_COEF0		0x0074
+
+#define DISPC_IRQ_FRAMEMASK		0x0001
+#define DISPC_IRQ_VSYNC			0x0002
+#define DISPC_IRQ_EVSYNC_EVEN		0x0004
+#define DISPC_IRQ_EVSYNC_ODD		0x0008
+#define DISPC_IRQ_ACBIAS_COUNT_STAT	0x0010
+#define DISPC_IRQ_PROG_LINE_NUM		0x0020
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW	0x0040
+#define DISPC_IRQ_GFX_END_WIN		0x0080
+#define DISPC_IRQ_PAL_GAMMA_MASK	0x0100
+#define DISPC_IRQ_OCP_ERR		0x0200
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW	0x0400
+#define DISPC_IRQ_VID1_END_WIN		0x0800
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW	0x1000
+#define DISPC_IRQ_VID2_END_WIN		0x2000
+#define DISPC_IRQ_SYNC_LOST		0x4000
+
+#define DISPC_IRQ_MASK_ALL		0x7fff
+
+#define DISPC_IRQ_MASK_ERROR		(DISPC_IRQ_GFX_FIFO_UNDERFLOW |	\
+					     DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+					     DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+					     DISPC_IRQ_SYNC_LOST)
+
+#define RFBI_CONTROL			0x48050040
+
+#define MAX_PALETTE_SIZE		(256 * 16)
+
+#define FLD_MASK(pos, len)	(((1 << len) - 1) << pos)
+
+#define MOD_REG_FLD(reg, mask, val) \
+	dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
+
+#define OMAP2_SRAM_START		0x40200000
+/* Maximum size, in reality this is smaller if SRAM is partially locked. */
+#define OMAP2_SRAM_SIZE			0xa0000		/* 640k */
+
+/* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */
+#define DISPC_MEMTYPE_NUM		2
+
+#define RESMAP_SIZE(_page_cnt)						\
+	((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
+#define RESMAP_PTR(_res_map, _page_nr)					\
+	(((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
+#define RESMAP_MASK(_page_nr)						\
+	(1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
+
+struct resmap {
+	unsigned long	start;
+	unsigned	page_cnt;
+	unsigned long	*map;
+};
+
+static struct {
+	u32		base;
+
+	struct omapfb_mem_desc	mem_desc;
+	struct resmap		*res_map[DISPC_MEMTYPE_NUM];
+	atomic_t		map_count[OMAPFB_PLANE_NUM];
+
+	dma_addr_t	palette_paddr;
+	void		*palette_vaddr;
+
+	int		ext_mode;
+
+	unsigned long	enabled_irqs;
+	void		(*irq_callback)(void *);
+	void		*irq_callback_data;
+	struct completion	frame_done;
+
+	int		fir_hinc[OMAPFB_PLANE_NUM];
+	int		fir_vinc[OMAPFB_PLANE_NUM];
+
+	struct clk	*dss_ick, *dss1_fck;
+	struct clk	*dss_54m_fck;
+
+	enum omapfb_update_mode	update_mode;
+	struct omapfb_device	*fbdev;
+
+	struct omapfb_color_key	color_key;
+} dispc;
+
+static void enable_lcd_clocks(int enable);
+
+static void inline dispc_write_reg(int idx, u32 val)
+{
+	__raw_writel(val, dispc.base + idx);
+}
+
+static u32 inline dispc_read_reg(int idx)
+{
+	u32 l = __raw_readl(dispc.base + idx);
+	return l;
+}
+
+/* Select RFBI or bypass mode */
+static void enable_rfbi_mode(int enable)
+{
+	u32 l;
+
+	l = dispc_read_reg(DISPC_CONTROL);
+	/* Enable RFBI, GPIO0/1 */
+	l &= ~((1 << 11) | (1 << 15) | (1 << 16));
+	l |= enable ? (1 << 11) : 0;
+	/* RFBI En: GPIO0/1=10  RFBI Dis: GPIO0/1=11 */
+	l |= 1 << 15;
+	l |= enable ? 0 : (1 << 16);
+	dispc_write_reg(DISPC_CONTROL, l);
+
+	/* Set bypass mode in RFBI module */
+	l = __raw_readl(io_p2v(RFBI_CONTROL));
+	l |= enable ? 0 : (1 << 1);
+	__raw_writel(l, io_p2v(RFBI_CONTROL));
+}
+
+static void set_lcd_data_lines(int data_lines)
+{
+	u32 l;
+	int code = 0;
+
+	switch (data_lines) {
+	case 12:
+		code = 0;
+		break;
+	case 16:
+		code = 1;
+		break;
+	case 18:
+		code = 2;
+		break;
+	case 24:
+		code = 3;
+		break;
+	default:
+		BUG();
+	}
+
+	l = dispc_read_reg(DISPC_CONTROL);
+	l &= ~(0x03 << 8);
+	l |= code << 8;
+	dispc_write_reg(DISPC_CONTROL, l);
+}
+
+static void set_load_mode(int mode)
+{
+	BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
+			DISPC_LOAD_CLUT_ONCE_FRAME));
+	MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
+}
+
+void omap_dispc_set_lcd_size(int x, int y)
+{
+	BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+			((y - 1) << 16) | (x - 1));
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_set_lcd_size);
+
+void omap_dispc_set_digit_size(int x, int y)
+{
+	BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+			((y - 1) << 16) | (x - 1));
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_set_digit_size);
+
+static void setup_plane_fifo(int plane, int ext_mode)
+{
+	const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+				DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
+			        DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
+	const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+				DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
+				DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
+	int low, high;
+	u32 l;
+
+	BUG_ON(plane > 2);
+
+	l = dispc_read_reg(fsz_reg[plane]);
+	l &= FLD_MASK(0, 9);
+	if (ext_mode) {
+		low = l * 3 / 4;
+		high = l;
+	} else {
+		low = l / 4;
+		high = l * 3 / 4;
+	}
+	MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9),
+			(high << 16) | low);
+}
+
+void omap_dispc_enable_lcd_out(int enable)
+{
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
+
+void omap_dispc_enable_digit_out(int enable)
+{
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_digit_out);
+
+static inline int _setup_plane(int plane, int channel_out,
+				  u32 paddr, int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+				DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+			        DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+	const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
+				DISPC_VID2_BASE + DISPC_VID_BA0 };
+	const u32 ps_reg[] = { DISPC_GFX_POSITION,
+				DISPC_VID1_BASE + DISPC_VID_POSITION,
+				DISPC_VID2_BASE + DISPC_VID_POSITION };
+	const u32 sz_reg[] = { DISPC_GFX_SIZE,
+				DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,
+				DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };
+	const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
+				DISPC_VID1_BASE + DISPC_VID_ROW_INC,
+			        DISPC_VID2_BASE + DISPC_VID_ROW_INC };
+	const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+				DISPC_VID2_BASE + DISPC_VID_SIZE };
+
+	int chout_shift, burst_shift;
+	int chout_val;
+	int color_code;
+	int bpp;
+	int cconv_en;
+	int set_vsize;
+	u32 l;
+
+#ifdef VERBOSE
+	dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d"
+		    " pos_x %d pos_y %d width %d height %d color_mode %d\n",
+		    plane, channel_out, paddr, screen_width, pos_x, pos_y,
+		    width, height, color_mode);
+#endif
+
+	set_vsize = 0;
+	switch (plane) {
+	case OMAPFB_PLANE_GFX:
+		burst_shift = 6;
+		chout_shift = 8;
+		break;
+	case OMAPFB_PLANE_VID1:
+	case OMAPFB_PLANE_VID2:
+		burst_shift = 14;
+		chout_shift = 16;
+		set_vsize = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (channel_out) {
+	case OMAPFB_CHANNEL_OUT_LCD:
+		chout_val = 0;
+		break;
+	case OMAPFB_CHANNEL_OUT_DIGIT:
+		chout_val = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cconv_en = 0;
+	switch (color_mode) {
+	case OMAPFB_COLOR_RGB565:
+		color_code = DISPC_RGB_16_BPP;
+		bpp = 16;
+		break;
+	case OMAPFB_COLOR_YUV422:
+		if (plane == 0)
+			return -EINVAL;
+		color_code = DISPC_UYVY_422;
+		cconv_en = 1;
+		bpp = 16;
+		break;
+	case OMAPFB_COLOR_YUY422:
+		if (plane == 0)
+			return -EINVAL;
+		color_code = DISPC_YUV2_422;
+		cconv_en = 1;
+		bpp = 16;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	l = dispc_read_reg(at_reg[plane]);
+
+	l &= ~(0x0f << 1);
+	l |= color_code << 1;
+	l &= ~(1 << 9);
+	l |= cconv_en << 9;
+
+	l &= ~(0x03 << burst_shift);
+	l |= DISPC_BURST_8x32 << burst_shift;
+
+	l &= ~(1 << chout_shift);
+	l |= chout_val << chout_shift;
+
+	dispc_write_reg(at_reg[plane], l);
+
+	dispc_write_reg(ba_reg[plane], paddr);
+	MOD_REG_FLD(ps_reg[plane],
+		    FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
+
+	MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
+			((height - 1) << 16) | (width - 1));
+
+	if (set_vsize) {
+		/* Set video size if set_scale hasn't set it */
+		if (!dispc.fir_vinc[plane])
+			MOD_REG_FLD(vs_reg[plane],
+				FLD_MASK(16, 11), (height - 1) << 16);
+		if (!dispc.fir_hinc[plane])
+			MOD_REG_FLD(vs_reg[plane],
+				FLD_MASK(0, 11), width - 1);
+	}
+
+	dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
+
+	return height * screen_width * bpp / 8;
+}
+
+static int omap_dispc_setup_plane(int plane, int channel_out,
+				  unsigned long offset,
+				  int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	u32 paddr;
+	int r;
+
+	if ((unsigned)plane > dispc.mem_desc.region_cnt)
+		return -EINVAL;
+	paddr = dispc.mem_desc.region[plane].paddr + offset;
+	enable_lcd_clocks(1);
+	r = _setup_plane(plane, channel_out, paddr,
+			screen_width,
+			pos_x, pos_y, width, height, color_mode);
+	enable_lcd_clocks(0);
+	return r;
+}
+
+static void write_firh_reg(int plane, int reg, u32 value)
+{
+	u32 base;
+
+	if (plane == 1)
+		base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;
+	else
+		base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;
+	dispc_write_reg(base + reg * 8,	value);
+}
+
+static void write_firhv_reg(int plane, int reg, u32 value)
+{
+	u32 base;
+
+	if (plane == 1)
+		base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;
+	else
+		base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;
+	dispc_write_reg(base + reg * 8,	value);
+}
+
+static void set_upsampling_coef_table(int plane)
+{
+	const u32 coef[][2] = {
+		{ 0x00800000, 0x00800000 },
+		{ 0x0D7CF800, 0x037B02FF },
+		{ 0x1E70F5FF, 0x0C6F05FE },
+		{ 0x335FF5FE, 0x205907FB },
+		{ 0xF74949F7, 0x00404000 },
+		{ 0xF55F33FB, 0x075920FE },
+		{ 0xF5701EFE, 0x056F0CFF },
+		{ 0xF87C0DFF, 0x027B0300 },
+	};
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		write_firh_reg(plane, i, coef[i][0]);
+		write_firhv_reg(plane, i, coef[i][1]);
+	}
+}
+
+static int omap_dispc_set_scale(int plane,
+				int orig_width, int orig_height,
+				int out_width, int out_height)
+{
+	const u32 at_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+				DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+	const u32 vs_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+				DISPC_VID2_BASE + DISPC_VID_SIZE };
+	const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR,
+				DISPC_VID2_BASE + DISPC_VID_FIR };
+
+	u32 l;
+	int fir_hinc;
+	int fir_vinc;
+
+	if ((unsigned)plane > OMAPFB_PLANE_NUM)
+		return -ENODEV;
+
+	if (plane == OMAPFB_PLANE_GFX &&
+	    (out_width != orig_width || out_height != orig_height))
+		return -EINVAL;
+
+	enable_lcd_clocks(1);
+	if (orig_width < out_width) {
+		/*
+		 * Upsampling.
+		 * Currently you can only scale both dimensions in one way.
+		 */
+		if (orig_height > out_height ||
+		    orig_width * 8 < out_width ||
+		    orig_height * 8 < out_height) {
+			enable_lcd_clocks(0);
+			return -EINVAL;
+		}
+		set_upsampling_coef_table(plane);
+	} else if (orig_width > out_width) {
+		/* Downsampling not yet supported
+		*/
+
+		enable_lcd_clocks(0);
+		return -EINVAL;
+	}
+	if (!orig_width || orig_width == out_width)
+		fir_hinc = 0;
+	else
+		fir_hinc = 1024 * orig_width / out_width;
+	if (!orig_height || orig_height == out_height)
+		fir_vinc = 0;
+	else
+		fir_vinc = 1024 * orig_height / out_height;
+	dispc.fir_hinc[plane] = fir_hinc;
+	dispc.fir_vinc[plane] = fir_vinc;
+
+	MOD_REG_FLD(fir_reg[plane],
+		    FLD_MASK(16, 12) | FLD_MASK(0, 12),
+		    ((fir_vinc & 4095) << 16) |
+		    (fir_hinc & 4095));
+
+	dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
+		"orig_height %d fir_hinc  %d fir_vinc %d\n",
+		out_width, out_height, orig_width, orig_height,
+		fir_hinc, fir_vinc);
+
+	MOD_REG_FLD(vs_reg[plane],
+		    FLD_MASK(16, 11) | FLD_MASK(0, 11),
+		    ((out_height - 1) << 16) | (out_width - 1));
+
+	l = dispc_read_reg(at_reg[plane]);
+	l &= ~(0x03 << 5);
+	l |= fir_hinc ? (1 << 5) : 0;
+	l |= fir_vinc ? (1 << 6) : 0;
+	dispc_write_reg(at_reg[plane], l);
+
+	enable_lcd_clocks(0);
+	return 0;
+}
+
+static int omap_dispc_enable_plane(int plane, int enable)
+{
+	const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+				DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+				DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+	if ((unsigned int)plane > dispc.mem_desc.region_cnt)
+		return -EINVAL;
+
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
+	enable_lcd_clocks(0);
+
+	return 0;
+}
+
+static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
+{
+	u32 df_reg, tr_reg;
+	int shift, val;
+
+	switch (ck->channel_out) {
+	case OMAPFB_CHANNEL_OUT_LCD:
+		df_reg = DISPC_DEFAULT_COLOR0;
+		tr_reg = DISPC_TRANS_COLOR0;
+		shift = 10;
+		break;
+	case OMAPFB_CHANNEL_OUT_DIGIT:
+		df_reg = DISPC_DEFAULT_COLOR1;
+		tr_reg = DISPC_TRANS_COLOR1;
+		shift = 12;
+		break;
+	default:
+		return -EINVAL;
+	}
+	switch (ck->key_type) {
+	case OMAPFB_COLOR_KEY_DISABLED:
+		val = 0;
+		break;
+	case OMAPFB_COLOR_KEY_GFX_DST:
+		val = 1;
+		break;
+	case OMAPFB_COLOR_KEY_VID_SRC:
+		val = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
+
+	if (val != 0)
+		dispc_write_reg(tr_reg, ck->trans_key);
+	dispc_write_reg(df_reg, ck->background);
+	enable_lcd_clocks(0);
+
+	dispc.color_key = *ck;
+
+	return 0;
+}
+
+static int omap_dispc_get_color_key(struct omapfb_color_key *ck)
+{
+	*ck = dispc.color_key;
+	return 0;
+}
+
+static void load_palette(void)
+{
+}
+
+static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
+{
+	int r = 0;
+
+	if (mode != dispc.update_mode) {
+		switch (mode) {
+		case OMAPFB_AUTO_UPDATE:
+		case OMAPFB_MANUAL_UPDATE:
+			enable_lcd_clocks(1);
+			omap_dispc_enable_lcd_out(1);
+			dispc.update_mode = mode;
+			break;
+		case OMAPFB_UPDATE_DISABLED:
+			init_completion(&dispc.frame_done);
+			omap_dispc_enable_lcd_out(0);
+			if (!wait_for_completion_timeout(&dispc.frame_done,
+					msecs_to_jiffies(500))) {
+				dev_err(dispc.fbdev->dev,
+					 "timeout waiting for FRAME DONE\n");
+			}
+			dispc.update_mode = mode;
+			enable_lcd_clocks(0);
+			break;
+		default:
+			r = -EINVAL;
+		}
+	}
+
+	return r;
+}
+
+static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps)
+{
+	caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM;
+	if (plane > 0)
+		caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE;
+	caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) |
+			     (1 << OMAPFB_COLOR_YUV422) |
+			     (1 << OMAPFB_COLOR_YUY422);
+	if (plane == 0)
+		caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) |
+				     (1 << OMAPFB_COLOR_CLUT_4BPP) |
+				     (1 << OMAPFB_COLOR_CLUT_2BPP) |
+				     (1 << OMAPFB_COLOR_CLUT_1BPP) |
+				     (1 << OMAPFB_COLOR_RGB444);
+}
+
+static enum omapfb_update_mode omap_dispc_get_update_mode(void)
+{
+	return dispc.update_mode;
+}
+
+static void setup_color_conv_coef(void)
+{
+	u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11);
+	int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0;
+	int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0;
+	int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES;
+	int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES;
+	const struct color_conv_coef {
+		int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
+		int  full_range;
+	}  ctbl_bt601_5 = {
+		    298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
+	};
+	const struct color_conv_coef *ct;
+#define CVAL(x, y)	(((x & 2047) << 16) | (y & 2047))
+
+	ct = &ctbl_bt601_5;
+
+	MOD_REG_FLD(cf1_reg,		mask,	CVAL(ct->rcr, ct->ry));
+	MOD_REG_FLD(cf1_reg + 4,	mask,	CVAL(ct->gy,  ct->rcb));
+	MOD_REG_FLD(cf1_reg + 8,	mask,	CVAL(ct->gcb, ct->gcr));
+	MOD_REG_FLD(cf1_reg + 12,	mask,	CVAL(ct->bcr, ct->by));
+	MOD_REG_FLD(cf1_reg + 16,	mask,	CVAL(0,	      ct->bcb));
+
+	MOD_REG_FLD(cf2_reg,		mask,	CVAL(ct->rcr, ct->ry));
+	MOD_REG_FLD(cf2_reg + 4,	mask,	CVAL(ct->gy,  ct->rcb));
+	MOD_REG_FLD(cf2_reg + 8,	mask,	CVAL(ct->gcb, ct->gcr));
+	MOD_REG_FLD(cf2_reg + 12,	mask,	CVAL(ct->bcr, ct->by));
+	MOD_REG_FLD(cf2_reg + 16,	mask,	CVAL(0,	      ct->bcb));
+#undef CVAL
+
+	MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range);
+	MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
+}
+
+static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
+{
+	unsigned long fck, lck;
+
+	*lck_div = 1;
+	pck = max(1, pck);
+	fck = clk_get_rate(dispc.dss1_fck);
+	lck = fck;
+	*pck_div = (lck + pck - 1) / pck;
+	if (is_tft)
+		*pck_div = max(2, *pck_div);
+	else
+		*pck_div = max(3, *pck_div);
+	if (*pck_div > 255) {
+		*pck_div = 255;
+		lck = pck * *pck_div;
+		*lck_div = fck / lck;
+		BUG_ON(*lck_div < 1);
+		if (*lck_div > 255) {
+			*lck_div = 255;
+			dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n",
+				 pck / 1000);
+		}
+	}
+}
+
+static void set_lcd_tft_mode(int enable)
+{
+	u32 mask;
+
+	mask = 1 << 3;
+	MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0);
+}
+
+static void set_lcd_timings(void)
+{
+	u32 l;
+	int lck_div, pck_div;
+	struct lcd_panel *panel = dispc.fbdev->panel;
+	int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+	unsigned long fck;
+
+	l = dispc_read_reg(DISPC_TIMING_H);
+	l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+	l |= ( max(1, (min(64,  panel->hsw))) - 1 ) << 0;
+	l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
+	l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
+	dispc_write_reg(DISPC_TIMING_H, l);
+
+	l = dispc_read_reg(DISPC_TIMING_V);
+	l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+	l |= ( max(1, (min(64,  panel->vsw))) - 1 ) << 0;
+	l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
+	l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
+	dispc_write_reg(DISPC_TIMING_V, l);
+
+	l = dispc_read_reg(DISPC_POL_FREQ);
+	l &= ~FLD_MASK(12, 6);
+	l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
+	l |= panel->acb & 0xff;
+	dispc_write_reg(DISPC_POL_FREQ, l);
+
+	calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
+
+	l = dispc_read_reg(DISPC_DIVISOR);
+	l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
+	l |= (lck_div << 16) | (pck_div << 0);
+	dispc_write_reg(DISPC_DIVISOR, l);
+
+	/* update panel info with the exact clock */
+	fck = clk_get_rate(dispc.dss1_fck);
+	panel->pixel_clock = fck / lck_div / pck_div / 1000;
+}
+
+int omap_dispc_request_irq(void (*callback)(void *data), void *data)
+{
+	int r = 0;
+
+	BUG_ON(callback == NULL);
+
+	if (dispc.irq_callback)
+		r = -EBUSY;
+	else {
+		dispc.irq_callback = callback;
+		dispc.irq_callback_data = data;
+	}
+
+	return r;
+}
+EXPORT_SYMBOL(omap_dispc_request_irq);
+
+void omap_dispc_enable_irqs(int irq_mask)
+{
+	enable_lcd_clocks(1);
+	dispc.enabled_irqs = irq_mask;
+	irq_mask |= DISPC_IRQ_MASK_ERROR;
+	MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_irqs);
+
+void omap_dispc_disable_irqs(int irq_mask)
+{
+	enable_lcd_clocks(1);
+	dispc.enabled_irqs &= ~irq_mask;
+	irq_mask &= ~DISPC_IRQ_MASK_ERROR;
+	MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_disable_irqs);
+
+void omap_dispc_free_irq(void)
+{
+	enable_lcd_clocks(1);
+	omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL);
+	dispc.irq_callback = NULL;
+	dispc.irq_callback_data = NULL;
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_free_irq);
+
+static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
+{
+	u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
+
+	if (stat & DISPC_IRQ_FRAMEMASK)
+		complete(&dispc.frame_done);
+
+	if (stat & DISPC_IRQ_MASK_ERROR) {
+		if (printk_ratelimit()) {
+			dev_err(dispc.fbdev->dev, "irq error status %04x\n",
+				stat & 0x7fff);
+		}
+	}
+
+	if ((stat & dispc.enabled_irqs) && dispc.irq_callback)
+		dispc.irq_callback(dispc.irq_callback_data);
+
+	dispc_write_reg(DISPC_IRQSTATUS, stat);
+
+	return IRQ_HANDLED;
+}
+
+static int get_dss_clocks(void)
+{
+	if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
+		dev_err(dispc.fbdev->dev, "can't get dss_ick");
+		return PTR_ERR(dispc.dss_ick);
+	}
+
+	if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
+		dev_err(dispc.fbdev->dev, "can't get dss1_fck");
+		clk_put(dispc.dss_ick);
+		return PTR_ERR(dispc.dss1_fck);
+	}
+
+	if (IS_ERR((dispc.dss_54m_fck =
+				clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
+		dev_err(dispc.fbdev->dev, "can't get dss_54m_fck");
+		clk_put(dispc.dss_ick);
+		clk_put(dispc.dss1_fck);
+		return PTR_ERR(dispc.dss_54m_fck);
+	}
+
+	return 0;
+}
+
+static void put_dss_clocks(void)
+{
+	clk_put(dispc.dss_54m_fck);
+	clk_put(dispc.dss1_fck);
+	clk_put(dispc.dss_ick);
+}
+
+static void enable_lcd_clocks(int enable)
+{
+	if (enable)
+		clk_enable(dispc.dss1_fck);
+	else
+		clk_disable(dispc.dss1_fck);
+}
+
+static void enable_interface_clocks(int enable)
+{
+	if (enable)
+		clk_enable(dispc.dss_ick);
+	else
+		clk_disable(dispc.dss_ick);
+}
+
+static void enable_digit_clocks(int enable)
+{
+	if (enable)
+		clk_enable(dispc.dss_54m_fck);
+	else
+		clk_disable(dispc.dss_54m_fck);
+}
+
+static void omap_dispc_suspend(void)
+{
+	if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+		init_completion(&dispc.frame_done);
+		omap_dispc_enable_lcd_out(0);
+		if (!wait_for_completion_timeout(&dispc.frame_done,
+				msecs_to_jiffies(500))) {
+			dev_err(dispc.fbdev->dev,
+				"timeout waiting for FRAME DONE\n");
+		}
+		enable_lcd_clocks(0);
+	}
+}
+
+static void omap_dispc_resume(void)
+{
+	if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+		enable_lcd_clocks(1);
+		if (!dispc.ext_mode) {
+			set_lcd_timings();
+			load_palette();
+		}
+		omap_dispc_enable_lcd_out(1);
+	}
+}
+
+
+static int omap_dispc_update_window(struct fb_info *fbi,
+				 struct omapfb_update_window *win,
+				 void (*complete_callback)(void *arg),
+				 void *complete_callback_data)
+{
+	return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0;
+}
+
+static int mmap_kern(struct omapfb_mem_region *region)
+{
+	struct vm_struct	*kvma;
+	struct vm_area_struct	vma;
+	pgprot_t		pgprot;
+	unsigned long		vaddr;
+
+	kvma = get_vm_area(region->size, VM_IOREMAP);
+	if (kvma == NULL) {
+		dev_err(dispc.fbdev->dev, "can't get kernel vm area\n");
+		return -ENOMEM;
+	}
+	vma.vm_mm = &init_mm;
+
+	vaddr = (unsigned long)kvma->addr;
+
+	pgprot = pgprot_writecombine(pgprot_kernel);
+	vma.vm_start = vaddr;
+	vma.vm_end = vaddr + region->size;
+	if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT,
+			   region->size, pgprot) < 0) {
+		dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n");
+		return -EAGAIN;
+	}
+	region->vaddr = (void *)vaddr;
+
+	return 0;
+}
+
+static void mmap_user_open(struct vm_area_struct *vma)
+{
+	int plane = (int)vma->vm_private_data;
+
+	atomic_inc(&dispc.map_count[plane]);
+}
+
+static void mmap_user_close(struct vm_area_struct *vma)
+{
+	int plane = (int)vma->vm_private_data;
+
+	atomic_dec(&dispc.map_count[plane]);
+}
+
+static struct vm_operations_struct mmap_user_ops = {
+	.open = mmap_user_open,
+	.close = mmap_user_close,
+};
+
+static int omap_dispc_mmap_user(struct fb_info *info,
+				struct vm_area_struct *vma)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	unsigned long off;
+	unsigned long start;
+	u32 len;
+
+	if (vma->vm_end - vma->vm_start == 0)
+		return 0;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	off = vma->vm_pgoff << PAGE_SHIFT;
+
+	start = info->fix.smem_start;
+	len = info->fix.smem_len;
+	if (off >= len)
+		return -EINVAL;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		return -EINVAL;
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	vma->vm_ops = &mmap_user_ops;
+	vma->vm_private_data = (void *)plane->idx;
+	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
+		return -EAGAIN;
+	/* vm_ops.open won't be called for mmap itself. */
+	atomic_inc(&dispc.map_count[plane->idx]);
+	return 0;
+}
+
+static void unmap_kern(struct omapfb_mem_region *region)
+{
+	vunmap(region->vaddr);
+}
+
+static int alloc_palette_ram(void)
+{
+	dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
+		MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL);
+	if (dispc.palette_vaddr == NULL) {
+		dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void free_palette_ram(void)
+{
+	dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE,
+			dispc.palette_vaddr, dispc.palette_paddr);
+}
+
+static int alloc_fbmem(struct omapfb_mem_region *region)
+{
+	region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
+			region->size, &region->paddr, GFP_KERNEL);
+
+	if (region->vaddr == NULL) {
+		dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void free_fbmem(struct omapfb_mem_region *region)
+{
+	dma_free_writecombine(dispc.fbdev->dev, region->size,
+			      region->vaddr, region->paddr);
+}
+
+static struct resmap *init_resmap(unsigned long start, size_t size)
+{
+	unsigned page_cnt;
+	struct resmap *res_map;
+
+	page_cnt = PAGE_ALIGN(size) / PAGE_SIZE;
+	res_map =
+	    kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL);
+	if (res_map == NULL)
+		return NULL;
+	res_map->start = start;
+	res_map->page_cnt = page_cnt;
+	res_map->map = (unsigned long *)(res_map + 1);
+	return res_map;
+}
+
+static void cleanup_resmap(struct resmap *res_map)
+{
+	kfree(res_map);
+}
+
+static inline int resmap_mem_type(unsigned long start)
+{
+	if (start >= OMAP2_SRAM_START &&
+	    start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
+		return OMAPFB_MEMTYPE_SRAM;
+	else
+		return OMAPFB_MEMTYPE_SDRAM;
+}
+
+static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr)
+{
+	return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0;
+}
+
+static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr)
+{
+	BUG_ON(resmap_page_reserved(res_map, page_nr));
+	*RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr);
+}
+
+static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr)
+{
+	BUG_ON(!resmap_page_reserved(res_map, page_nr));
+	*RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr);
+}
+
+static void resmap_reserve_region(unsigned long start, size_t size)
+{
+
+	struct resmap	*res_map;
+	unsigned	start_page;
+	unsigned	end_page;
+	int		mtype;
+	unsigned	i;
+
+	mtype = resmap_mem_type(start);
+	res_map = dispc.res_map[mtype];
+	dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n",
+		mtype, start, size);
+	start_page = (start - res_map->start) / PAGE_SIZE;
+	end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
+	for (i = start_page; i < end_page; i++)
+		resmap_reserve_page(res_map, i);
+}
+
+static void resmap_free_region(unsigned long start, size_t size)
+{
+	struct resmap	*res_map;
+	unsigned	start_page;
+	unsigned	end_page;
+	unsigned	i;
+	int		mtype;
+
+	mtype = resmap_mem_type(start);
+	res_map = dispc.res_map[mtype];
+	dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n",
+		mtype, start, size);
+	start_page = (start - res_map->start) / PAGE_SIZE;
+	end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
+	for (i = start_page; i < end_page; i++)
+		resmap_free_page(res_map, i);
+}
+
+static unsigned long resmap_alloc_region(int mtype, size_t size)
+{
+	unsigned i;
+	unsigned total;
+	unsigned start_page;
+	unsigned long start;
+	struct resmap *res_map = dispc.res_map[mtype];
+
+	BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size);
+
+	size = PAGE_ALIGN(size) / PAGE_SIZE;
+	start_page = 0;
+	total = 0;
+	for (i = 0; i < res_map->page_cnt; i++) {
+		if (resmap_page_reserved(res_map, i)) {
+			start_page = i + 1;
+			total = 0;
+		} else if (++total == size)
+			break;
+	}
+	if (total < size)
+		return 0;
+
+	start = res_map->start + start_page * PAGE_SIZE;
+	resmap_reserve_region(start, size * PAGE_SIZE);
+
+	return start;
+}
+
+/* Note that this will only work for user mappings, we don't deal with
+ * kernel mappings here, so fbcon will keep using the old region.
+ */
+static int omap_dispc_setup_mem(int plane, size_t size, int mem_type,
+				unsigned long *paddr)
+{
+	struct omapfb_mem_region *rg;
+	unsigned long new_addr = 0;
+
+	if ((unsigned)plane > dispc.mem_desc.region_cnt)
+		return -EINVAL;
+	if (mem_type >= DISPC_MEMTYPE_NUM)
+		return -EINVAL;
+	if (dispc.res_map[mem_type] == NULL)
+		return -ENOMEM;
+	rg = &dispc.mem_desc.region[plane];
+	if (size == rg->size && mem_type == rg->type)
+		return 0;
+	if (atomic_read(&dispc.map_count[plane]))
+		return -EBUSY;
+	if (rg->size != 0)
+		resmap_free_region(rg->paddr, rg->size);
+	if (size != 0) {
+		new_addr = resmap_alloc_region(mem_type, size);
+		if (!new_addr) {
+			/* Reallocate old region. */
+			resmap_reserve_region(rg->paddr, rg->size);
+			return -ENOMEM;
+		}
+	}
+	rg->paddr = new_addr;
+	rg->size = size;
+	rg->type = mem_type;
+
+	*paddr = new_addr;
+
+	return 0;
+}
+
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
+{
+	struct omapfb_mem_region	*rg;
+	int i;
+	int r;
+	unsigned long			mem_start[DISPC_MEMTYPE_NUM];
+	unsigned long			mem_end[DISPC_MEMTYPE_NUM];
+
+	if (!req_md->region_cnt) {
+		dev_err(dispc.fbdev->dev, "no memory regions defined\n");
+		return -ENOENT;
+	}
+
+	rg = &req_md->region[0];
+	memset(mem_start, 0xff, sizeof(mem_start));
+	memset(mem_end, 0, sizeof(mem_end));
+
+	for (i = 0; i < req_md->region_cnt; i++, rg++) {
+		int mtype;
+		if (rg->paddr) {
+			rg->alloc = 0;
+			if (rg->vaddr == NULL) {
+				rg->map = 1;
+				if ((r = mmap_kern(rg)) < 0)
+					return r;
+			}
+		} else {
+			if (rg->type != OMAPFB_MEMTYPE_SDRAM) {
+				dev_err(dispc.fbdev->dev,
+					"unsupported memory type\n");
+				return -EINVAL;
+			}
+			rg->alloc = rg->map = 1;
+			if ((r = alloc_fbmem(rg)) < 0)
+				return r;
+		}
+		mtype = rg->type;
+
+		if (rg->paddr < mem_start[mtype])
+			mem_start[mtype] = rg->paddr;
+		if (rg->paddr + rg->size > mem_end[mtype])
+			mem_end[mtype] = rg->paddr + rg->size;
+	}
+
+	for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+		unsigned long start;
+		size_t size;
+		if (mem_end[i] == 0)
+			continue;
+		start = mem_start[i];
+		size = mem_end[i] - start;
+		dispc.res_map[i] = init_resmap(start, size);
+		r = -ENOMEM;
+		if (dispc.res_map[i] == NULL)
+			goto fail;
+		/* Initial state is that everything is reserved. This
+		 * includes possible holes as well, which will never be
+		 * freed.
+		 */
+		resmap_reserve_region(start, size);
+	}
+
+	dispc.mem_desc = *req_md;
+
+	return 0;
+fail:
+	for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+		if (dispc.res_map[i] != NULL)
+			cleanup_resmap(dispc.res_map[i]);
+	}
+	return r;
+}
+
+static void cleanup_fbmem(void)
+{
+	struct omapfb_mem_region *rg;
+	int i;
+
+	for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+		if (dispc.res_map[i] != NULL)
+			cleanup_resmap(dispc.res_map[i]);
+	}
+	rg = &dispc.mem_desc.region[0];
+	for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) {
+		if (rg->alloc)
+			free_fbmem(rg);
+		else {
+			if (rg->map)
+				unmap_kern(rg);
+		}
+	}
+}
+
+static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
+			   struct omapfb_mem_desc *req_vram)
+{
+	int r;
+	u32 l;
+	struct lcd_panel *panel = fbdev->panel;
+	int tmo = 10000;
+	int skip_init = 0;
+	int i;
+
+	memset(&dispc, 0, sizeof(dispc));
+
+	dispc.base = io_p2v(DISPC_BASE);
+	dispc.fbdev = fbdev;
+	dispc.ext_mode = ext_mode;
+
+	init_completion(&dispc.frame_done);
+
+	if ((r = get_dss_clocks()) < 0)
+		return r;
+
+	enable_interface_clocks(1);
+	enable_lcd_clocks(1);
+
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+	l = dispc_read_reg(DISPC_CONTROL);
+	/* LCD enabled ? */
+	if (l & 1) {
+		pr_info("omapfb: skipping hardware initialization\n");
+		skip_init = 1;
+	}
+#endif
+
+	if (!skip_init) {
+		/* Reset monitoring works only w/ the 54M clk */
+		enable_digit_clocks(1);
+
+		/* Soft reset */
+		MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
+
+		while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
+			if (!--tmo) {
+				dev_err(dispc.fbdev->dev, "soft reset failed\n");
+				r = -ENODEV;
+				enable_digit_clocks(0);
+				goto fail1;
+			}
+		}
+
+		enable_digit_clocks(0);
+	}
+
+	/* Enable smart idle and autoidle */
+	l = dispc_read_reg(DISPC_CONTROL);
+	l &= ~((3 << 12) | (3 << 3));
+	l |= (2 << 12) | (2 << 3) | (1 << 0);
+	dispc_write_reg(DISPC_SYSCONFIG, l);
+	omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
+
+	/* Set functional clock autogating */
+	l = dispc_read_reg(DISPC_CONFIG);
+	l |= 1 << 9;
+	dispc_write_reg(DISPC_CONFIG, l);
+
+	l = dispc_read_reg(DISPC_IRQSTATUS);
+	dispc_write_reg(l, DISPC_IRQSTATUS);
+
+	/* Enable those that we handle always */
+	omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
+
+	if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
+			   0, MODULE_NAME, fbdev)) < 0) {
+		dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n");
+		goto fail1;
+	}
+
+	/* L3 firewall setting: enable access to OCM RAM */
+	__raw_writel(0x402000b0, io_p2v(0x680050a0));
+
+	if ((r = alloc_palette_ram()) < 0)
+		goto fail2;
+
+	if ((r = setup_fbmem(req_vram)) < 0)
+		goto fail3;
+
+	if (!skip_init) {
+		for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
+			memset(dispc.mem_desc.region[i].vaddr, 0,
+				dispc.mem_desc.region[i].size);
+		}
+
+		/* Set logic clock to fck, pixel clock to fck/2 for now */
+		MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16);
+		MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0);
+
+		setup_plane_fifo(0, ext_mode);
+		setup_plane_fifo(1, ext_mode);
+		setup_plane_fifo(2, ext_mode);
+
+		setup_color_conv_coef();
+
+		set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT);
+		set_load_mode(DISPC_LOAD_FRAME_ONLY);
+
+		if (!ext_mode) {
+			set_lcd_data_lines(panel->data_lines);
+			omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
+			set_lcd_timings();
+		} else
+			set_lcd_data_lines(panel->bpp);
+		enable_rfbi_mode(ext_mode);
+	}
+
+	l = dispc_read_reg(DISPC_REVISION);
+	pr_info("omapfb: DISPC version %d.%d initialized\n",
+		 l >> 4 & 0x0f, l & 0x0f);
+	enable_lcd_clocks(0);
+
+	return 0;
+fail3:
+	free_palette_ram();
+fail2:
+	free_irq(INT_24XX_DSS_IRQ, fbdev);
+fail1:
+	enable_lcd_clocks(0);
+	enable_interface_clocks(0);
+	put_dss_clocks();
+
+	return r;
+}
+
+static void omap_dispc_cleanup(void)
+{
+	int i;
+
+	omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	/* This will also disable clocks that are on */
+	for (i = 0; i < dispc.mem_desc.region_cnt; i++)
+		omap_dispc_enable_plane(i, 0);
+	cleanup_fbmem();
+	free_palette_ram();
+	free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
+	enable_interface_clocks(0);
+	put_dss_clocks();
+}
+
+const struct lcd_ctrl omap2_int_ctrl = {
+	.name			= "internal",
+	.init			= omap_dispc_init,
+	.cleanup		= omap_dispc_cleanup,
+	.get_caps		= omap_dispc_get_caps,
+	.set_update_mode	= omap_dispc_set_update_mode,
+	.get_update_mode	= omap_dispc_get_update_mode,
+	.update_window		= omap_dispc_update_window,
+	.suspend		= omap_dispc_suspend,
+	.resume			= omap_dispc_resume,
+	.setup_plane		= omap_dispc_setup_plane,
+	.setup_mem		= omap_dispc_setup_mem,
+	.set_scale		= omap_dispc_set_scale,
+	.enable_plane		= omap_dispc_enable_plane,
+	.set_color_key		= omap_dispc_set_color_key,
+	.get_color_key		= omap_dispc_get_color_key,
+	.mmap			= omap_dispc_mmap_user,
+};
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
new file mode 100644
index 0000000..eb1512b
--- /dev/null
+++ b/drivers/video/omap/dispc.h
@@ -0,0 +1,43 @@
+#ifndef _DISPC_H
+#define _DISPC_H
+
+#include <linux/interrupt.h>
+
+#define DISPC_PLANE_GFX			0
+#define DISPC_PLANE_VID1		1
+#define DISPC_PLANE_VID2		2
+
+#define DISPC_RGB_1_BPP			0x00
+#define DISPC_RGB_2_BPP			0x01
+#define DISPC_RGB_4_BPP			0x02
+#define DISPC_RGB_8_BPP			0x03
+#define DISPC_RGB_12_BPP		0x04
+#define DISPC_RGB_16_BPP		0x06
+#define DISPC_RGB_24_BPP		0x08
+#define DISPC_RGB_24_BPP_UNPACK_32	0x09
+#define DISPC_YUV2_422			0x0a
+#define DISPC_UYVY_422			0x0b
+
+#define DISPC_BURST_4x32		0
+#define DISPC_BURST_8x32		1
+#define DISPC_BURST_16x32		2
+
+#define DISPC_LOAD_CLUT_AND_FRAME	0x00
+#define DISPC_LOAD_CLUT_ONLY		0x01
+#define DISPC_LOAD_FRAME_ONLY		0x02
+#define DISPC_LOAD_CLUT_ONCE_FRAME	0x03
+
+#define DISPC_TFT_DATA_LINES_12		0
+#define DISPC_TFT_DATA_LINES_16		1
+#define DISPC_TFT_DATA_LINES_18		2
+#define DISPC_TFT_DATA_LINES_24		3
+
+extern void omap_dispc_set_lcd_size(int width, int height);
+
+extern void omap_dispc_enable_lcd_out(int enable);
+extern void omap_dispc_enable_digit_out(int enable);
+
+extern int  omap_dispc_request_irq(void (*callback)(void *data), void *data);
+extern void omap_dispc_free_irq(void);
+
+#endif
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
new file mode 100644
index 0000000..dc48e02
--- /dev/null
+++ b/drivers/video/omap/hwa742.c
@@ -0,0 +1,1077 @@
+/*
+ * Epson HWA742 LCD controller driver
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Authors:     Juha Yrjölä   <juha.yrjola@nokia.com>
+ *	        Imre Deak     <imre.deak@nokia.com>
+ * YUV support: Jussi Laako   <jussi.laako@nokia.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.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/hwa742.h>
+
+#define HWA742_REV_CODE_REG       0x0
+#define HWA742_CONFIG_REG         0x2
+#define HWA742_PLL_DIV_REG        0x4
+#define HWA742_PLL_0_REG          0x6
+#define HWA742_PLL_1_REG          0x8
+#define HWA742_PLL_2_REG          0xa
+#define HWA742_PLL_3_REG          0xc
+#define HWA742_PLL_4_REG          0xe
+#define HWA742_CLK_SRC_REG        0x12
+#define HWA742_PANEL_TYPE_REG     0x14
+#define HWA742_H_DISP_REG         0x16
+#define HWA742_H_NDP_REG          0x18
+#define HWA742_V_DISP_1_REG       0x1a
+#define HWA742_V_DISP_2_REG       0x1c
+#define HWA742_V_NDP_REG          0x1e
+#define HWA742_HS_W_REG           0x20
+#define HWA742_HP_S_REG           0x22
+#define HWA742_VS_W_REG           0x24
+#define HWA742_VP_S_REG           0x26
+#define HWA742_PCLK_POL_REG       0x28
+#define HWA742_INPUT_MODE_REG     0x2a
+#define HWA742_TRANSL_MODE_REG1   0x2e
+#define HWA742_DISP_MODE_REG      0x34
+#define HWA742_WINDOW_TYPE        0x36
+#define HWA742_WINDOW_X_START_0   0x38
+#define HWA742_WINDOW_X_START_1   0x3a
+#define HWA742_WINDOW_Y_START_0   0x3c
+#define HWA742_WINDOW_Y_START_1   0x3e
+#define HWA742_WINDOW_X_END_0     0x40
+#define HWA742_WINDOW_X_END_1     0x42
+#define HWA742_WINDOW_Y_END_0     0x44
+#define HWA742_WINDOW_Y_END_1     0x46
+#define HWA742_MEMORY_WRITE_LSB   0x48
+#define HWA742_MEMORY_WRITE_MSB   0x49
+#define HWA742_MEMORY_READ_0      0x4a
+#define HWA742_MEMORY_READ_1      0x4c
+#define HWA742_MEMORY_READ_2      0x4e
+#define HWA742_POWER_SAVE         0x56
+#define HWA742_NDP_CTRL           0x58
+
+#define HWA742_AUTO_UPDATE_TIME		(HZ / 20)
+
+/* Reserve 4 request slots for requests in irq context */
+#define REQ_POOL_SIZE			24
+#define IRQ_REQ_POOL_SIZE		4
+
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE	0
+#define REQ_PENDING	1
+
+struct update_param {
+	int	x, y, width, height;
+	int	color_mode;
+	int	flags;
+};
+
+struct hwa742_request {
+	struct list_head entry;
+	unsigned int	 flags;
+
+	int		 (*handler)(struct hwa742_request *req);
+	void		 (*complete)(void *data);
+	void		 *complete_data;
+
+	union {
+		struct update_param	update;
+		struct completion	*sync;
+	} par;
+};
+
+struct {
+	enum omapfb_update_mode	update_mode;
+	enum omapfb_update_mode	update_mode_before_suspend;
+
+	struct timer_list	auto_update_timer;
+	int			stop_auto_update;
+	struct omapfb_update_window	auto_update_window;
+	unsigned		te_connected:1;
+	unsigned		vsync_only:1;
+
+	struct hwa742_request	req_pool[REQ_POOL_SIZE];
+	struct list_head	pending_req_list;
+	struct list_head	free_req_list;
+	struct semaphore	req_sema;
+	spinlock_t		req_lock;
+
+	struct extif_timings	reg_timings, lut_timings;
+
+	int			prev_color_mode;
+	int			prev_flags;
+	int			window_type;
+
+	u32			max_transmit_size;
+	u32			extif_clk_period;
+	unsigned long		pix_tx_time;
+	unsigned long		line_upd_time;
+
+
+	struct omapfb_device	*fbdev;
+	struct lcd_ctrl_extif	*extif;
+	struct lcd_ctrl		*int_ctrl;
+
+	void			(*power_up)(struct device *dev);
+	void			(*power_down)(struct device *dev);
+} hwa742;
+
+struct lcd_ctrl hwa742_ctrl;
+
+static u8 hwa742_read_reg(u8 reg)
+{
+	u8 data;
+
+	hwa742.extif->set_bits_per_cycle(8);
+	hwa742.extif->write_command(&reg, 1);
+	hwa742.extif->read_data(&data, 1);
+
+	return data;
+}
+
+static void hwa742_write_reg(u8 reg, u8 data)
+{
+	hwa742.extif->set_bits_per_cycle(8);
+	hwa742.extif->write_command(&reg, 1);
+	hwa742.extif->write_data(&data, 1);
+}
+
+static void set_window_regs(int x_start, int y_start, int x_end, int y_end)
+{
+	u8 tmp[8];
+	u8 cmd;
+
+	x_end--;
+	y_end--;
+	tmp[0] = x_start;
+	tmp[1] = x_start >> 8;
+	tmp[2] = y_start;
+	tmp[3] = y_start >> 8;
+	tmp[4] = x_end;
+	tmp[5] = x_end >> 8;
+	tmp[6] = y_end;
+	tmp[7] = y_end >> 8;
+
+	hwa742.extif->set_bits_per_cycle(8);
+	cmd = HWA742_WINDOW_X_START_0;
+
+	hwa742.extif->write_command(&cmd, 1);
+
+	hwa742.extif->write_data(tmp, 8);
+}
+
+static void set_format_regs(int conv, int transl, int flags)
+{
+	if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
+		hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
+#ifdef VERBOSE
+		dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n");
+#endif
+	} else {
+		hwa742.window_type = (hwa742.window_type & 0xfc);
+#ifdef VERBOSE
+		dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n");
+#endif
+	}
+
+	hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
+	hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl);
+	hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type);
+}
+
+static void enable_tearsync(int y, int width, int height, int screen_height,
+			    int force_vsync)
+{
+	u8 b;
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b |= 1 << 2;
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+	if (likely(hwa742.vsync_only || force_vsync)) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if (width * hwa742.pix_tx_time < hwa742.line_upd_time) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if ((width * hwa742.pix_tx_time / 1000) * height <
+	    (y + height) * (hwa742.line_upd_time / 1000)) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	hwa742.extif->enable_tearsync(1, y + 1);
+}
+
+static void disable_tearsync(void)
+{
+	u8 b;
+
+	hwa742.extif->enable_tearsync(0, 0);
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b &= ~(1 << 2);
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+}
+
+static inline struct hwa742_request *alloc_req(void)
+{
+	unsigned long flags;
+	struct hwa742_request *req;
+	int req_flags = 0;
+
+	if (!in_interrupt())
+		down(&hwa742.req_sema);
+	else
+		req_flags = REQ_FROM_IRQ_POOL;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+	BUG_ON(list_empty(&hwa742.free_req_list));
+	req = list_entry(hwa742.free_req_list.next,
+			 struct hwa742_request, entry);
+	list_del(&req->entry);
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+	INIT_LIST_HEAD(&req->entry);
+	req->flags = req_flags;
+
+	return req;
+}
+
+static inline void free_req(struct hwa742_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+
+	list_del(&req->entry);
+	list_add(&req->entry, &hwa742.free_req_list);
+	if (!(req->flags & REQ_FROM_IRQ_POOL))
+		up(&hwa742.req_sema);
+
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void process_pending_requests(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+
+	while (!list_empty(&hwa742.pending_req_list)) {
+		struct hwa742_request *req;
+		void (*complete)(void *);
+		void *complete_data;
+
+		req = list_entry(hwa742.pending_req_list.next,
+				 struct hwa742_request, entry);
+		spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+		if (req->handler(req) == REQ_PENDING)
+			return;
+
+		complete = req->complete;
+		complete_data = req->complete_data;
+		free_req(req);
+
+		if (complete)
+			complete(complete_data);
+
+		spin_lock_irqsave(&hwa742.req_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void submit_req_list(struct list_head *head)
+{
+	unsigned long flags;
+	int process = 1;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+	if (likely(!list_empty(&hwa742.pending_req_list)))
+		process = 0;
+	list_splice_init(head, hwa742.pending_req_list.prev);
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+	if (process)
+		process_pending_requests();
+}
+
+static void request_complete(void *data)
+{
+	struct hwa742_request	*req = (struct hwa742_request *)data;
+	void			(*complete)(void *);
+	void			*complete_data;
+
+	complete = req->complete;
+	complete_data = req->complete_data;
+
+	free_req(req);
+
+	if (complete)
+		complete(complete_data);
+
+	process_pending_requests();
+}
+
+static int send_frame_handler(struct hwa742_request *req)
+{
+	struct update_param *par = &req->par.update;
+	int x = par->x;
+	int y = par->y;
+	int w = par->width;
+	int h = par->height;
+	int bpp;
+	int conv, transl;
+	unsigned long offset;
+	int color_mode = par->color_mode;
+	int flags = par->flags;
+	int scr_width = hwa742.fbdev->panel->x_res;
+	int scr_height = hwa742.fbdev->panel->y_res;
+
+#ifdef VERBOSE
+	dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d "
+		"color_mode %d flags %d\n",
+		x, y, w, h, scr_width, color_mode, flags);
+#endif
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_YUV422:
+		bpp = 16;
+		conv = 0x08;
+		transl = 0x25;
+		break;
+	case OMAPFB_COLOR_YUV420:
+		bpp = 12;
+		conv = 0x09;
+		transl = 0x25;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		bpp = 16;
+		conv = 0x01;
+		transl = 0x05;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (hwa742.prev_flags != flags ||
+	    hwa742.prev_color_mode != color_mode) {
+		set_format_regs(conv, transl, flags);
+		hwa742.prev_color_mode = color_mode;
+		hwa742.prev_flags = flags;
+	}
+	flags = req->par.update.flags;
+	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+		enable_tearsync(y, scr_width, h, scr_height,
+				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+	else
+		disable_tearsync();
+
+	set_window_regs(x, y, x + w, y + h);
+
+	offset = (scr_width * y + x) * bpp / 8;
+
+	hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX,
+			OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h,
+			color_mode);
+
+	hwa742.extif->set_bits_per_cycle(16);
+
+	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+	hwa742.extif->transfer_area(w, h, request_complete, req);
+
+	return REQ_PENDING;
+}
+
+static void send_frame_complete(void *data)
+{
+	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
+}
+
+#define ADD_PREQ(_x, _y, _w, _h) do {		\
+	req = alloc_req();			\
+	req->handler	= send_frame_handler;	\
+	req->complete	= send_frame_complete;	\
+	req->par.update.x = _x;			\
+	req->par.update.y = _y;			\
+	req->par.update.width  = _w;		\
+	req->par.update.height = _h;		\
+	req->par.update.color_mode = color_mode;\
+	req->par.update.flags	  = flags;	\
+	list_add_tail(&req->entry, req_head);	\
+} while(0)
+
+static void create_req_list(struct omapfb_update_window *win,
+			    struct list_head *req_head)
+{
+	struct hwa742_request *req;
+	int x = win->x;
+	int y = win->y;
+	int width = win->width;
+	int height = win->height;
+	int color_mode;
+	int flags;
+
+	flags = win->format & ~OMAPFB_FORMAT_MASK;
+	color_mode = win->format & OMAPFB_FORMAT_MASK;
+
+	if (x & 1) {
+		ADD_PREQ(x, y, 1, height);
+		width--;
+		x++;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+	if (width & ~1) {
+		unsigned int xspan = width & ~1;
+		unsigned int ystart = y;
+		unsigned int yspan = height;
+
+		if (xspan * height * 2 > hwa742.max_transmit_size) {
+			yspan = hwa742.max_transmit_size / (xspan * 2);
+			ADD_PREQ(x, ystart, xspan, yspan);
+			ystart += yspan;
+			yspan = height - yspan;
+			flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+		}
+
+		ADD_PREQ(x, ystart, xspan, yspan);
+		x += xspan;
+		width -= xspan;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+	if (width)
+		ADD_PREQ(x, y, 1, height);
+}
+
+static void auto_update_complete(void *data)
+{
+	if (!hwa742.stop_auto_update)
+		mod_timer(&hwa742.auto_update_timer,
+			  jiffies + HWA742_AUTO_UPDATE_TIME);
+}
+
+static void hwa742_update_window_auto(unsigned long arg)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *last;
+
+	create_req_list(&hwa742.auto_update_window, &req_list);
+	last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+	last->complete = auto_update_complete;
+	last->complete_data = NULL;
+
+	submit_req_list(&req_list);
+}
+
+int hwa742_update_window_async(struct fb_info *fbi,
+				 struct omapfb_update_window *win,
+				 void (*complete_callback)(void *arg),
+				 void *complete_callback_data)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *last;
+	int r = 0;
+
+	if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
+		dev_dbg(hwa742.fbdev->dev, "invalid update mode\n");
+		r = -EINVAL;
+		goto out;
+	}
+	if (unlikely(win->format &
+	    ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE |
+	    OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) {
+		dev_dbg(hwa742.fbdev->dev, "invalid window flag");
+		r = -EINVAL;
+		goto out;
+	}
+
+	create_req_list(win, &req_list);
+	last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+	last->complete = complete_callback;
+	last->complete_data = (void *)complete_callback_data;
+
+	submit_req_list(&req_list);
+
+out:
+	return r;
+}
+EXPORT_SYMBOL(hwa742_update_window_async);
+
+static int hwa742_setup_plane(int plane, int channel_out,
+				  unsigned long offset, int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	if (plane != OMAPFB_PLANE_GFX ||
+	    channel_out != OMAPFB_CHANNEL_OUT_LCD)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int hwa742_enable_plane(int plane, int enable)
+{
+	if (plane != 0)
+		return -EINVAL;
+
+	hwa742.int_ctrl->enable_plane(plane, enable);
+
+	return 0;
+}
+
+static int sync_handler(struct hwa742_request *req)
+{
+	complete(req->par.sync);
+	return REQ_COMPLETE;
+}
+
+static void hwa742_sync(void)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *req;
+	struct completion comp;
+
+	req = alloc_req();
+
+	req->handler = sync_handler;
+	req->complete = NULL;
+	init_completion(&comp);
+	req->par.sync = &comp;
+
+	list_add(&req->entry, &req_list);
+	submit_req_list(&req_list);
+
+	wait_for_completion(&comp);
+}
+
+static void hwa742_bind_client(struct omapfb_notifier_block *nb)
+{
+	dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode);
+	if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+	}
+}
+
+static int hwa742_set_update_mode(enum omapfb_update_mode mode)
+{
+	if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
+	    mode != OMAPFB_UPDATE_DISABLED)
+		return -EINVAL;
+
+	if (mode == hwa742.update_mode)
+		return 0;
+
+	dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n",
+			mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
+			(mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
+
+	switch (hwa742.update_mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		hwa742.stop_auto_update = 1;
+		del_timer_sync(&hwa742.auto_update_timer);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	hwa742.update_mode = mode;
+	hwa742_sync();
+	hwa742.stop_auto_update = 0;
+
+	switch (mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		hwa742_update_window_auto(0);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	return 0;
+}
+
+static enum omapfb_update_mode hwa742_get_update_mode(void)
+{
+	return hwa742.update_mode;
+}
+
+static unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+	int bus_tick = hwa742.extif_clk_period * div;
+	return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 12.2 ns (regs),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 16 ns (regs),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 2*SYSCLK  (regs),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns */
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+	t = &hwa742.reg_timings;
+	memset(t, 0, sizeof(*t));
+	t->clk_div = div;
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return hwa742.extif->convert_timings(t);
+}
+
+static int calc_lut_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns
+	 */
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+	t = &hwa742.lut_timings;
+	memset(t, 0, sizeof(*t));
+
+	t->clk_div = div;
+
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return hwa742.extif->convert_timings(t);
+}
+
+static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
+{
+	int max_clk_div;
+	int div;
+
+	hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div);
+	for (div = 1; div < max_clk_div; div++) {
+		if (calc_reg_timing(sysclk, div) == 0)
+			break;
+	}
+	if (div > max_clk_div)
+		goto err;
+
+	*extif_mem_div = div;
+
+	for (div = 1; div < max_clk_div; div++) {
+		if (calc_lut_timing(sysclk, div) == 0)
+			break;
+	}
+
+	if (div > max_clk_div)
+		goto err;
+
+	return 0;
+
+err:
+	dev_err(hwa742.fbdev->dev, "can't setup timings\n");
+	return -1;
+}
+
+static void calc_hwa742_clk_rates(unsigned long ext_clk,
+				unsigned long *sys_clk, unsigned long *pix_clk)
+{
+	int pix_clk_src;
+	int sys_div = 0, sys_mul = 0;
+	int pix_div;
+
+	pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG);
+	pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
+	if ((pix_clk_src & (0x3 << 1)) == 0) {
+		/* Source is the PLL */
+		sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1;
+		sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1;
+		*sys_clk = ext_clk * sys_mul / sys_div;
+	} else	/* else source is ext clk, or oscillator */
+		*sys_clk = ext_clk;
+
+	*pix_clk = *sys_clk / pix_div;			/* HZ */
+	dev_dbg(hwa742.fbdev->dev,
+		"ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
+		ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
+	dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
+		*sys_clk, *pix_clk);
+}
+
+
+static int setup_tearsync(unsigned long pix_clk, int extif_div)
+{
+	int hdisp, vdisp;
+	int hndp, vndp;
+	int hsw, vsw;
+	int hs, vs;
+	int hs_pol_inv, vs_pol_inv;
+	int use_hsvs, use_ndp;
+	u8  b;
+
+	hsw = hwa742_read_reg(HWA742_HS_W_REG);
+	vsw = hwa742_read_reg(HWA742_VS_W_REG);
+	hs_pol_inv = !(hsw & 0x80);
+	vs_pol_inv = !(vsw & 0x80);
+	hsw = hsw & 0x7f;
+	vsw = vsw & 0x3f;
+
+	hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8;
+	vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) +
+		((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8);
+
+	hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f;
+	vndp = hwa742_read_reg(HWA742_V_NDP_REG);
+
+	/* time to transfer one pixel (16bpp) in ps */
+	hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time;
+	if (hwa742.extif->get_max_tx_rate != NULL) {
+		/*
+		 * The external interface might have a rate limitation,
+		 * if so, we have to maximize our transfer rate.
+		 */
+		unsigned long min_tx_time;
+		unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate();
+
+		dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n",
+			max_tx_rate);
+		min_tx_time = 1000000000 / (max_tx_rate / 1000);  /* ps */
+		if (hwa742.pix_tx_time < min_tx_time)
+			hwa742.pix_tx_time = min_tx_time;
+	}
+
+	/* time to update one line in ps */
+	hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
+	hwa742.line_upd_time *= 1000;
+	if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time)
+		/*
+		 * transfer speed too low, we might have to use both
+		 * HS and VS
+		 */
+		use_hsvs = 1;
+	else
+		/* decent transfer speed, we'll always use only VS */
+		use_hsvs = 0;
+
+	if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
+		/*
+		 * HS or'ed with VS doesn't work, use the active high
+		 * TE signal based on HNDP / VNDP
+		 */
+		use_ndp = 1;
+		hs_pol_inv = 0;
+		vs_pol_inv = 0;
+		hs = hndp;
+		vs = vndp;
+	} else {
+		/*
+		 * Use HS or'ed with VS as a TE signal if both are needed
+		 * or VNDP if only vsync is needed.
+		 */
+		use_ndp = 0;
+		hs = hsw;
+		vs = vsw;
+		if (!use_hsvs) {
+			hs_pol_inv = 0;
+			vs_pol_inv = 0;
+		}
+	}
+
+	hs = hs * 1000000 / (pix_clk / 1000);			/* ps */
+	hs *= 1000;
+
+	vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000);	/* ps */
+	vs *= 1000;
+
+	if (vs <= hs)
+		return -EDOM;
+	/* set VS to 120% of HS to minimize VS detection time */
+	vs = hs * 12 / 10;
+	/* minimize HS too */
+	hs = 10000;
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b &= ~0x3;
+	b |= use_hsvs ? 1 : 0;
+	b |= (use_ndp && use_hsvs) ? 0 : 2;
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+	hwa742.vsync_only = !use_hsvs;
+
+	dev_dbg(hwa742.fbdev->dev,
+		"pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
+		pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time);
+	dev_dbg(hwa742.fbdev->dev,
+		"hs %d ps vs %d ps mode %d vsync_only %d\n",
+		hs, vs, (b & 0x3), !use_hsvs);
+
+	return hwa742.extif->setup_tearsync(1, hs, vs,
+					    hs_pol_inv, vs_pol_inv, extif_div);
+}
+
+static void hwa742_get_caps(int plane, struct omapfb_caps *caps)
+{
+	hwa742.int_ctrl->get_caps(plane, caps);
+	caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
+		      OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE;
+	if (hwa742.te_connected)
+		caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
+	caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
+			   (1 << OMAPFB_COLOR_YUV420);
+}
+
+static void hwa742_suspend(void)
+{
+	hwa742.update_mode_before_suspend = hwa742.update_mode;
+	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	/* Enable sleep mode */
+	hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1);
+	if (hwa742.power_down != NULL)
+		hwa742.power_down(hwa742.fbdev->dev);
+}
+
+static void hwa742_resume(void)
+{
+	if (hwa742.power_up != NULL)
+		hwa742.power_up(hwa742.fbdev->dev);
+	/* Disable sleep mode */
+	hwa742_write_reg(HWA742_POWER_SAVE, 0);
+	while (1) {
+		/* Loop until PLL output is stabilized */
+		if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7))
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(msecs_to_jiffies(5));
+	}
+	hwa742_set_update_mode(hwa742.update_mode_before_suspend);
+}
+
+static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
+		       struct omapfb_mem_desc *req_vram)
+{
+	int r = 0, i;
+	u8 rev, conf;
+	unsigned long ext_clk;
+	unsigned long sys_clk, pix_clk;
+	int extif_mem_div;
+	struct omapfb_platform_data *omapfb_conf;
+	struct hwa742_platform_data *ctrl_conf;
+
+	BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
+
+	hwa742.fbdev = fbdev;
+	hwa742.extif = fbdev->ext_if;
+	hwa742.int_ctrl = fbdev->int_ctrl;
+
+	omapfb_conf = fbdev->dev->platform_data;
+	ctrl_conf = omapfb_conf->ctrl_platform_data;
+
+	if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
+		dev_err(fbdev->dev, "HWA742: missing platform data\n");
+		r = -ENOENT;
+		goto err1;
+	}
+
+	hwa742.power_down = ctrl_conf->power_down;
+	hwa742.power_up = ctrl_conf->power_up;
+
+	spin_lock_init(&hwa742.req_lock);
+
+	if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0)
+		goto err1;
+
+	if ((r = hwa742.extif->init(fbdev)) < 0)
+		goto err2;
+
+	ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
+	if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
+		goto err3;
+	hwa742.extif->set_timings(&hwa742.reg_timings);
+	if (hwa742.power_up != NULL)
+		hwa742.power_up(fbdev->dev);
+
+	calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
+	if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
+		goto err4;
+	hwa742.extif->set_timings(&hwa742.reg_timings);
+
+	rev = hwa742_read_reg(HWA742_REV_CODE_REG);
+	if ((rev & 0xfc) != 0x80) {
+		dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev);
+		r = -ENODEV;
+		goto err4;
+	}
+
+
+	if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
+		dev_err(fbdev->dev,
+		      "HWA742: controller not initialized by the bootloader\n");
+		r = -ENODEV;
+		goto err4;
+	}
+
+	if (ctrl_conf->te_connected) {
+		if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
+			dev_err(hwa742.fbdev->dev,
+			       "HWA742: can't setup tearing synchronization\n");
+			goto err4;
+		}
+		hwa742.te_connected = 1;
+	}
+
+	hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
+
+	hwa742.update_mode = OMAPFB_UPDATE_DISABLED;
+
+	hwa742.auto_update_window.x = 0;
+	hwa742.auto_update_window.y = 0;
+	hwa742.auto_update_window.width = fbdev->panel->x_res;
+	hwa742.auto_update_window.height = fbdev->panel->y_res;
+	hwa742.auto_update_window.format = 0;
+
+	init_timer(&hwa742.auto_update_timer);
+	hwa742.auto_update_timer.function = hwa742_update_window_auto;
+	hwa742.auto_update_timer.data = 0;
+
+	hwa742.prev_color_mode = -1;
+	hwa742.prev_flags = 0;
+
+	hwa742.fbdev = fbdev;
+
+	INIT_LIST_HEAD(&hwa742.free_req_list);
+	INIT_LIST_HEAD(&hwa742.pending_req_list);
+	for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
+		list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list);
+	BUG_ON(i <= IRQ_REQ_POOL_SIZE);
+	sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
+
+	conf = hwa742_read_reg(HWA742_CONFIG_REG);
+	dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+
+	return 0;
+err4:
+	if (hwa742.power_down != NULL)
+		hwa742.power_down(fbdev->dev);
+err3:
+	hwa742.extif->cleanup();
+err2:
+	hwa742.int_ctrl->cleanup();
+err1:
+	return r;
+}
+
+static void hwa742_cleanup(void)
+{
+	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	hwa742.extif->cleanup();
+	hwa742.int_ctrl->cleanup();
+	if (hwa742.power_down != NULL)
+		hwa742.power_down(hwa742.fbdev->dev);
+}
+
+struct lcd_ctrl hwa742_ctrl = {
+	.name			= "hwa742",
+	.init			= hwa742_init,
+	.cleanup		= hwa742_cleanup,
+	.bind_client		= hwa742_bind_client,
+	.get_caps		= hwa742_get_caps,
+	.set_update_mode	= hwa742_set_update_mode,
+	.get_update_mode	= hwa742_get_update_mode,
+	.setup_plane		= hwa742_setup_plane,
+	.enable_plane		= hwa742_enable_plane,
+	.update_window		= hwa742_update_window_async,
+	.sync			= hwa742_sync,
+	.suspend		= hwa742_suspend,
+	.resume			= hwa742_resume,
+};
+
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
new file mode 100644
index 0000000..51807b4
--- /dev/null
+++ b/drivers/video/omap/lcd_h3.c
@@ -0,0 +1,141 @@
+/*
+ * LCD panel support for the TI OMAP H3 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME	"omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void h3_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int h3_panel_enable(struct lcd_panel *panel)
+{
+	int r = 0;
+
+	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+	r = tps65010_set_gpio_out_value(GPIO1, HIGH);
+	if (!r)
+		r = tps65010_set_gpio_out_value(GPIO2, HIGH);
+	if (r)
+		pr_err("Unable to turn on LCD panel\n");
+
+	return r;
+}
+
+static void h3_panel_disable(struct lcd_panel *panel)
+{
+	int r = 0;
+
+	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+	r = tps65010_set_gpio_out_value(GPIO1, LOW);
+	if (!r)
+		tps65010_set_gpio_out_value(GPIO2, LOW);
+	if (r)
+		pr_err("Unable to turn off LCD panel\n");
+}
+
+static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel h3_panel = {
+	.name		= "h3",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.data_lines	= 16,
+	.bpp		= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12000,
+	.hsw		= 12,
+	.hfp		= 14,
+	.hbp		= 72 - 12,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 0,
+
+	.init		= h3_panel_init,
+	.cleanup	= h3_panel_cleanup,
+	.enable		= h3_panel_enable,
+	.disable	= h3_panel_disable,
+	.get_caps	= h3_panel_get_caps,
+};
+
+static int h3_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&h3_panel);
+	return 0;
+}
+
+static int h3_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int h3_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int h3_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver h3_panel_driver = {
+	.probe		= h3_panel_probe,
+	.remove		= h3_panel_remove,
+	.suspend	= h3_panel_suspend,
+	.resume		= h3_panel_resume,
+	.driver		= {
+		.name	= "lcd_h3",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int h3_panel_drv_init(void)
+{
+	return platform_driver_register(&h3_panel_driver);
+}
+
+static void h3_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&h3_panel_driver);
+}
+
+module_init(h3_panel_drv_init);
+module_exit(h3_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
new file mode 100644
index 0000000..fd6f0eb
--- /dev/null
+++ b/drivers/video/omap/lcd_h4.c
@@ -0,0 +1,117 @@
+/*
+ * LCD panel support for the TI OMAP H4 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/omapfb.h>
+
+static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void h4_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int h4_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void h4_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel h4_panel = {
+	.name		= "h4",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 6250,
+	.hsw		= 15,
+	.hfp		= 15,
+	.hbp		= 60,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 1,
+
+	.init		= h4_panel_init,
+	.cleanup	= h4_panel_cleanup,
+	.enable		= h4_panel_enable,
+	.disable	= h4_panel_disable,
+	.get_caps	= h4_panel_get_caps,
+};
+
+static int h4_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&h4_panel);
+	return 0;
+}
+
+static int h4_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int h4_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver h4_panel_driver = {
+	.probe		= h4_panel_probe,
+	.remove		= h4_panel_remove,
+	.suspend	= h4_panel_suspend,
+	.resume		= h4_panel_resume,
+	.driver		= {
+		.name	= "lcd_h4",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int h4_panel_drv_init(void)
+{
+	return platform_driver_register(&h4_panel_driver);
+}
+
+static void h4_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&h4_panel_driver);
+}
+
+module_init(h4_panel_drv_init);
+module_exit(h4_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
new file mode 100644
index 0000000..551f385
--- /dev/null
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -0,0 +1,124 @@
+/*
+ * LCD panel support for the TI OMAP1510 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/omapfb.h>
+
+static int innovator1510_panel_init(struct lcd_panel *panel,
+				    struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void innovator1510_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int innovator1510_panel_enable(struct lcd_panel *panel)
+{
+	fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+	return 0;
+}
+
+static void innovator1510_panel_disable(struct lcd_panel *panel)
+{
+	fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+}
+
+static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel innovator1510_panel = {
+	.name		= "inn1510",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= innovator1510_panel_init,
+	.cleanup	= innovator1510_panel_cleanup,
+	.enable		= innovator1510_panel_enable,
+	.disable	= innovator1510_panel_disable,
+	.get_caps	= innovator1510_panel_get_caps,
+};
+
+static int innovator1510_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&innovator1510_panel);
+	return 0;
+}
+
+static int innovator1510_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int innovator1510_panel_suspend(struct platform_device *pdev,
+				       pm_message_t mesg)
+{
+	return 0;
+}
+
+static int innovator1510_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver innovator1510_panel_driver = {
+	.probe		= innovator1510_panel_probe,
+	.remove		= innovator1510_panel_remove,
+	.suspend	= innovator1510_panel_suspend,
+	.resume		= innovator1510_panel_resume,
+	.driver		= {
+		.name	= "lcd_inn1510",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int innovator1510_panel_drv_init(void)
+{
+	return platform_driver_register(&innovator1510_panel_driver);
+}
+
+static void innovator1510_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&innovator1510_panel_driver);
+}
+
+module_init(innovator1510_panel_drv_init);
+module_exit(innovator1510_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
new file mode 100644
index 0000000..95604ca
--- /dev/null
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -0,0 +1,150 @@
+/*
+ * LCD panel support for the TI OMAP1610 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME	"omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int innovator1610_panel_init(struct lcd_panel *panel,
+				    struct omapfb_device *fbdev)
+{
+	int r = 0;
+
+	if (omap_request_gpio(14)) {
+		pr_err("can't request GPIO 14\n");
+		r = -1;
+		goto exit;
+	}
+	if (omap_request_gpio(15)) {
+		pr_err("can't request GPIO 15\n");
+		omap_free_gpio(14);
+		r = -1;
+		goto exit;
+	}
+	/* configure GPIO(14, 15) as outputs */
+	omap_set_gpio_direction(14, 0);
+	omap_set_gpio_direction(15, 0);
+exit:
+	return r;
+}
+
+static void innovator1610_panel_cleanup(struct lcd_panel *panel)
+{
+	omap_free_gpio(15);
+	omap_free_gpio(14);
+}
+
+static int innovator1610_panel_enable(struct lcd_panel *panel)
+{
+	/* set GPIO14 and GPIO15 high */
+	omap_set_gpio_dataout(14, 1);
+	omap_set_gpio_dataout(15, 1);
+	return 0;
+}
+
+static void innovator1610_panel_disable(struct lcd_panel *panel)
+{
+	/* set GPIO13, GPIO14 and GPIO15 low */
+	omap_set_gpio_dataout(14, 0);
+	omap_set_gpio_dataout(15, 0);
+}
+
+static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel innovator1610_panel = {
+	.name		= "inn1610",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 320,
+	.y_res		= 240,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= innovator1610_panel_init,
+	.cleanup	= innovator1610_panel_cleanup,
+	.enable		= innovator1610_panel_enable,
+	.disable	= innovator1610_panel_disable,
+	.get_caps	= innovator1610_panel_get_caps,
+};
+
+static int innovator1610_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&innovator1610_panel);
+	return 0;
+}
+
+static int innovator1610_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int innovator1610_panel_suspend(struct platform_device *pdev,
+				       pm_message_t mesg)
+{
+	return 0;
+}
+
+static int innovator1610_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver innovator1610_panel_driver = {
+	.probe		= innovator1610_panel_probe,
+	.remove		= innovator1610_panel_remove,
+	.suspend	= innovator1610_panel_suspend,
+	.resume		= innovator1610_panel_resume,
+	.driver		= {
+		.name	= "lcd_inn1610",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int innovator1610_panel_drv_init(void)
+{
+	return platform_driver_register(&innovator1610_panel_driver);
+}
+
+static void innovator1610_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&innovator1610_panel_driver);
+}
+
+module_init(innovator1610_panel_drv_init);
+module_exit(innovator1610_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
new file mode 100644
index 0000000..a380388
--- /dev/null
+++ b/drivers/video/omap/lcd_osk.c
@@ -0,0 +1,144 @@
+/*
+ * LCD panel support for the TI OMAP OSK board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ * Adapted for OSK by <dirk.behme@de.bosch.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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
+
+static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void osk_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int osk_panel_enable(struct lcd_panel *panel)
+{
+	/* configure PWL pin */
+	omap_cfg_reg(PWL);
+
+	/* Enable PWL unit */
+	omap_writeb(0x01, OMAP_PWL_CLK_ENABLE);
+
+	/* Set PWL level */
+	omap_writeb(0xFF, OMAP_PWL_ENABLE);
+
+	/* configure GPIO2 as output */
+	omap_set_gpio_direction(2, 0);
+
+	/* set GPIO2 high */
+	omap_set_gpio_dataout(2, 1);
+
+	return 0;
+}
+
+static void osk_panel_disable(struct lcd_panel *panel)
+{
+	/* Set PWL level to zero */
+	omap_writeb(0x00, OMAP_PWL_ENABLE);
+
+	/* Disable PWL unit */
+	omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
+
+	/* set GPIO2 low */
+	omap_set_gpio_dataout(2, 0);
+}
+
+static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel osk_panel = {
+	.name		= "osk",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= osk_panel_init,
+	.cleanup	= osk_panel_cleanup,
+	.enable		= osk_panel_enable,
+	.disable	= osk_panel_disable,
+	.get_caps	= osk_panel_get_caps,
+};
+
+static int osk_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&osk_panel);
+	return 0;
+}
+
+static int osk_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int osk_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int osk_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver osk_panel_driver = {
+	.probe		= osk_panel_probe,
+	.remove		= osk_panel_remove,
+	.suspend	= osk_panel_suspend,
+	.resume		= osk_panel_resume,
+	.driver		= {
+		.name	= "lcd_osk",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int osk_panel_drv_init(void)
+{
+	return platform_driver_register(&osk_panel_driver);
+}
+
+static void osk_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&osk_panel_driver);
+}
+
+module_init(osk_panel_drv_init);
+module_exit(osk_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
new file mode 100644
index 0000000..52bdfda
--- /dev/null
+++ b/drivers/video/omap/lcd_palmte.c
@@ -0,0 +1,123 @@
+/*
+ * LCD panel support for the Palm Tungsten E
+ *
+ * Original version : Romain Goyet <r.goyet@gmail.com>
+ * Current version : Laurent Gonzalez <palmte.linux@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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 <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/omapfb.h>
+
+static int palmte_panel_init(struct lcd_panel *panel,
+				struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmte_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmte_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmte_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmte_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel palmte_panel = {
+	.name		= "palmte",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			  OMAP_LCDC_HSVS_OPPOSITE,
+
+	.data_lines	= 16,
+	.bpp		= 8,
+	.pixel_clock	= 12000,
+	.x_res		= 320,
+	.y_res		= 320,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmte_panel_init,
+	.cleanup	= palmte_panel_cleanup,
+	.enable		= palmte_panel_enable,
+	.disable	= palmte_panel_disable,
+	.get_caps	= palmte_panel_get_caps,
+};
+
+static int palmte_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmte_panel);
+	return 0;
+}
+
+static int palmte_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmte_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmte_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver palmte_panel_driver = {
+	.probe		= palmte_panel_probe,
+	.remove		= palmte_panel_remove,
+	.suspend	= palmte_panel_suspend,
+	.resume		= palmte_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmte",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int palmte_panel_drv_init(void)
+{
+	return platform_driver_register(&palmte_panel_driver);
+}
+
+static void palmte_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&palmte_panel_driver);
+}
+
+module_init(palmte_panel_drv_init);
+module_exit(palmte_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
new file mode 100644
index 0000000..4bb349f
--- /dev/null
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -0,0 +1,127 @@
+/*
+ * LCD panel support for Palm Tungsten|T
+ * Current version : Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Modified from lcd_inn1510.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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.
+ */
+
+/*
+GPIO11 - backlight
+GPIO12 - screen blanking
+GPIO13 - screen blanking
+*/
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+static int palmtt_panel_init(struct lcd_panel *panel,
+	struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmtt_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmtt_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmtt_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmtt_panel_get_caps(struct lcd_panel *panel)
+{
+	return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmtt_panel = {
+	.name		= "palmtt",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			OMAP_LCDC_HSVS_OPPOSITE,
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 320,
+	.y_res		= 320,
+	.pixel_clock	= 10000,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmtt_panel_init,
+	.cleanup	= palmtt_panel_cleanup,
+	.enable		= palmtt_panel_enable,
+	.disable	= palmtt_panel_disable,
+	.get_caps	= palmtt_panel_get_caps,
+};
+
+static int palmtt_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmtt_panel);
+	return 0;
+}
+
+static int palmtt_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmtt_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmtt_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver palmtt_panel_driver = {
+	.probe		= palmtt_panel_probe,
+	.remove		= palmtt_panel_remove,
+	.suspend	= palmtt_panel_suspend,
+	.resume		= palmtt_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmtt",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int palmtt_panel_drv_init(void)
+{
+	return platform_driver_register(&palmtt_panel_driver);
+}
+
+static void palmtt_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&palmtt_panel_driver);
+}
+
+module_init(palmtt_panel_drv_init);
+module_exit(palmtt_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
new file mode 100644
index 0000000..ea6170d
--- /dev/null
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -0,0 +1,123 @@
+/*
+ * LCD panel support for the Palm Zire71
+ *
+ * Original version : Romain Goyet
+ * Current version : Laurent Gonzalez
+ * Modified for zire71 : Marek Vasut
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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 <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/omapfb.h>
+
+static int palmz71_panel_init(struct lcd_panel *panel,
+			      struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmz71_panel_cleanup(struct lcd_panel *panel)
+{
+
+}
+
+static int palmz71_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmz71_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmz71_panel_get_caps(struct lcd_panel *panel)
+{
+	return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmz71_panel = {
+	.name		= "palmz71",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			  OMAP_LCDC_HSVS_OPPOSITE,
+	.data_lines	= 16,
+	.bpp		= 16,
+	.pixel_clock	= 24000,
+	.x_res		= 320,
+	.y_res		= 320,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmz71_panel_init,
+	.cleanup	= palmz71_panel_cleanup,
+	.enable		= palmz71_panel_enable,
+	.disable	= palmz71_panel_disable,
+	.get_caps	= palmz71_panel_get_caps,
+};
+
+static int palmz71_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmz71_panel);
+	return 0;
+}
+
+static int palmz71_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmz71_panel_suspend(struct platform_device *pdev,
+				 pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmz71_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver palmz71_panel_driver = {
+	.probe		= palmz71_panel_probe,
+	.remove		= palmz71_panel_remove,
+	.suspend	= palmz71_panel_suspend,
+	.resume		= palmz71_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmz71",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int palmz71_panel_drv_init(void)
+{
+	return platform_driver_register(&palmz71_panel_driver);
+}
+
+static void palmz71_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&palmz71_panel_driver);
+}
+
+module_init(palmz71_panel_drv_init);
+module_exit(palmz71_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c
new file mode 100644
index 0000000..c4f306a
--- /dev/null
+++ b/drivers/video/omap/lcd_sx1.c
@@ -0,0 +1,334 @@
+/*
+ * LCD panel support for the Siemens SX1 mobile phone
+ *
+ * Current version : Vovan888@gmail.com, great help from FCA00000
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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 <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/mux.h>
+
+/*
+ * OMAP310 GPIO registers
+ */
+#define GPIO_DATA_INPUT		0xfffce000
+#define GPIO_DATA_OUTPUT	0xfffce004
+#define GPIO_DIR_CONTROL	0xfffce008
+#define GPIO_INT_CONTROL	0xfffce00c
+#define GPIO_INT_MASK		0xfffce010
+#define GPIO_INT_STATUS		0xfffce014
+#define GPIO_PIN_CONTROL	0xfffce018
+
+
+#define A_LCD_SSC_RD	3
+#define A_LCD_SSC_SD	7
+#define _A_LCD_RESET	9
+#define _A_LCD_SSC_CS	12
+#define _A_LCD_SSC_A0	13
+
+#define DSP_REG		0xE1017024
+
+const unsigned char INIT_1[12] = {
+	0x1C, 0x02, 0x88, 0x00, 0x1E, 0xE0, 0x00, 0xDC, 0x00, 0x02, 0x00
+};
+
+const unsigned char INIT_2[127] = {
+	0x15, 0x00, 0x29, 0x00, 0x3E, 0x00, 0x51, 0x00,
+	0x65, 0x00, 0x7A, 0x00, 0x8D, 0x00, 0xA1, 0x00,
+	0xB6, 0x00, 0xC7, 0x00, 0xD8, 0x00, 0xEB, 0x00,
+	0xFB, 0x00, 0x0B, 0x01, 0x1B, 0x01, 0x27, 0x01,
+	0x34, 0x01, 0x41, 0x01, 0x4C, 0x01, 0x55, 0x01,
+	0x5F, 0x01, 0x68, 0x01, 0x70, 0x01, 0x78, 0x01,
+	0x7E, 0x01, 0x86, 0x01, 0x8C, 0x01, 0x94, 0x01,
+	0x9B, 0x01, 0xA1, 0x01, 0xA4, 0x01, 0xA9, 0x01,
+	0xAD, 0x01, 0xB2, 0x01, 0xB7, 0x01, 0xBC, 0x01,
+	0xC0, 0x01, 0xC4, 0x01, 0xC8, 0x01, 0xCB, 0x01,
+	0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01,
+	0xDB, 0x01, 0xE0, 0x01, 0xE3, 0x01, 0xE6, 0x01,
+	0xE8, 0x01, 0xEB, 0x01, 0xEE, 0x01, 0xF1, 0x01,
+	0xF3, 0x01, 0xF8, 0x01, 0xF9, 0x01, 0xFC, 0x01,
+	0x00, 0x02, 0x03, 0x02, 0x07, 0x02, 0x09, 0x02,
+	0x0E, 0x02, 0x13, 0x02, 0x1C, 0x02, 0x00
+};
+
+const unsigned char INIT_3[15] = {
+	0x14, 0x26, 0x33, 0x3D, 0x45, 0x4D, 0x53, 0x59,
+	0x5E, 0x63, 0x67, 0x6D, 0x71, 0x78, 0xFF
+};
+
+static void epson_sendbyte(int flag, unsigned char byte)
+{
+	int i, shifter = 0x80;
+
+	if (!flag)
+		omap_set_gpio_dataout(_A_LCD_SSC_A0, 0);
+	mdelay(2);
+	omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+
+	omap_set_gpio_dataout(A_LCD_SSC_SD, flag);
+
+	OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
+	OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
+	for (i = 0; i < 8; i++) {
+		OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
+		omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte);
+		OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
+		shifter >>= 1;
+	}
+	omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+}
+
+static void init_system(void)
+{
+	omap_mcbsp_request(OMAP_MCBSP3);
+	omap_mcbsp_stop(OMAP_MCBSP3);
+}
+
+static void setup_GPIO(void)
+{
+	/* new wave */
+	omap_request_gpio(A_LCD_SSC_RD);
+	omap_request_gpio(A_LCD_SSC_SD);
+	omap_request_gpio(_A_LCD_RESET);
+	omap_request_gpio(_A_LCD_SSC_CS);
+	omap_request_gpio(_A_LCD_SSC_A0);
+
+	/* set all GPIOs to output */
+	omap_set_gpio_direction(A_LCD_SSC_RD, 0);
+	omap_set_gpio_direction(A_LCD_SSC_SD, 0);
+	omap_set_gpio_direction(_A_LCD_RESET, 0);
+	omap_set_gpio_direction(_A_LCD_SSC_CS, 0);
+	omap_set_gpio_direction(_A_LCD_SSC_A0, 0);
+
+	/* set GPIO data */
+	omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+	omap_set_gpio_dataout(A_LCD_SSC_SD, 0);
+	omap_set_gpio_dataout(_A_LCD_RESET, 0);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+}
+
+static void display_init(void)
+{
+	int i;
+
+	omap_cfg_reg(MCBSP3_CLKX);
+
+	mdelay(2);
+	setup_GPIO();
+	mdelay(2);
+
+	/* reset LCD */
+	omap_set_gpio_dataout(A_LCD_SSC_SD, 1);
+	epson_sendbyte(0, 0x25);
+
+	omap_set_gpio_dataout(_A_LCD_RESET, 0);
+	mdelay(10);
+	omap_set_gpio_dataout(_A_LCD_RESET, 1);
+
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	mdelay(2);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD, phase 1 */
+	epson_sendbyte(0, 0xCA);
+	for (i = 0; i < 10; i++)
+		epson_sendbyte(1, INIT_1[i]);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 2 */
+	epson_sendbyte(0, 0xCB);
+	for (i = 0; i < 125; i++)
+		epson_sendbyte(1, INIT_2[i]);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 2a */
+	epson_sendbyte(0, 0xCC);
+	for (i = 0; i < 14; i++)
+		epson_sendbyte(1, INIT_3[i]);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 3 */
+	epson_sendbyte(0, 0xBC);
+	epson_sendbyte(1, 0x08);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 4 */
+	epson_sendbyte(0, 0x07);
+	epson_sendbyte(1, 0x05);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 5 */
+	epson_sendbyte(0, 0x94);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 6 */
+	epson_sendbyte(0, 0xC6);
+	epson_sendbyte(1, 0x80);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	mdelay(100); /* used to be 1000 */
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 7 */
+	epson_sendbyte(0, 0x16);
+	epson_sendbyte(1, 0x02);
+	epson_sendbyte(1, 0x00);
+	epson_sendbyte(1, 0xB1);
+	epson_sendbyte(1, 0x00);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 8 */
+	epson_sendbyte(0, 0x76);
+	epson_sendbyte(1, 0x00);
+	epson_sendbyte(1, 0x00);
+	epson_sendbyte(1, 0xDB);
+	epson_sendbyte(1, 0x00);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 9 */
+	epson_sendbyte(0, 0xAF);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+}
+
+static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void sx1_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static void sx1_panel_disable(struct lcd_panel *panel)
+{
+	printk(KERN_INFO "SX1: LCD panel disable\n");
+	sx1_setmmipower(0);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+
+	epson_sendbyte(0, 0x25);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	epson_sendbyte(0, 0xAE);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	mdelay(100);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	epson_sendbyte(0, 0x95);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+}
+
+static int sx1_panel_enable(struct lcd_panel *panel)
+{
+	printk(KERN_INFO "lcd_sx1: LCD panel enable\n");
+	init_system();
+	display_init();
+
+	sx1_setmmipower(1);
+	sx1_setbacklight(0x18);
+	sx1_setkeylight (0x06);
+	return 0;
+}
+
+
+static unsigned long sx1_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel sx1_panel = {
+	.name		= "sx1",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_INV_PIX_CLOCK |
+			  OMAP_LCDC_INV_OUTPUT_EN,
+
+	.x_res		= 176,
+	.y_res		= 220,
+	.data_lines	= 16,
+	.bpp		= 16,
+	.hsw		= 5,
+	.hfp		= 5,
+	.hbp		= 5,
+	.vsw		= 2,
+	.vfp		= 1,
+	.vbp		= 1,
+	.pixel_clock	= 1500,
+
+	.init		= sx1_panel_init,
+	.cleanup	= sx1_panel_cleanup,
+	.enable		= sx1_panel_enable,
+	.disable	= sx1_panel_disable,
+	.get_caps	= sx1_panel_get_caps,
+};
+
+static int sx1_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&sx1_panel);
+	return 0;
+}
+
+static int sx1_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int sx1_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int sx1_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver sx1_panel_driver = {
+	.probe		= sx1_panel_probe,
+	.remove		= sx1_panel_remove,
+	.suspend	= sx1_panel_suspend,
+	.resume		= sx1_panel_resume,
+	.driver	= {
+		.name	= "lcd_sx1",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int sx1_panel_drv_init(void)
+{
+	return platform_driver_register(&sx1_panel_driver);
+}
+
+static void sx1_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&sx1_panel_driver);
+}
+
+module_init(sx1_panel_drv_init);
+module_exit(sx1_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
new file mode 100644
index 0000000..9085188
--- /dev/null
+++ b/drivers/video/omap/lcdc.c
@@ -0,0 +1,893 @@
+/*
+ * OMAP1 internal LCD controller
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.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.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#include <asm/mach-types.h>
+
+#define MODULE_NAME			"lcdc"
+
+#define OMAP_LCDC_BASE			0xfffec000
+#define OMAP_LCDC_SIZE			256
+#define OMAP_LCDC_IRQ			INT_LCD_CTRL
+
+#define OMAP_LCDC_CONTROL		(OMAP_LCDC_BASE + 0x00)
+#define OMAP_LCDC_TIMING0		(OMAP_LCDC_BASE + 0x04)
+#define OMAP_LCDC_TIMING1		(OMAP_LCDC_BASE + 0x08)
+#define OMAP_LCDC_TIMING2		(OMAP_LCDC_BASE + 0x0c)
+#define OMAP_LCDC_STATUS		(OMAP_LCDC_BASE + 0x10)
+#define OMAP_LCDC_SUBPANEL		(OMAP_LCDC_BASE + 0x14)
+#define OMAP_LCDC_LINE_INT		(OMAP_LCDC_BASE + 0x18)
+#define OMAP_LCDC_DISPLAY_STATUS	(OMAP_LCDC_BASE + 0x1c)
+
+#define OMAP_LCDC_STAT_DONE		(1 << 0)
+#define OMAP_LCDC_STAT_VSYNC		(1 << 1)
+#define OMAP_LCDC_STAT_SYNC_LOST	(1 << 2)
+#define OMAP_LCDC_STAT_ABC		(1 << 3)
+#define OMAP_LCDC_STAT_LINE_INT		(1 << 4)
+#define OMAP_LCDC_STAT_FUF		(1 << 5)
+#define OMAP_LCDC_STAT_LOADED_PALETTE	(1 << 6)
+
+#define OMAP_LCDC_CTRL_LCD_EN		(1 << 0)
+#define OMAP_LCDC_CTRL_LCD_TFT		(1 << 7)
+#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL	(1 << 10)
+
+#define OMAP_LCDC_IRQ_VSYNC		(1 << 2)
+#define OMAP_LCDC_IRQ_DONE		(1 << 3)
+#define OMAP_LCDC_IRQ_LOADED_PALETTE	(1 << 4)
+#define OMAP_LCDC_IRQ_LINE_NIRQ		(1 << 5)
+#define OMAP_LCDC_IRQ_LINE		(1 << 6)
+#define OMAP_LCDC_IRQ_MASK		(((1 << 5) - 1) << 2)
+
+#define MAX_PALETTE_SIZE		PAGE_SIZE
+
+enum lcdc_load_mode {
+	OMAP_LCDC_LOAD_PALETTE,
+	OMAP_LCDC_LOAD_FRAME,
+	OMAP_LCDC_LOAD_PALETTE_AND_FRAME
+};
+
+static struct omap_lcd_controller {
+	enum omapfb_update_mode	update_mode;
+	int			ext_mode;
+
+	unsigned long		frame_offset;
+	int			screen_width;
+	int			xres;
+	int			yres;
+
+	enum omapfb_color_format	color_mode;
+	int			bpp;
+	void			*palette_virt;
+	dma_addr_t		palette_phys;
+	int			palette_code;
+	int			palette_size;
+
+	unsigned int		irq_mask;
+	struct completion	last_frame_complete;
+	struct completion	palette_load_complete;
+	struct clk		*lcd_ck;
+	struct omapfb_device	*fbdev;
+
+	void			(*dma_callback)(void *data);
+	void			*dma_callback_data;
+
+	int			fbmem_allocated;
+	dma_addr_t		vram_phys;
+	void			*vram_virt;
+	unsigned long		vram_size;
+} lcdc;
+
+static void inline enable_irqs(int mask)
+{
+	lcdc.irq_mask |= mask;
+}
+
+static void inline disable_irqs(int mask)
+{
+	lcdc.irq_mask &= ~mask;
+}
+
+static void set_load_mode(enum lcdc_load_mode mode)
+{
+	u32 l;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l &= ~(3 << 20);
+	switch (mode) {
+	case OMAP_LCDC_LOAD_PALETTE:
+		l |= 1 << 20;
+		break;
+	case OMAP_LCDC_LOAD_FRAME:
+		l |= 2 << 20;
+		break;
+	case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:
+		break;
+	default:
+		BUG();
+	}
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void enable_controller(void)
+{
+	u32 l;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l |= OMAP_LCDC_CTRL_LCD_EN;
+	l &= ~OMAP_LCDC_IRQ_MASK;
+	l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;	/* enabled IRQs */
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller_async(void)
+{
+	u32 l;
+	u32 mask;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;
+	/*
+	 * Preserve the DONE mask, since we still want to get the
+	 * final DONE irq. It will be disabled in the IRQ handler.
+	 */
+	mask &= ~OMAP_LCDC_IRQ_DONE;
+	l &= ~mask;
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller(void)
+{
+	init_completion(&lcdc.last_frame_complete);
+	disable_controller_async();
+	if (!wait_for_completion_timeout(&lcdc.last_frame_complete,
+				msecs_to_jiffies(500)))
+		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+}
+
+static void reset_controller(u32 status)
+{
+	static unsigned long reset_count;
+	static unsigned long last_jiffies;
+
+	disable_controller_async();
+	reset_count++;
+	if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
+		dev_err(lcdc.fbdev->dev,
+			  "resetting (status %#010x,reset count %lu)\n",
+			  status, reset_count);
+		last_jiffies = jiffies;
+	}
+	if (reset_count < 100) {
+		enable_controller();
+	} else {
+		reset_count = 0;
+		dev_err(lcdc.fbdev->dev,
+			"too many reset attempts, giving up.\n");
+	}
+}
+
+/*
+ * Configure the LCD DMA according to the current mode specified by parameters
+ * in lcdc.fbdev and fbdev->var.
+ */
+static void setup_lcd_dma(void)
+{
+	static const int dma_elem_type[] = {
+		0,
+		OMAP_DMA_DATA_TYPE_S8,
+		OMAP_DMA_DATA_TYPE_S16,
+		0,
+		OMAP_DMA_DATA_TYPE_S32,
+	};
+	struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;
+	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+	unsigned long	src;
+	int		esize, xelem, yelem;
+
+	src = lcdc.vram_phys + lcdc.frame_offset;
+
+	switch (var->rotate) {
+	case 0:
+		if (plane->info.mirror || (src & 3) ||
+		    lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
+		    (lcdc.xres & 1))
+			esize = 2;
+		else
+			esize = 4;
+		xelem = lcdc.xres * lcdc.bpp / 8 / esize;
+		yelem = lcdc.yres;
+		break;
+	case 90:
+	case 180:
+	case 270:
+		if (cpu_is_omap15xx()) {
+			BUG();
+		}
+		esize = 2;
+		xelem = lcdc.yres * lcdc.bpp / 16;
+		yelem = lcdc.xres;
+		break;
+	default:
+		BUG();
+		return;
+	}
+#ifdef VERBOSE
+	dev_dbg(lcdc.fbdev->dev,
+		 "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
+		 src, esize, xelem, yelem);
+#endif
+	omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
+	if (!cpu_is_omap15xx()) {
+		int bpp = lcdc.bpp;
+
+		/*
+		 * YUV support is only for external mode when we have the
+		 * YUV window embedded in a 16bpp frame buffer.
+		 */
+		if (lcdc.color_mode == OMAPFB_COLOR_YUV420)
+			bpp = 16;
+		/* Set virtual xres elem size */
+		omap_set_lcd_dma_b1_vxres(
+			lcdc.screen_width * bpp / 8 / esize);
+		/* Setup transformations */
+		omap_set_lcd_dma_b1_rotation(var->rotate);
+		omap_set_lcd_dma_b1_mirror(plane->info.mirror);
+	}
+	omap_setup_lcd_dma();
+}
+
+static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)
+{
+	u32 status;
+
+	status = omap_readl(OMAP_LCDC_STATUS);
+
+	if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))
+		reset_controller(status);
+	else {
+		if (status & OMAP_LCDC_STAT_DONE) {
+			u32 l;
+
+			/*
+			 * Disable IRQ_DONE. The status bit will be cleared
+			 * only when the controller is reenabled and we don't
+			 * want to get more interrupts.
+			 */
+			l = omap_readl(OMAP_LCDC_CONTROL);
+			l &= ~OMAP_LCDC_IRQ_DONE;
+			omap_writel(l, OMAP_LCDC_CONTROL);
+			complete(&lcdc.last_frame_complete);
+		}
+		if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
+			disable_controller_async();
+			complete(&lcdc.palette_load_complete);
+		}
+	}
+
+	/*
+	 * Clear these interrupt status bits.
+	 * Sync_lost, FUF bits were cleared by disabling the LCD controller
+	 * LOADED_PALETTE can be cleared this way only in palette only
+	 * load mode. In other load modes it's cleared by disabling the
+	 * controller.
+	 */
+	status &= ~(OMAP_LCDC_STAT_VSYNC |
+		    OMAP_LCDC_STAT_LOADED_PALETTE |
+		    OMAP_LCDC_STAT_ABC |
+		    OMAP_LCDC_STAT_LINE_INT);
+	omap_writel(status, OMAP_LCDC_STATUS);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Change to a new video mode. We defer this to a later time to avoid any
+ * flicker and not to mess up the current LCD DMA context. For this we disable
+ * the LCD controler, which will generate a DONE irq after the last frame has
+ * been transferred. Then it'll be safe to reconfigure both the LCD controller
+ * as well as the LCD DMA.
+ */
+static int omap_lcdc_setup_plane(int plane, int channel_out,
+				 unsigned long offset, int screen_width,
+				 int pos_x, int pos_y, int width, int height,
+				 int color_mode)
+{
+	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+	int rot_x, rot_y;
+
+	if (var->rotate == 0) {
+		rot_x = panel->x_res;
+		rot_y = panel->y_res;
+	} else {
+		rot_x = panel->y_res;
+		rot_y = panel->x_res;
+	}
+	if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
+	    width > rot_x || height > rot_y) {
+#ifdef VERBOSE
+		dev_dbg(lcdc.fbdev->dev,
+			"invalid plane params plane %d pos_x %d pos_y %d "
+			"w %d h %d\n", plane, pos_x, pos_y, width, height);
+#endif
+		return -EINVAL;
+	}
+
+	lcdc.frame_offset = offset;
+	lcdc.xres = width;
+	lcdc.yres = height;
+	lcdc.screen_width = screen_width;
+	lcdc.color_mode = color_mode;
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_CLUT_8BPP:
+		lcdc.bpp = 8;
+		lcdc.palette_code = 0x3000;
+		lcdc.palette_size = 512;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		lcdc.bpp = 16;
+		lcdc.palette_code = 0x4000;
+		lcdc.palette_size = 32;
+		break;
+	case OMAPFB_COLOR_RGB444:
+		lcdc.bpp = 16;
+		lcdc.palette_code = 0x4000;
+		lcdc.palette_size = 32;
+		break;
+	case OMAPFB_COLOR_YUV420:
+		if (lcdc.ext_mode) {
+			lcdc.bpp = 12;
+			break;
+		}
+		/* fallthrough */
+	case OMAPFB_COLOR_YUV422:
+		if (lcdc.ext_mode) {
+			lcdc.bpp = 16;
+			break;
+		}
+		/* fallthrough */
+	default:
+		/* FIXME: other BPPs.
+		 * bpp1: code  0,     size 256
+		 * bpp2: code  0x1000 size 256
+		 * bpp4: code  0x2000 size 256
+		 * bpp12: code 0x4000 size 32
+		 */
+		dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);
+		BUG();
+		return -1;
+	}
+
+	if (lcdc.ext_mode) {
+		setup_lcd_dma();
+		return 0;
+	}
+
+	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+		disable_controller();
+		omap_stop_lcd_dma();
+		setup_lcd_dma();
+		enable_controller();
+	}
+
+	return 0;
+}
+
+static int omap_lcdc_enable_plane(int plane, int enable)
+{
+	dev_dbg(lcdc.fbdev->dev,
+		"plane %d enable %d update_mode %d ext_mode %d\n",
+		plane, enable, lcdc.update_mode, lcdc.ext_mode);
+	if (plane != OMAPFB_PLANE_GFX)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Configure the LCD DMA for a palette load operation and do the palette
+ * downloading synchronously. We don't use the frame+palette load mode of
+ * the controller, since the palette can always be downloaded seperately.
+ */
+static void load_palette(void)
+{
+	u16	*palette;
+
+	palette = (u16 *)lcdc.palette_virt;
+
+	*(u16 *)palette &= 0x0fff;
+	*(u16 *)palette |= lcdc.palette_code;
+
+	omap_set_lcd_dma_b1(lcdc.palette_phys,
+		lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
+
+	omap_set_lcd_dma_single_transfer(1);
+	omap_setup_lcd_dma();
+
+	init_completion(&lcdc.palette_load_complete);
+	enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+	set_load_mode(OMAP_LCDC_LOAD_PALETTE);
+	enable_controller();
+	if (!wait_for_completion_timeout(&lcdc.palette_load_complete,
+				msecs_to_jiffies(500)))
+		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+	/* The controller gets disabled in the irq handler */
+	disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+	omap_stop_lcd_dma();
+
+	omap_set_lcd_dma_single_transfer(lcdc.ext_mode);
+}
+
+/* Used only in internal controller mode */
+static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
+			       u16 transp, int update_hw_pal)
+{
+	u16 *palette;
+
+	if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
+		return -EINVAL;
+
+	palette = (u16 *)lcdc.palette_virt;
+
+	palette[regno] &= ~0x0fff;
+	palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
+			   (blue >> 12);
+
+	if (update_hw_pal) {
+		disable_controller();
+		omap_stop_lcd_dma();
+		load_palette();
+		setup_lcd_dma();
+		set_load_mode(OMAP_LCDC_LOAD_FRAME);
+		enable_controller();
+	}
+
+	return 0;
+}
+
+static void calc_ck_div(int is_tft, int pck, int *pck_div)
+{
+	unsigned long lck;
+
+	pck = max(1, pck);
+	lck = clk_get_rate(lcdc.lcd_ck);
+	*pck_div = (lck + pck - 1) / pck;
+	if (is_tft)
+		*pck_div = max(2, *pck_div);
+	else
+		*pck_div = max(3, *pck_div);
+	if (*pck_div > 255) {
+		/* FIXME: try to adjust logic clock divider as well */
+		*pck_div = 255;
+		dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",
+			 pck / 1000);
+	}
+}
+
+static void inline setup_regs(void)
+{
+	u32 l;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+	int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+	unsigned long lck;
+	int pcd;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l &= ~OMAP_LCDC_CTRL_LCD_TFT;
+	l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;
+#ifdef CONFIG_MACH_OMAP_PALMTE
+/* FIXME:if (machine_is_omap_palmte()) { */
+		/* PalmTE uses alternate TFT setting in 8BPP mode */
+		l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0;
+/*	} */
+#endif
+	omap_writel(l, OMAP_LCDC_CONTROL);
+
+	l = omap_readl(OMAP_LCDC_TIMING2);
+	l &= ~(((1 << 6) - 1) << 20);
+	l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;
+	omap_writel(l, OMAP_LCDC_TIMING2);
+
+	l = panel->x_res - 1;
+	l |= (panel->hsw - 1) << 10;
+	l |= (panel->hfp - 1) << 16;
+	l |= (panel->hbp - 1) << 24;
+	omap_writel(l, OMAP_LCDC_TIMING0);
+
+	l = panel->y_res - 1;
+	l |= (panel->vsw - 1) << 10;
+	l |= panel->vfp << 16;
+	l |= panel->vbp << 24;
+	omap_writel(l, OMAP_LCDC_TIMING1);
+
+	l = omap_readl(OMAP_LCDC_TIMING2);
+	l &= ~0xff;
+
+	lck = clk_get_rate(lcdc.lcd_ck);
+
+	if (!panel->pcd)
+		calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
+	else {
+		dev_warn(lcdc.fbdev->dev,
+		    "Pixel clock divider value is obsolete.\n"
+		    "Try to set pixel_clock to %lu and pcd to 0 "
+		    "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
+			lck / panel->pcd / 1000, panel->name);
+
+		pcd = panel->pcd;
+	}
+	l |= pcd & 0xff;
+	l |= panel->acb << 8;
+	omap_writel(l, OMAP_LCDC_TIMING2);
+
+	/* update panel info with the exact clock */
+	panel->pixel_clock = lck / pcd / 1000;
+}
+
+/*
+ * Configure the LCD controller, download the color palette and start a looped
+ * DMA transfer of the frame image data. Called only in internal
+ * controller mode.
+ */
+static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
+{
+	int r = 0;
+
+	if (mode != lcdc.update_mode) {
+		switch (mode) {
+		case OMAPFB_AUTO_UPDATE:
+			setup_regs();
+			load_palette();
+
+			/* Setup and start LCD DMA */
+			setup_lcd_dma();
+
+			set_load_mode(OMAP_LCDC_LOAD_FRAME);
+			enable_irqs(OMAP_LCDC_IRQ_DONE);
+			/* This will start the actual DMA transfer */
+			enable_controller();
+			lcdc.update_mode = mode;
+			break;
+		case OMAPFB_UPDATE_DISABLED:
+			disable_controller();
+			omap_stop_lcd_dma();
+			lcdc.update_mode = mode;
+			break;
+		default:
+			r = -EINVAL;
+		}
+	}
+
+	return r;
+}
+
+static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
+{
+	return lcdc.update_mode;
+}
+
+/* PM code called only in internal controller mode */
+static void omap_lcdc_suspend(void)
+{
+	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+		disable_controller();
+		omap_stop_lcd_dma();
+	}
+}
+
+static void omap_lcdc_resume(void)
+{
+	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+		setup_regs();
+		load_palette();
+		setup_lcd_dma();
+		set_load_mode(OMAP_LCDC_LOAD_FRAME);
+		enable_irqs(OMAP_LCDC_IRQ_DONE);
+		enable_controller();
+	}
+}
+
+static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
+{
+	return;
+}
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)
+{
+	BUG_ON(callback == NULL);
+
+	if (lcdc.dma_callback)
+		return -EBUSY;
+	else {
+		lcdc.dma_callback = callback;
+		lcdc.dma_callback_data = data;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(omap_lcdc_set_dma_callback);
+
+void omap_lcdc_free_dma_callback(void)
+{
+	lcdc.dma_callback = NULL;
+}
+EXPORT_SYMBOL(omap_lcdc_free_dma_callback);
+
+static void lcdc_dma_handler(u16 status, void *data)
+{
+	if (lcdc.dma_callback)
+		lcdc.dma_callback(lcdc.dma_callback_data);
+}
+
+static int mmap_kern(void)
+{
+	struct vm_struct	*kvma;
+	struct vm_area_struct	vma;
+	pgprot_t		pgprot;
+	unsigned long		vaddr;
+
+	kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP);
+	if (kvma == NULL) {
+		dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n");
+		return -ENOMEM;
+	}
+	vma.vm_mm = &init_mm;
+
+	vaddr = (unsigned long)kvma->addr;
+	vma.vm_start = vaddr;
+	vma.vm_end = vaddr + lcdc.vram_size;
+
+	pgprot = pgprot_writecombine(pgprot_kernel);
+	if (io_remap_pfn_range(&vma, vaddr,
+			   lcdc.vram_phys >> PAGE_SHIFT,
+			   lcdc.vram_size, pgprot) < 0) {
+		dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n");
+		return -EAGAIN;
+	}
+
+	lcdc.vram_virt = (void *)vaddr;
+
+	return 0;
+}
+
+static void unmap_kern(void)
+{
+	vunmap(lcdc.vram_virt);
+}
+
+static int alloc_palette_ram(void)
+{
+	lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+		MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL);
+	if (lcdc.palette_virt == NULL) {
+		dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
+		return -ENOMEM;
+	}
+	memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
+
+	return 0;
+}
+
+static void free_palette_ram(void)
+{
+	dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
+			lcdc.palette_virt, lcdc.palette_phys);
+}
+
+static int alloc_fbmem(struct omapfb_mem_region *region)
+{
+	int bpp;
+	int frame_size;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+
+	bpp = panel->bpp;
+	if (bpp == 12)
+		bpp = 16;
+	frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);
+	if (region->size > frame_size)
+		frame_size = region->size;
+	lcdc.vram_size = frame_size;
+	lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+			lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL);
+	if (lcdc.vram_virt == NULL) {
+		dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
+		return -ENOMEM;
+	}
+	region->size = frame_size;
+	region->paddr = lcdc.vram_phys;
+	region->vaddr = lcdc.vram_virt;
+	region->alloc = 1;
+
+	memset(lcdc.vram_virt, 0, lcdc.vram_size);
+
+	return 0;
+}
+
+static void free_fbmem(void)
+{
+	dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size,
+			      lcdc.vram_virt, lcdc.vram_phys);
+}
+
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
+{
+	int r;
+
+	if (!req_md->region_cnt) {
+		dev_err(lcdc.fbdev->dev, "no memory regions defined\n");
+		return -EINVAL;
+	}
+
+	if (req_md->region_cnt > 1) {
+		dev_err(lcdc.fbdev->dev, "only one plane is supported\n");
+		req_md->region_cnt = 1;
+	}
+
+	if (req_md->region[0].paddr == 0) {
+		lcdc.fbmem_allocated = 1;
+		if ((r = alloc_fbmem(&req_md->region[0])) < 0)
+			return r;
+		return 0;
+	}
+
+	lcdc.vram_phys = req_md->region[0].paddr;
+	lcdc.vram_size = req_md->region[0].size;
+
+	if ((r = mmap_kern()) < 0)
+		return r;
+
+	dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n",
+		 lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt);
+
+	return 0;
+}
+
+static void cleanup_fbmem(void)
+{
+	if (lcdc.fbmem_allocated)
+		free_fbmem();
+	else
+		unmap_kern();
+}
+
+static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
+			  struct omapfb_mem_desc *req_vram)
+{
+	int r;
+	u32 l;
+	int rate;
+	struct clk *tc_ck;
+
+	lcdc.irq_mask = 0;
+
+	lcdc.fbdev = fbdev;
+	lcdc.ext_mode = ext_mode;
+
+	l = 0;
+	omap_writel(l, OMAP_LCDC_CONTROL);
+
+	/* FIXME:
+	 * According to errata some platforms have a clock rate limitiation
+	 */
+	lcdc.lcd_ck = clk_get(NULL, "lcd_ck");
+	if (IS_ERR(lcdc.lcd_ck)) {
+		dev_err(fbdev->dev, "unable to access LCD clock\n");
+		r = PTR_ERR(lcdc.lcd_ck);
+		goto fail0;
+	}
+
+	tc_ck = clk_get(NULL, "tc_ck");
+	if (IS_ERR(tc_ck)) {
+		dev_err(fbdev->dev, "unable to access TC clock\n");
+		r = PTR_ERR(tc_ck);
+		goto fail1;
+	}
+
+	rate = clk_get_rate(tc_ck);
+	clk_put(tc_ck);
+
+	if (machine_is_ams_delta())
+		rate /= 4;
+	if (machine_is_omap_h3())
+		rate /= 3;
+	r = clk_set_rate(lcdc.lcd_ck, rate);
+	if (r) {
+		dev_err(fbdev->dev, "failed to adjust LCD rate\n");
+		goto fail1;
+	}
+	clk_enable(lcdc.lcd_ck);
+
+	r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "unable to get IRQ\n");
+		goto fail2;
+	}
+
+	r = omap_request_lcd_dma(lcdc_dma_handler, NULL);
+	if (r) {
+		dev_err(fbdev->dev, "unable to get LCD DMA\n");
+		goto fail3;
+	}
+
+	omap_set_lcd_dma_single_transfer(ext_mode);
+	omap_set_lcd_dma_ext_controller(ext_mode);
+
+	if (!ext_mode)
+		if ((r = alloc_palette_ram()) < 0)
+			goto fail4;
+
+	if ((r = setup_fbmem(req_vram)) < 0)
+		goto fail5;
+
+	pr_info("omapfb: LCDC initialized\n");
+
+	return 0;
+fail5:
+	if (!ext_mode)
+		free_palette_ram();
+fail4:
+	omap_free_lcd_dma();
+fail3:
+	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+fail2:
+	clk_disable(lcdc.lcd_ck);
+fail1:
+	clk_put(lcdc.lcd_ck);
+fail0:
+	return r;
+}
+
+static void omap_lcdc_cleanup(void)
+{
+	if (!lcdc.ext_mode)
+		free_palette_ram();
+	cleanup_fbmem();
+	omap_free_lcd_dma();
+	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+	clk_disable(lcdc.lcd_ck);
+	clk_put(lcdc.lcd_ck);
+}
+
+const struct lcd_ctrl omap1_int_ctrl = {
+	.name			= "internal",
+	.init			= omap_lcdc_init,
+	.cleanup		= omap_lcdc_cleanup,
+	.get_caps		= omap_lcdc_get_caps,
+	.set_update_mode	= omap_lcdc_set_update_mode,
+	.get_update_mode	= omap_lcdc_get_update_mode,
+	.update_window		= NULL,
+	.suspend		= omap_lcdc_suspend,
+	.resume			= omap_lcdc_resume,
+	.setup_plane		= omap_lcdc_setup_plane,
+	.enable_plane		= omap_lcdc_enable_plane,
+	.setcolreg		= omap_lcdc_setcolreg,
+};
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h
new file mode 100644
index 0000000..adb731e
--- /dev/null
+++ b/drivers/video/omap/lcdc.h
@@ -0,0 +1,7 @@
+#ifndef LCDC_H
+#define LCDC_H
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
+void omap_lcdc_free_dma_callback(void);
+
+#endif
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
new file mode 100644
index 0000000..14d0f7a
--- /dev/null
+++ b/drivers/video/omap/omapfb_main.c
@@ -0,0 +1,1941 @@
+/*
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * Acknowledgements:
+ *   Alex McMains <aam@ridgerun.com>       - Original driver
+ *   Juha Yrjola <juha.yrjola@nokia.com>   - Original driver and improvements
+ *   Dirk Behme <dirk.behme@de.bosch.com>  - changes for 2.6 kernel API
+ *   Texas Instruments                     - H3 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.
+ */
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME	"omapfb"
+
+static unsigned int	def_accel;
+static unsigned long	def_vram[OMAPFB_PLANE_NUM];
+static int		def_vram_cnt;
+static unsigned long	def_vxres;
+static unsigned long	def_vyres;
+static unsigned int	def_rotate;
+static unsigned int	def_mirror;
+
+#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
+static int		manual_update = 1;
+#else
+static int		manual_update;
+#endif
+
+static struct platform_device	*fbdev_pdev;
+static struct lcd_panel		*fbdev_panel;
+static struct omapfb_device	*omapfb_dev;
+
+struct caps_table_struct {
+	unsigned long flag;
+	const char *name;
+};
+
+static struct caps_table_struct ctrl_caps[] = {
+	{ OMAPFB_CAPS_MANUAL_UPDATE,  "manual update" },
+	{ OMAPFB_CAPS_TEARSYNC,       "tearing synchronization" },
+	{ OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" },
+	{ OMAPFB_CAPS_PLANE_SCALE,    "scale plane" },
+	{ OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
+	{ OMAPFB_CAPS_WINDOW_SCALE,   "scale window" },
+	{ OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
+	{ OMAPFB_CAPS_SET_BACKLIGHT,  "backlight setting" },
+};
+
+static struct caps_table_struct color_caps[] = {
+	{ 1 << OMAPFB_COLOR_RGB565,	"RGB565", },
+	{ 1 << OMAPFB_COLOR_YUV422,	"YUV422", },
+	{ 1 << OMAPFB_COLOR_YUV420,	"YUV420", },
+	{ 1 << OMAPFB_COLOR_CLUT_8BPP,	"CLUT8", },
+	{ 1 << OMAPFB_COLOR_CLUT_4BPP,	"CLUT4", },
+	{ 1 << OMAPFB_COLOR_CLUT_2BPP,	"CLUT2", },
+	{ 1 << OMAPFB_COLOR_CLUT_1BPP,	"CLUT1", },
+	{ 1 << OMAPFB_COLOR_RGB444,	"RGB444", },
+	{ 1 << OMAPFB_COLOR_YUY422,	"YUY422", },
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD panel
+ * ---------------------------------------------------------------------------
+ */
+extern struct lcd_ctrl omap1_int_ctrl;
+extern struct lcd_ctrl omap2_int_ctrl;
+extern struct lcd_ctrl hwa742_ctrl;
+extern struct lcd_ctrl blizzard_ctrl;
+
+static struct lcd_ctrl *ctrls[] = {
+#ifdef CONFIG_ARCH_OMAP1
+	&omap1_int_ctrl,
+#else
+	&omap2_int_ctrl,
+#endif
+
+#ifdef CONFIG_FB_OMAP_LCDC_HWA742
+	&hwa742_ctrl,
+#endif
+#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD
+	&blizzard_ctrl,
+#endif
+};
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+#ifdef CONFIG_ARCH_OMAP1
+extern struct lcd_ctrl_extif omap1_ext_if;
+#else
+extern struct lcd_ctrl_extif omap2_ext_if;
+#endif
+#endif
+
+static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
+{
+	mutex_lock(&fbdev->rqueue_mutex);
+}
+
+static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
+{
+	mutex_unlock(&fbdev->rqueue_mutex);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD controller and LCD DMA
+ * ---------------------------------------------------------------------------
+ */
+/* Lookup table to map elem size to elem type. */
+static const int dma_elem_type[] = {
+	0,
+	OMAP_DMA_DATA_TYPE_S8,
+	OMAP_DMA_DATA_TYPE_S16,
+	0,
+	OMAP_DMA_DATA_TYPE_S32,
+};
+
+/*
+ * Allocate resources needed for LCD controller and LCD DMA operations. Video
+ * memory is allocated from system memory according to the virtual display
+ * size, except if a bigger memory size is specified explicitly as a kernel
+ * parameter.
+ */
+static int ctrl_init(struct omapfb_device *fbdev)
+{
+	int r;
+	int i;
+
+	/* kernel/module vram parameters override boot tags/board config */
+	if (def_vram_cnt) {
+		for (i = 0; i < def_vram_cnt; i++)
+			fbdev->mem_desc.region[i].size =
+				PAGE_ALIGN(def_vram[i]);
+		fbdev->mem_desc.region_cnt = i;
+	} else {
+		struct omapfb_platform_data *conf;
+
+		conf = fbdev->dev->platform_data;
+		fbdev->mem_desc = conf->mem_desc;
+	}
+
+	if (!fbdev->mem_desc.region_cnt) {
+		struct lcd_panel *panel = fbdev->panel;
+		int def_size;
+		int bpp = panel->bpp;
+
+		/* 12 bpp is packed in 16 bits */
+		if (bpp == 12)
+			bpp = 16;
+		def_size = def_vxres * def_vyres * bpp / 8;
+		fbdev->mem_desc.region_cnt = 1;
+		fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size);
+	}
+	r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc);
+	if (r < 0) {
+		dev_err(fbdev->dev, "controller initialization failed (%d)\n",
+			r);
+		return r;
+	}
+
+#ifdef DEBUG
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n",
+			 i,
+			 fbdev->mem_desc.region[i].paddr,
+			 fbdev->mem_desc.region[i].vaddr,
+			 fbdev->mem_desc.region[i].size);
+	}
+#endif
+	return 0;
+}
+
+static void ctrl_cleanup(struct omapfb_device *fbdev)
+{
+	fbdev->ctrl->cleanup();
+}
+
+/* Must be called with fbdev->rqueue_mutex held. */
+static int ctrl_change_mode(struct fb_info *fbi)
+{
+	int r;
+	unsigned long offset;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var = &fbi->var;
+
+	offset = var->yoffset * fbi->fix.line_length +
+		 var->xoffset * var->bits_per_pixel / 8;
+
+	if (fbdev->ctrl->sync)
+		fbdev->ctrl->sync();
+	r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out,
+				 offset, var->xres_virtual,
+				 plane->info.pos_x, plane->info.pos_y,
+				 var->xres, var->yres, plane->color_mode);
+	if (fbdev->ctrl->set_scale != NULL)
+		r = fbdev->ctrl->set_scale(plane->idx,
+				   var->xres, var->yres,
+				   plane->info.out_width,
+				   plane->info.out_height);
+
+	return r;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks and the ioctl interface
+ * ---------------------------------------------------------------------------
+ */
+/* Called each time the omapfb device is opened */
+static int omapfb_open(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+static void omapfb_sync(struct fb_info *info);
+
+/* Called when the omapfb device is closed. We make sure that any pending
+ * gfx DMA operations are ended, before we return. */
+static int omapfb_release(struct fb_info *info, int user)
+{
+	omapfb_sync(info);
+	return 0;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
+			u_int blue, u_int transp, int update_hw_pal)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var = &info->var;
+	int r = 0;
+
+	switch (plane->color_mode) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUV420:
+	case OMAPFB_COLOR_YUY422:
+		r = -EINVAL;
+		break;
+	case OMAPFB_COLOR_CLUT_8BPP:
+	case OMAPFB_COLOR_CLUT_4BPP:
+	case OMAPFB_COLOR_CLUT_2BPP:
+	case OMAPFB_COLOR_CLUT_1BPP:
+		if (fbdev->ctrl->setcolreg)
+			r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+							transp, update_hw_pal);
+		/* Fallthrough */
+	case OMAPFB_COLOR_RGB565:
+	case OMAPFB_COLOR_RGB444:
+		if (r != 0)
+			break;
+
+		if (regno < 0) {
+			r = -EINVAL;
+			break;
+		}
+
+		if (regno < 16) {
+			u16 pal;
+			pal = ((red >> (16 - var->red.length)) <<
+					var->red.offset) |
+			      ((green >> (16 - var->green.length)) <<
+					var->green.offset) |
+			      (blue >> (16 - var->blue.length));
+			((u32 *)(info->pseudo_palette))[regno] = pal;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			    u_int transp, struct fb_info *info)
+{
+	return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	int count, index, r;
+	u16 *red, *green, *blue, *transp;
+	u16 trans = 0xffff;
+
+	red     = cmap->red;
+	green   = cmap->green;
+	blue    = cmap->blue;
+	transp  = cmap->transp;
+	index   = cmap->start;
+
+	for (count = 0; count < cmap->len; count++) {
+		if (transp)
+			trans = *transp++;
+		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+				count == cmap->len - 1);
+		if (r != 0)
+			return r;
+	}
+
+	return 0;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi);
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int do_update = 0;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	switch (blank) {
+	case VESA_NO_BLANKING:
+		if (fbdev->state == OMAPFB_SUSPENDED) {
+			if (fbdev->ctrl->resume)
+				fbdev->ctrl->resume();
+			fbdev->panel->enable(fbdev->panel);
+			fbdev->state = OMAPFB_ACTIVE;
+			if (fbdev->ctrl->get_update_mode() ==
+					OMAPFB_MANUAL_UPDATE)
+				do_update = 1;
+		}
+		break;
+	case VESA_POWERDOWN:
+		if (fbdev->state == OMAPFB_ACTIVE) {
+			fbdev->panel->disable(fbdev->panel);
+			if (fbdev->ctrl->suspend)
+				fbdev->ctrl->suspend();
+			fbdev->state = OMAPFB_SUSPENDED;
+		}
+		break;
+	default:
+		r = -EINVAL;
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	if (r == 0 && do_update)
+		r = omapfb_update_full_screen(fbi);
+
+	return r;
+}
+
+static void omapfb_sync(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+
+	omapfb_rqueue_lock(fbdev);
+	if (fbdev->ctrl->sync)
+		fbdev->ctrl->sync();
+	omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set fb_info.fix fields and also updates fbdev.
+ * When calling this fb_info.var must be set up already.
+ */
+static void set_fb_fix(struct fb_info *fbi)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_mem_region *rg;
+	int bpp;
+
+	rg = &plane->fbdev->mem_desc.region[plane->idx];
+	fbi->screen_base	= (char __iomem *)rg->vaddr;
+	fix->smem_start		= rg->paddr;
+	fix->smem_len		= rg->size;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	bpp = var->bits_per_pixel;
+	if (var->nonstd)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else switch (var->bits_per_pixel) {
+	case 16:
+	case 12:
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		/* 12bpp is stored in 16 bits */
+		bpp = 16;
+		break;
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+	fix->accel		= FB_ACCEL_OMAP1610;
+	fix->line_length	= var->xres_virtual * bpp / 8;
+}
+
+static int set_color_mode(struct omapfb_plane_struct *plane,
+			  struct fb_var_screeninfo *var)
+{
+	switch (var->nonstd) {
+	case 0:
+		break;
+	case OMAPFB_COLOR_YUV422:
+		var->bits_per_pixel = 16;
+		plane->color_mode = var->nonstd;
+		return 0;
+	case OMAPFB_COLOR_YUV420:
+		var->bits_per_pixel = 12;
+		plane->color_mode = var->nonstd;
+		return 0;
+	case OMAPFB_COLOR_YUY422:
+		var->bits_per_pixel = 16;
+		plane->color_mode = var->nonstd;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		plane->color_mode = OMAPFB_COLOR_CLUT_1BPP;
+		return 0;
+	case 2:
+		plane->color_mode = OMAPFB_COLOR_CLUT_2BPP;
+		return 0;
+	case 4:
+		plane->color_mode = OMAPFB_COLOR_CLUT_4BPP;
+		return 0;
+	case 8:
+		plane->color_mode = OMAPFB_COLOR_CLUT_8BPP;
+		return 0;
+	case 12:
+		var->bits_per_pixel = 16;
+		plane->color_mode = OMAPFB_COLOR_RGB444;
+		return 0;
+	case 16:
+		plane->color_mode = OMAPFB_COLOR_RGB565;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/*
+ * Check the values in var against our capabilities and in case of out of
+ * bound values try to adjust them.
+ */
+static int set_fb_var(struct fb_info *fbi,
+		      struct fb_var_screeninfo *var)
+{
+	int		bpp;
+	unsigned long	max_frame_size;
+	unsigned long	line_size;
+	int		xres_min, xres_max;
+	int		yres_min, yres_max;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct lcd_panel *panel = fbdev->panel;
+
+	if (set_color_mode(plane, var) < 0)
+		return -EINVAL;
+
+	bpp = var->bits_per_pixel;
+	if (plane->color_mode == OMAPFB_COLOR_RGB444)
+		bpp = 16;
+
+	switch (var->rotate) {
+	case 0:
+	case 180:
+		xres_min = OMAPFB_PLANE_XRES_MIN;
+		xres_max = panel->x_res;
+		yres_min = OMAPFB_PLANE_YRES_MIN;
+		yres_max = panel->y_res;
+		if (cpu_is_omap15xx()) {
+			var->xres = panel->x_res;
+			var->yres = panel->y_res;
+		}
+		break;
+	case 90:
+	case 270:
+		xres_min = OMAPFB_PLANE_YRES_MIN;
+		xres_max = panel->y_res;
+		yres_min = OMAPFB_PLANE_XRES_MIN;
+		yres_max = panel->x_res;
+		if (cpu_is_omap15xx()) {
+			var->xres = panel->y_res;
+			var->yres = panel->x_res;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (var->xres < xres_min)
+		var->xres = xres_min;
+	if (var->yres < yres_min)
+		var->yres = yres_min;
+	if (var->xres > xres_max)
+		var->xres = xres_max;
+	if (var->yres > yres_max)
+		var->yres = yres_max;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	max_frame_size = fbdev->mem_desc.region[plane->idx].size;
+	line_size = var->xres_virtual * bpp / 8;
+	if (line_size * var->yres_virtual > max_frame_size) {
+		/* Try to keep yres_virtual first */
+		line_size = max_frame_size / var->yres_virtual;
+		var->xres_virtual = line_size * 8 / bpp;
+		if (var->xres_virtual < var->xres) {
+			/* Still doesn't fit. Shrink yres_virtual too */
+			var->xres_virtual = var->xres;
+			line_size = var->xres * bpp / 8;
+			var->yres_virtual = max_frame_size / line_size;
+		}
+		/* Recheck this, as the virtual size changed. */
+		if (var->xres_virtual < var->xres)
+			var->xres = var->xres_virtual;
+		if (var->yres_virtual < var->yres)
+			var->yres = var->yres_virtual;
+		if (var->xres < xres_min || var->yres < yres_min)
+			return -EINVAL;
+	}
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+	line_size = var->xres * bpp / 8;
+
+	if (plane->color_mode == OMAPFB_COLOR_RGB444) {
+		var->red.offset	  = 8; var->red.length	 = 4;
+						var->red.msb_right   = 0;
+		var->green.offset = 4; var->green.length = 4;
+						var->green.msb_right = 0;
+		var->blue.offset  = 0; var->blue.length  = 4;
+						var->blue.msb_right  = 0;
+	} else {
+		var->red.offset	 = 11; var->red.length	 = 5;
+						var->red.msb_right   = 0;
+		var->green.offset = 5;  var->green.length = 6;
+						var->green.msb_right = 0;
+		var->blue.offset = 0;  var->blue.length  = 5;
+						var->blue.msb_right  = 0;
+	}
+
+	var->height		= -1;
+	var->width		= -1;
+	var->grayscale		= 0;
+
+	/* pixclock in ps, the rest in pixclock */
+	var->pixclock		= 10000000 / (panel->pixel_clock / 100);
+	var->left_margin	= panel->hfp;
+	var->right_margin	= panel->hbp;
+	var->upper_margin	= panel->vfp;
+	var->lower_margin	= panel->vbp;
+	var->hsync_len		= panel->hsw;
+	var->vsync_len		= panel->vsw;
+
+	/* TODO: get these from panel->config */
+	var->vmode		= FB_VMODE_NONINTERLACED;
+	var->sync		= 0;
+
+	return 0;
+}
+
+
+/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
+static void omapfb_rotate(struct fb_info *fbi, int rotate)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+
+	omapfb_rqueue_lock(fbdev);
+	if (cpu_is_omap15xx() && rotate != fbi->var.rotate) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+		memcpy(new_var, &fbi->var, sizeof(*new_var));
+		new_var->rotate = rotate;
+		if (set_fb_var(fbi, new_var) == 0 &&
+		    memcmp(new_var, &fbi->var, sizeof(*new_var))) {
+			memcpy(&fbi->var, new_var, sizeof(*new_var));
+			ctrl_change_mode(fbi);
+		}
+	}
+	omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set new x,y offsets in the virtual display for the visible area and switch
+ * to the new mode.
+ */
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	if (var->xoffset != fbi->var.xoffset ||
+	    var->yoffset != fbi->var.yoffset) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+		memcpy(new_var, &fbi->var, sizeof(*new_var));
+		new_var->xoffset = var->xoffset;
+		new_var->yoffset = var->yoffset;
+		if (set_fb_var(fbi, new_var))
+			r = -EINVAL;
+		else {
+			memcpy(&fbi->var, new_var, sizeof(*new_var));
+			ctrl_change_mode(fbi);
+		}
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/* Set mirror to vertical axis and switch to the new mode. */
+static int omapfb_mirror(struct fb_info *fbi, int mirror)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	mirror = mirror ? 1 : 0;
+	if (cpu_is_omap15xx())
+		r = -EINVAL;
+	else if (mirror != plane->info.mirror) {
+		plane->info.mirror = mirror;
+		r = ctrl_change_mode(fbi);
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Check values in var, try to adjust them in case of out of bound values if
+ * possible, or return error.
+ */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	if (fbdev->ctrl->sync != NULL)
+		fbdev->ctrl->sync();
+	r = set_fb_var(fbi, var);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Switch to a new mode. The parameters for it has been check already by
+ * omapfb_check_var.
+ */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	set_fb_fix(fbi);
+	r = ctrl_change_mode(fbi);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+int omapfb_update_window_async(struct fb_info *fbi,
+				struct omapfb_update_window *win,
+				void (*callback)(void *),
+				void *callback_data)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var;
+
+	var = &fbi->var;
+	if (win->x >= var->xres || win->y >= var->yres ||
+	    win->out_x > var->xres || win->out_y >= var->yres)
+		return -EINVAL;
+
+	if (!fbdev->ctrl->update_window ||
+	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+		return -ENODEV;
+
+	if (win->x + win->width >= var->xres)
+		win->width = var->xres - win->x;
+	if (win->y + win->height >= var->yres)
+		win->height = var->yres - win->y;
+	/* The out sizes should be cropped to the LCD size */
+	if (win->out_x + win->out_width > fbdev->panel->x_res)
+		win->out_width = fbdev->panel->x_res - win->out_x;
+	if (win->out_y + win->out_height > fbdev->panel->y_res)
+		win->out_height = fbdev->panel->y_res - win->out_y;
+	if (!win->width || !win->height || !win->out_width || !win->out_height)
+		return 0;
+
+	return fbdev->ctrl->update_window(fbi, win, callback, callback_data);
+}
+EXPORT_SYMBOL(omapfb_update_window_async);
+
+static int omapfb_update_win(struct fb_info *fbi,
+				struct omapfb_update_window *win)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	int ret;
+
+	omapfb_rqueue_lock(plane->fbdev);
+	ret = omapfb_update_window_async(fbi, win, NULL, 0);
+	omapfb_rqueue_unlock(plane->fbdev);
+
+	return ret;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_update_window win;
+	int r;
+
+	if (!fbdev->ctrl->update_window ||
+	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+		return -ENODEV;
+
+	win.x = 0;
+	win.y = 0;
+	win.width = fbi->var.xres;
+	win.height = fbi->var.yres;
+	win.out_x = 0;
+	win.out_y = 0;
+	win.out_width = fbi->var.xres;
+	win.out_height = fbi->var.yres;
+	win.format = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct lcd_panel *panel = fbdev->panel;
+	struct omapfb_plane_info old_info;
+	int r = 0;
+
+	if (pi->pos_x + pi->out_width > panel->x_res ||
+	    pi->pos_y + pi->out_height > panel->y_res)
+		return -EINVAL;
+
+	omapfb_rqueue_lock(fbdev);
+	if (pi->enabled && !fbdev->mem_desc.region[plane->idx].size) {
+		/*
+		 * This plane's memory was freed, can't enable it
+		 * until it's reallocated.
+		 */
+		r = -EINVAL;
+		goto out;
+	}
+	old_info = plane->info;
+	plane->info = *pi;
+	if (pi->enabled) {
+		r = ctrl_change_mode(fbi);
+		if (r < 0) {
+			plane->info = old_info;
+			goto out;
+		}
+	}
+	r = fbdev->ctrl->enable_plane(plane->idx, pi->enabled);
+	if (r < 0) {
+		plane->info = old_info;
+		goto out;
+	}
+out:
+	omapfb_rqueue_unlock(fbdev);
+	return r;
+}
+
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+
+	*pi = plane->info;
+	return 0;
+}
+
+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_mem_region *rg = &fbdev->mem_desc.region[plane->idx];
+	size_t size;
+	int r = 0;
+
+	if (fbdev->ctrl->setup_mem == NULL)
+		return -ENODEV;
+	if (mi->type > OMAPFB_MEMTYPE_MAX)
+		return -EINVAL;
+
+	size = PAGE_ALIGN(mi->size);
+	omapfb_rqueue_lock(fbdev);
+	if (plane->info.enabled) {
+		r = -EBUSY;
+		goto out;
+	}
+	if (rg->size != size || rg->type != mi->type) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+		unsigned long old_size = rg->size;
+		u8	      old_type = rg->type;
+		unsigned long paddr;
+
+		rg->size = size;
+		rg->type = mi->type;
+		/*
+		 * size == 0 is a special case, for which we
+		 * don't check / adjust the screen parameters.
+		 * This isn't a problem since the plane can't
+		 * be reenabled unless its size is > 0.
+		 */
+		if (old_size != size && size) {
+			if (size) {
+				memcpy(new_var, &fbi->var, sizeof(*new_var));
+				r = set_fb_var(fbi, new_var);
+				if (r < 0)
+					goto out;
+			}
+		}
+
+		if (fbdev->ctrl->sync)
+			fbdev->ctrl->sync();
+		r = fbdev->ctrl->setup_mem(plane->idx, size, mi->type, &paddr);
+		if (r < 0) {
+			/* Revert changes. */
+			rg->size = old_size;
+			rg->type = old_type;
+			goto out;
+		}
+		rg->paddr = paddr;
+
+		if (old_size != size) {
+			if (size) {
+				memcpy(&fbi->var, new_var, sizeof(fbi->var));
+				set_fb_fix(fbi);
+			} else {
+				/*
+				 * Set these explicitly to indicate that the
+				 * plane memory is dealloce'd, the other
+				 * screen parameters in var / fix are invalid.
+				 */
+				fbi->fix.smem_start = 0;
+				fbi->fix.smem_len = 0;
+			}
+		}
+	}
+out:
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_mem_region *rg;
+
+	rg = &fbdev->mem_desc.region[plane->idx];
+	memset(mi, 0, sizeof(*mi));
+	mi->size = rg->size;
+	mi->type = rg->type;
+
+	return 0;
+}
+
+static int omapfb_set_color_key(struct omapfb_device *fbdev,
+				struct omapfb_color_key *ck)
+{
+	int r;
+
+	if (!fbdev->ctrl->set_color_key)
+		return -ENODEV;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->set_color_key(ck);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_get_color_key(struct omapfb_device *fbdev,
+				struct omapfb_color_key *ck)
+{
+	int r;
+
+	if (!fbdev->ctrl->get_color_key)
+		return -ENODEV;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->get_color_key(ck);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM];
+static int notifier_inited;
+
+static void omapfb_init_notifier(void)
+{
+	int i;
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+		BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]);
+}
+
+int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
+				omapfb_notifier_callback_t callback,
+				void *callback_data)
+{
+	int r;
+
+	if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+		return -EINVAL;
+
+	if (!notifier_inited) {
+		omapfb_init_notifier();
+		notifier_inited = 1;
+	}
+
+	omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,
+					unsigned long, void *))callback;
+	omapfb_nb->data = callback_data;
+	r = blocking_notifier_chain_register(
+				&omapfb_client_list[omapfb_nb->plane_idx],
+				&omapfb_nb->nb);
+	if (r)
+		return r;
+	if (omapfb_dev != NULL &&
+	    omapfb_dev->ctrl && omapfb_dev->ctrl->bind_client) {
+		omapfb_dev->ctrl->bind_client(omapfb_nb);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omapfb_register_client);
+
+int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb)
+{
+	return blocking_notifier_chain_unregister(
+		&omapfb_client_list[omapfb_nb->plane_idx], &omapfb_nb->nb);
+}
+EXPORT_SYMBOL(omapfb_unregister_client);
+
+void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event)
+{
+	int i;
+
+	if (!notifier_inited)
+		/* no client registered yet */
+		return;
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+		blocking_notifier_call_chain(&omapfb_client_list[i], event,
+				    fbdev->fb_info[i]);
+}
+EXPORT_SYMBOL(omapfb_notify_clients);
+
+static int omapfb_set_update_mode(struct omapfb_device *fbdev,
+				   enum omapfb_update_mode mode)
+{
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->set_update_mode(mode);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
+{
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->get_update_mode();
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static void omapfb_get_caps(struct omapfb_device *fbdev, int plane,
+				     struct omapfb_caps *caps)
+{
+	memset(caps, 0, sizeof(*caps));
+	fbdev->ctrl->get_caps(plane, caps);
+	caps->ctrl |= fbdev->panel->get_caps(fbdev->panel);
+}
+
+/* For lcd testing */
+void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
+{
+	omapfb_rqueue_lock(fbdev);
+	*(u16 *)fbdev->mem_desc.region[0].vaddr = pixval;
+	if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
+		struct omapfb_update_window win;
+
+		memset(&win, 0, sizeof(win));
+		win.width = 2;
+		win.height = 2;
+		win.out_width = 2;
+		win.out_height = 2;
+		fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
+	}
+	omapfb_rqueue_unlock(fbdev);
+}
+EXPORT_SYMBOL(omapfb_write_first_pixel);
+
+/*
+ * Ioctl interface. Part of the kernel mode frame buffer API is duplicated
+ * here to be accessible by user mode code.
+ */
+static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
+			unsigned long arg)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device	*fbdev = plane->fbdev;
+	struct fb_ops		*ops = fbi->fbops;
+	union {
+		struct omapfb_update_window	update_window;
+		struct omapfb_plane_info	plane_info;
+		struct omapfb_mem_info		mem_info;
+		struct omapfb_color_key		color_key;
+		enum omapfb_update_mode		update_mode;
+		struct omapfb_caps		caps;
+		unsigned int		mirror;
+		int			plane_out;
+		int			enable_plane;
+	} p;
+	int r = 0;
+
+	BUG_ON(!ops);
+	switch (cmd) {
+	case OMAPFB_MIRROR:
+		if (get_user(p.mirror, (int __user *)arg))
+			r = -EFAULT;
+		else
+			omapfb_mirror(fbi, p.mirror);
+		break;
+	case OMAPFB_SYNC_GFX:
+		omapfb_sync(fbi);
+		break;
+	case OMAPFB_VSYNC:
+		break;
+	case OMAPFB_SET_UPDATE_MODE:
+		if (get_user(p.update_mode, (int __user *)arg))
+			r = -EFAULT;
+		else
+			r = omapfb_set_update_mode(fbdev, p.update_mode);
+		break;
+	case OMAPFB_GET_UPDATE_MODE:
+		p.update_mode = omapfb_get_update_mode(fbdev);
+		if (put_user(p.update_mode,
+					(enum omapfb_update_mode __user *)arg))
+			r = -EFAULT;
+		break;
+	case OMAPFB_UPDATE_WINDOW_OLD:
+		if (copy_from_user(&p.update_window, (void __user *)arg,
+				   sizeof(struct omapfb_update_window_old)))
+			r = -EFAULT;
+		else {
+			struct omapfb_update_window *u = &p.update_window;
+			u->out_x = u->x;
+			u->out_y = u->y;
+			u->out_width = u->width;
+			u->out_height = u->height;
+			memset(u->reserved, 0, sizeof(u->reserved));
+			r = omapfb_update_win(fbi, u);
+		}
+		break;
+	case OMAPFB_UPDATE_WINDOW:
+		if (copy_from_user(&p.update_window, (void __user *)arg,
+				   sizeof(p.update_window)))
+			r = -EFAULT;
+		else
+			r = omapfb_update_win(fbi, &p.update_window);
+		break;
+	case OMAPFB_SETUP_PLANE:
+		if (copy_from_user(&p.plane_info, (void __user *)arg,
+				   sizeof(p.plane_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_plane(fbi, &p.plane_info);
+		break;
+	case OMAPFB_QUERY_PLANE:
+		if ((r = omapfb_query_plane(fbi, &p.plane_info)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.plane_info,
+				   sizeof(p.plane_info)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_SETUP_MEM:
+		if (copy_from_user(&p.mem_info, (void __user *)arg,
+				   sizeof(p.mem_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_mem(fbi, &p.mem_info);
+		break;
+	case OMAPFB_QUERY_MEM:
+		if ((r = omapfb_query_mem(fbi, &p.mem_info)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.mem_info,
+				   sizeof(p.mem_info)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_SET_COLOR_KEY:
+		if (copy_from_user(&p.color_key, (void __user *)arg,
+				   sizeof(p.color_key)))
+			r = -EFAULT;
+		else
+			r = omapfb_set_color_key(fbdev, &p.color_key);
+		break;
+	case OMAPFB_GET_COLOR_KEY:
+		if ((r = omapfb_get_color_key(fbdev, &p.color_key)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.color_key,
+				 sizeof(p.color_key)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_GET_CAPS:
+		omapfb_get_caps(fbdev, plane->idx, &p.caps);
+		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_LCD_TEST:
+		{
+			int test_num;
+
+			if (get_user(test_num, (int __user *)arg)) {
+				r = -EFAULT;
+				break;
+			}
+			if (!fbdev->panel->run_test) {
+				r = -EINVAL;
+				break;
+			}
+			r = fbdev->panel->run_test(fbdev->panel, test_num);
+			break;
+		}
+	case OMAPFB_CTRL_TEST:
+		{
+			int test_num;
+
+			if (get_user(test_num, (int __user *)arg)) {
+				r = -EFAULT;
+				break;
+			}
+			if (!fbdev->ctrl->run_test) {
+				r = -EINVAL;
+				break;
+			}
+			r = fbdev->ctrl->run_test(test_num);
+			break;
+		}
+	default:
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->mmap(info, vma);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Callback table for the frame buffer framework. Some of these pointers
+ * will be changed according to the current setting of fb_info->accel_flags.
+ */
+static struct fb_ops omapfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open        = omapfb_open,
+	.fb_release     = omapfb_release,
+	.fb_setcolreg	= omapfb_setcolreg,
+	.fb_setcmap	= omapfb_setcmap,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_blank       = omapfb_blank,
+	.fb_ioctl	= omapfb_ioctl,
+	.fb_check_var	= omapfb_check_var,
+	.fb_set_par	= omapfb_set_par,
+	.fb_rotate	= omapfb_rotate,
+	.fb_pan_display = omapfb_pan_display,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Sysfs interface
+ * ---------------------------------------------------------------------------
+ */
+/* omapfbX sysfs entries */
+static ssize_t omapfb_show_caps_num(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int plane;
+	size_t size;
+	struct omapfb_caps caps;
+
+	plane = 0;
+	size = 0;
+	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+		omapfb_get_caps(fbdev, plane, &caps);
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+			"plane#%d %#010x %#010x %#010x\n",
+			plane, caps.ctrl, caps.plane_color, caps.wnd_color);
+		plane++;
+	}
+	return size;
+}
+
+static ssize_t omapfb_show_caps_text(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int i;
+	struct omapfb_caps caps;
+	int plane;
+	size_t size;
+
+	plane = 0;
+	size = 0;
+	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+		omapfb_get_caps(fbdev, plane, &caps);
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 "plane#%d:\n", plane);
+		for (i = 0; i < ARRAY_SIZE(ctrl_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (ctrl_caps[i].flag & caps.ctrl)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					" %s\n", ctrl_caps[i].name);
+		}
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 " plane colors:\n");
+		for (i = 0; i < ARRAY_SIZE(color_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (color_caps[i].flag & caps.plane_color)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					"  %s\n", color_caps[i].name);
+		}
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 " window colors:\n");
+		for (i = 0; i < ARRAY_SIZE(color_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (color_caps[i].flag & caps.wnd_color)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					"  %s\n", color_caps[i].name);
+		}
+
+		plane++;
+	}
+	return size;
+}
+
+static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
+static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
+
+/* panel sysfs entries */
+static ssize_t omapfb_show_panel_name(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
+}
+
+static ssize_t omapfb_show_bklight_level(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int r;
+
+	if (fbdev->panel->get_bklight_level) {
+		r = snprintf(buf, PAGE_SIZE, "%d\n",
+			     fbdev->panel->get_bklight_level(fbdev->panel));
+	} else
+		r = -ENODEV;
+	return r;
+}
+
+static ssize_t omapfb_store_bklight_level(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t size)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int r;
+
+	if (fbdev->panel->set_bklight_level) {
+		unsigned int level;
+
+		if (sscanf(buf, "%10d", &level) == 1) {
+			r = fbdev->panel->set_bklight_level(fbdev->panel,
+							    level);
+		} else
+			r = -EINVAL;
+	} else
+		r = -ENODEV;
+	return r ? r : size;
+}
+
+static ssize_t omapfb_show_bklight_max(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int r;
+
+	if (fbdev->panel->get_bklight_level) {
+		r = snprintf(buf, PAGE_SIZE, "%d\n",
+			     fbdev->panel->get_bklight_max(fbdev->panel));
+	} else
+		r = -ENODEV;
+	return r;
+}
+
+static struct device_attribute dev_attr_panel_name =
+	__ATTR(name, 0444, omapfb_show_panel_name, NULL);
+static DEVICE_ATTR(backlight_level, 0664,
+		   omapfb_show_bklight_level, omapfb_store_bklight_level);
+static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
+
+static struct attribute *panel_attrs[] = {
+	&dev_attr_panel_name.attr,
+	&dev_attr_backlight_level.attr,
+	&dev_attr_backlight_max.attr,
+	NULL,
+};
+
+static struct attribute_group panel_attr_grp = {
+	.name  = "panel",
+	.attrs = panel_attrs,
+};
+
+/* ctrl sysfs entries */
+static ssize_t omapfb_show_ctrl_name(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
+}
+
+static struct device_attribute dev_attr_ctrl_name =
+	__ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
+
+static struct attribute *ctrl_attrs[] = {
+	&dev_attr_ctrl_name.attr,
+	NULL,
+};
+
+static struct attribute_group ctrl_attr_grp = {
+	.name  = "ctrl",
+	.attrs = ctrl_attrs,
+};
+
+static int omapfb_register_sysfs(struct omapfb_device *fbdev)
+{
+	int r;
+
+	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
+		goto fail0;
+
+	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
+		goto fail1;
+
+	if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
+		goto fail2;
+
+	if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
+		goto fail3;
+
+	return 0;
+fail3:
+	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+fail2:
+	device_remove_file(fbdev->dev, &dev_attr_caps_text);
+fail1:
+	device_remove_file(fbdev->dev, &dev_attr_caps_num);
+fail0:
+	dev_err(fbdev->dev, "unable to register sysfs interface\n");
+	return r;
+}
+
+static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
+{
+	sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
+	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+	device_remove_file(fbdev->dev, &dev_attr_caps_num);
+	device_remove_file(fbdev->dev, &dev_attr_caps_text);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LDM callbacks
+ * ---------------------------------------------------------------------------
+ */
+/* Initialize system fb_info object and set the default video mode.
+ * The frame buffer memory already allocated by lcddma_init
+ */
+static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
+{
+	struct fb_var_screeninfo	*var = &info->var;
+	struct fb_fix_screeninfo	*fix = &info->fix;
+	int				r = 0;
+
+	info->fbops = &omapfb_ops;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
+
+	info->pseudo_palette = fbdev->pseudo_palette;
+
+	var->accel_flags  = def_accel ? FB_ACCELF_TEXT : 0;
+	var->xres = def_vxres;
+	var->yres = def_vyres;
+	var->xres_virtual = def_vxres;
+	var->yres_virtual = def_vyres;
+	var->rotate	  = def_rotate;
+	var->bits_per_pixel = fbdev->panel->bpp;
+
+	set_fb_var(info, var);
+	set_fb_fix(info);
+
+	r = fb_alloc_cmap(&info->cmap, 16, 0);
+	if (r != 0)
+		dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
+	return r;
+}
+
+/* Release the fb_info object */
+static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi)
+{
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+static void planes_cleanup(struct omapfb_device *fbdev)
+{
+	int i;
+
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		if (fbdev->fb_info[i] == NULL)
+			break;
+		fbinfo_cleanup(fbdev, fbdev->fb_info[i]);
+		framebuffer_release(fbdev->fb_info[i]);
+	}
+}
+
+static int planes_init(struct omapfb_device *fbdev)
+{
+	struct fb_info *fbi;
+	int i;
+	int r;
+
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		struct omapfb_plane_struct *plane;
+		fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct),
+					fbdev->dev);
+		if (fbi == NULL) {
+			dev_err(fbdev->dev,
+				"unable to allocate memory for plane info\n");
+			planes_cleanup(fbdev);
+			return -ENOMEM;
+		}
+		plane = fbi->par;
+		plane->idx = i;
+		plane->fbdev = fbdev;
+		plane->info.mirror = def_mirror;
+		fbdev->fb_info[i] = fbi;
+
+		if ((r = fbinfo_init(fbdev, fbi)) < 0) {
+			framebuffer_release(fbi);
+			planes_cleanup(fbdev);
+			return r;
+		}
+		plane->info.out_width = fbi->var.xres;
+		plane->info.out_height = fbi->var.yres;
+	}
+	return 0;
+}
+
+/*
+ * Free driver resources. Can be called to rollback an aborted initialization
+ * sequence.
+ */
+static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
+{
+	int i;
+
+	switch (state) {
+	case OMAPFB_ACTIVE:
+		for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
+			unregister_framebuffer(fbdev->fb_info[i]);
+	case 7:
+		omapfb_unregister_sysfs(fbdev);
+	case 6:
+		fbdev->panel->disable(fbdev->panel);
+	case 5:
+		omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+	case 4:
+		planes_cleanup(fbdev);
+	case 3:
+		ctrl_cleanup(fbdev);
+	case 2:
+		fbdev->panel->cleanup(fbdev->panel);
+	case 1:
+		dev_set_drvdata(fbdev->dev, NULL);
+		kfree(fbdev);
+	case 0:
+		/* nothing to free */
+		break;
+	default:
+		BUG();
+	}
+}
+
+static int omapfb_find_ctrl(struct omapfb_device *fbdev)
+{
+	struct omapfb_platform_data *conf;
+	char name[17];
+	int i;
+
+	conf = fbdev->dev->platform_data;
+
+	fbdev->ctrl = NULL;
+
+	strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1);
+	name[sizeof(name) - 1] = '\0';
+
+	if (strcmp(name, "internal") == 0) {
+		fbdev->ctrl = fbdev->int_ctrl;
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
+		dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name);
+		if (strcmp(ctrls[i]->name, name) == 0) {
+			fbdev->ctrl = ctrls[i];
+			break;
+		}
+	}
+
+	if (fbdev->ctrl == NULL) {
+		dev_dbg(fbdev->dev, "ctrl %s not supported\n", name);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void check_required_callbacks(struct omapfb_device *fbdev)
+{
+#define _C(x) (fbdev->ctrl->x != NULL)
+#define _P(x) (fbdev->panel->x != NULL)
+	BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL);
+	BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
+		 _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) &&
+		 _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
+		 _P(get_caps)));
+#undef _P
+#undef _C
+}
+
+/*
+ * Called by LDM binding to probe and attach a new device.
+ * Initialization sequence:
+ *   1. allocate system omapfb_device structure
+ *   2. select controller type according to platform configuration
+ *      init LCD panel
+ *   3. init LCD controller and LCD DMA
+ *   4. init system fb_info structure for all planes
+ *   5. setup video mode for first plane and enable it
+ *   6. enable LCD panel
+ *   7. register sysfs attributes
+ *   OMAPFB_ACTIVE: register system fb_info structure for all planes
+ */
+static int omapfb_do_probe(struct platform_device *pdev,
+				struct lcd_panel *panel)
+{
+	struct omapfb_device	*fbdev = NULL;
+	int			init_state;
+	unsigned long		phz, hhz, vhz;
+	unsigned long		vram;
+	int			i;
+	int			r = 0;
+
+	init_state = 0;
+
+	if (pdev->num_resources != 0) {
+		dev_err(&pdev->dev, "probed for an unknown device\n");
+		r = -ENODEV;
+		goto cleanup;
+	}
+
+	if (pdev->dev.platform_data == NULL) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		r = -ENOENT;
+		goto cleanup;
+	}
+
+	fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL);
+	if (fbdev == NULL) {
+		dev_err(&pdev->dev,
+			"unable to allocate memory for device info\n");
+		r = -ENOMEM;
+		goto cleanup;
+	}
+	init_state++;
+
+	fbdev->dev = &pdev->dev;
+	fbdev->panel = panel;
+	platform_set_drvdata(pdev, fbdev);
+
+	mutex_init(&fbdev->rqueue_mutex);
+
+#ifdef CONFIG_ARCH_OMAP1
+	fbdev->int_ctrl = &omap1_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+	fbdev->ext_if = &omap1_ext_if;
+#endif
+#else	/* OMAP2 */
+	fbdev->int_ctrl = &omap2_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+	fbdev->ext_if = &omap2_ext_if;
+#endif
+#endif
+	if (omapfb_find_ctrl(fbdev) < 0) {
+		dev_err(fbdev->dev,
+			"LCD controller not found, board not supported\n");
+		r = -ENODEV;
+		goto cleanup;
+	}
+
+	r = fbdev->panel->init(fbdev->panel, fbdev);
+	if (r)
+		goto cleanup;
+
+	pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
+
+	def_vxres = def_vxres ? : fbdev->panel->x_res;
+	def_vyres = def_vyres ? : fbdev->panel->y_res;
+
+	init_state++;
+
+	r = ctrl_init(fbdev);
+	if (r)
+		goto cleanup;
+	if (fbdev->ctrl->mmap != NULL)
+		omapfb_ops.fb_mmap = omapfb_mmap;
+	init_state++;
+
+	check_required_callbacks(fbdev);
+
+	r = planes_init(fbdev);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+#ifdef CONFIG_FB_OMAP_DMA_TUNE
+	/* Set DMA priority for EMIFF access to highest */
+	if (cpu_class_is_omap1())
+		omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
+#endif
+
+	r = ctrl_change_mode(fbdev->fb_info[0]);
+	if (r) {
+		dev_err(fbdev->dev, "mode setting failed\n");
+		goto cleanup;
+	}
+
+	/* GFX plane is enabled by default */
+	r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+	if (r)
+		goto cleanup;
+
+	omapfb_set_update_mode(fbdev, manual_update ?
+				   OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
+	init_state++;
+
+	r = fbdev->panel->enable(fbdev->panel);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+	r = omapfb_register_sysfs(fbdev);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+	vram = 0;
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		r = register_framebuffer(fbdev->fb_info[i]);
+		if (r != 0) {
+			dev_err(fbdev->dev,
+				"registering framebuffer %d failed\n", i);
+			goto cleanup;
+		}
+		vram += fbdev->mem_desc.region[i].size;
+	}
+
+	fbdev->state = OMAPFB_ACTIVE;
+
+	panel = fbdev->panel;
+	phz = panel->pixel_clock * 1000;
+	hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
+	vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
+
+	omapfb_dev = fbdev;
+
+	pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n",
+			vram, fbdev->mem_desc.region_cnt);
+	pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz "
+			"vfreq %lu.%lu Hz\n",
+			phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
+
+	return 0;
+
+cleanup:
+	omapfb_free_resources(fbdev, init_state);
+
+	return r;
+}
+
+static int omapfb_probe(struct platform_device *pdev)
+{
+	BUG_ON(fbdev_pdev != NULL);
+
+	/* Delay actual initialization until the LCD is registered */
+	fbdev_pdev = pdev;
+	if (fbdev_panel != NULL)
+		omapfb_do_probe(fbdev_pdev, fbdev_panel);
+	return 0;
+}
+
+void omapfb_register_panel(struct lcd_panel *panel)
+{
+	BUG_ON(fbdev_panel != NULL);
+
+	fbdev_panel = panel;
+	if (fbdev_pdev != NULL)
+		omapfb_do_probe(fbdev_pdev, fbdev_panel);
+}
+
+/* Called when the device is being detached from the driver */
+static int omapfb_remove(struct platform_device *pdev)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+	enum omapfb_state saved_state = fbdev->state;
+
+	/* FIXME: wait till completion of pending events */
+
+	fbdev->state = OMAPFB_DISABLED;
+	omapfb_free_resources(fbdev, saved_state);
+
+	return 0;
+}
+
+/* PM suspend */
+static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+	omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]);
+
+	return 0;
+}
+
+/* PM resume */
+static int omapfb_resume(struct platform_device *pdev)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+	omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]);
+	return 0;
+}
+
+static struct platform_driver omapfb_driver = {
+	.probe		= omapfb_probe,
+	.remove		= omapfb_remove,
+	.suspend	= omapfb_suspend,
+	.resume		= omapfb_resume,
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+#ifndef MODULE
+
+/* Process kernel command line parameters */
+static int __init omapfb_setup(char *options)
+{
+	char *this_opt = NULL;
+	int r = 0;
+
+	pr_debug("omapfb: options %s\n", options);
+
+	if (!options || !*options)
+		return 0;
+
+	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "accel", 5))
+			def_accel = 1;
+		else if (!strncmp(this_opt, "vram:", 5)) {
+			char *suffix;
+			unsigned long vram;
+			vram = (simple_strtoul(this_opt + 5, &suffix, 0));
+			switch (suffix[0]) {
+			case '\0':
+				break;
+			case 'm':
+			case 'M':
+				vram *= 1024;
+				/* Fall through */
+			case 'k':
+			case 'K':
+				vram *= 1024;
+				break;
+			default:
+				pr_debug("omapfb: invalid vram suffix %c\n",
+					 suffix[0]);
+				r = -1;
+			}
+			def_vram[def_vram_cnt++] = vram;
+		}
+		else if (!strncmp(this_opt, "vxres:", 6))
+			def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "vyres:", 6))
+			def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "rotate:", 7))
+			def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
+		else if (!strncmp(this_opt, "mirror:", 7))
+			def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
+		else if (!strncmp(this_opt, "manual_update", 13))
+			manual_update = 1;
+		else {
+			pr_debug("omapfb: invalid option\n");
+			r = -1;
+		}
+	}
+
+	return r;
+}
+
+#endif
+
+/* Register both the driver and the device */
+static int __init omapfb_init(void)
+{
+#ifndef MODULE
+	char *option;
+
+	if (fb_get_options("omapfb", &option))
+		return -ENODEV;
+	omapfb_setup(option);
+#endif
+	/* Register the driver with LDM */
+	if (platform_driver_register(&omapfb_driver)) {
+		pr_debug("failed to register omapfb driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit omapfb_cleanup(void)
+{
+	platform_driver_unregister(&omapfb_driver);
+}
+
+module_param_named(accel, def_accel, uint, 0664);
+module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664);
+module_param_named(vxres, def_vxres, long, 0664);
+module_param_named(vyres, def_vyres, long, 0664);
+module_param_named(rotate, def_rotate, uint, 0664);
+module_param_named(mirror, def_mirror, uint, 0664);
+module_param_named(manual_update, manual_update, bool, 0664);
+
+module_init(omapfb_init);
+module_exit(omapfb_cleanup);
+
+MODULE_DESCRIPTION("TI OMAP framebuffer driver");
+MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
new file mode 100644
index 0000000..2b42698
--- /dev/null
+++ b/drivers/video/omap/rfbi.c
@@ -0,0 +1,588 @@
+/*
+ * OMAP2 Remote Frame Buffer Interface support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *	   Imre Deak <imre.deak@nokia.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.
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/arch/omapfb.h>
+
+#include "dispc.h"
+
+/* To work around an RFBI transfer rate limitation */
+#define OMAP_RFBI_RATE_LIMIT	1
+
+#define RFBI_BASE		0x48050800
+#define RFBI_REVISION		0x0000
+#define RFBI_SYSCONFIG		0x0010
+#define RFBI_SYSSTATUS		0x0014
+#define RFBI_CONTROL		0x0040
+#define RFBI_PIXEL_CNT		0x0044
+#define RFBI_LINE_NUMBER	0x0048
+#define RFBI_CMD		0x004c
+#define RFBI_PARAM		0x0050
+#define RFBI_DATA		0x0054
+#define RFBI_READ		0x0058
+#define RFBI_STATUS		0x005c
+#define RFBI_CONFIG0		0x0060
+#define RFBI_ONOFF_TIME0	0x0064
+#define RFBI_CYCLE_TIME0	0x0068
+#define RFBI_DATA_CYCLE1_0	0x006c
+#define RFBI_DATA_CYCLE2_0	0x0070
+#define RFBI_DATA_CYCLE3_0	0x0074
+#define RFBI_VSYNC_WIDTH	0x0090
+#define RFBI_HSYNC_WIDTH	0x0094
+
+#define DISPC_BASE		0x48050400
+#define DISPC_CONTROL		0x0040
+
+static struct {
+	u32		base;
+	void		(*lcdc_callback)(void *data);
+	void		*lcdc_callback_data;
+	unsigned long	l4_khz;
+	int		bits_per_cycle;
+	struct omapfb_device *fbdev;
+	struct clk	*dss_ick;
+	struct clk	*dss1_fck;
+	unsigned	tearsync_pin_cnt;
+	unsigned	tearsync_mode;
+} rfbi;
+
+static inline void rfbi_write_reg(int idx, u32 val)
+{
+	__raw_writel(val, rfbi.base + idx);
+}
+
+static inline u32 rfbi_read_reg(int idx)
+{
+	return __raw_readl(rfbi.base + idx);
+}
+
+static int rfbi_get_clocks(void)
+{
+	if (IS_ERR((rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "dss_ick")))) {
+		dev_err(rfbi.fbdev->dev, "can't get dss_ick");
+		return PTR_ERR(rfbi.dss_ick);
+	}
+
+	if (IS_ERR((rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck")))) {
+		dev_err(rfbi.fbdev->dev, "can't get dss1_fck");
+		clk_put(rfbi.dss_ick);
+		return PTR_ERR(rfbi.dss1_fck);
+	}
+
+	return 0;
+}
+
+static void rfbi_put_clocks(void)
+{
+	clk_put(rfbi.dss1_fck);
+	clk_put(rfbi.dss_ick);
+}
+
+static void rfbi_enable_clocks(int enable)
+{
+	if (enable) {
+		clk_enable(rfbi.dss_ick);
+		clk_enable(rfbi.dss1_fck);
+	} else {
+		clk_disable(rfbi.dss1_fck);
+		clk_disable(rfbi.dss_ick);
+	}
+}
+
+
+#ifdef VERBOSE
+static void rfbi_print_timings(void)
+{
+	u32 l;
+	u32 time;
+
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	time = 1000000000 / rfbi.l4_khz;
+	if (l & (1 << 4))
+		time *= 2;
+
+	dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
+	l = rfbi_read_reg(RFBI_ONOFF_TIME0);
+	dev_dbg(rfbi.fbdev->dev,
+		"CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
+		"REONTIME %d, REOFFTIME %d\n",
+		l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
+		(l >> 20) & 0x0f, (l >> 24) & 0x3f);
+
+	l = rfbi_read_reg(RFBI_CYCLE_TIME0);
+	dev_dbg(rfbi.fbdev->dev,
+		"WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
+		"ACCESSTIME %d\n",
+		(l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
+		(l >> 22) & 0x3f);
+}
+#else
+static void rfbi_print_timings(void) {}
+#endif
+
+static void rfbi_set_timings(const struct extif_timings *t)
+{
+	u32 l;
+
+	BUG_ON(!t->converted);
+
+	rfbi_enable_clocks(1);
+	rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
+	rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
+
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	l &= ~(1 << 4);
+	l |= (t->tim[2] ? 1 : 0) << 4;
+	rfbi_write_reg(RFBI_CONFIG0, l);
+
+	rfbi_print_timings();
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+	*clk_period = 1000000000 / rfbi.l4_khz;
+	*max_clk_div = 2;
+}
+
+static int ps_to_rfbi_ticks(int time, int div)
+{
+	unsigned long tick_ps;
+	int ret;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = 1000000000 / (rfbi.l4_khz) * div;
+
+	ret = (time + tick_ps - 1) / tick_ps;
+
+	return ret;
+}
+
+#ifdef OMAP_RFBI_RATE_LIMIT
+static unsigned long rfbi_get_max_tx_rate(void)
+{
+	unsigned long	l4_rate, dss1_rate;
+	int		min_l4_ticks = 0;
+	int		i;
+
+	/* According to TI this can't be calculated so make the
+	 * adjustments for a couple of known frequencies and warn for
+	 * others.
+	 */
+	static const struct {
+		unsigned long l4_clk;		/* HZ */
+		unsigned long dss1_clk;		/* HZ */
+		unsigned long min_l4_ticks;
+	} ftab[] = {
+		{ 55,	132,	7, },		/* 7.86 MPix/s */
+		{ 110,	110,	12, },		/* 9.16 MPix/s */
+		{ 110,	132,	10, },		/* 11   Mpix/s */
+		{ 120,	120,	10, },		/* 12   Mpix/s */
+		{ 133,	133,	10, },		/* 13.3 Mpix/s */
+	};
+
+	l4_rate = rfbi.l4_khz / 1000;
+	dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000;
+
+	for (i = 0; i < ARRAY_SIZE(ftab); i++) {
+		/* Use a window instead of an exact match, to account
+		 * for different DPLL multiplier / divider pairs.
+		 */
+		if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
+		    abs(ftab[i].dss1_clk - dss1_rate) < 3) {
+			min_l4_ticks = ftab[i].min_l4_ticks;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(ftab)) {
+		/* Can't be sure, return anyway the maximum not
+		 * rate-limited. This might cause a problem only for the
+		 * tearing synchronisation.
+		 */
+		dev_err(rfbi.fbdev->dev,
+			"can't determine maximum RFBI transfer rate\n");
+		return rfbi.l4_khz * 1000;
+	}
+	return rfbi.l4_khz * 1000 / min_l4_ticks;
+}
+#else
+static int rfbi_get_max_tx_rate(void)
+{
+	return rfbi.l4_khz * 1000;
+}
+#endif
+
+
+static int rfbi_convert_timings(struct extif_timings *t)
+{
+	u32 l;
+	int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
+	int actim, recyc, wecyc;
+	int div = t->clk_div;
+
+	if (div <= 0 || div > 2)
+		return -1;
+
+	/* Make sure that after conversion it still holds that:
+	 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
+	 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
+	 */
+	weon = ps_to_rfbi_ticks(t->we_on_time, div);
+	weoff = ps_to_rfbi_ticks(t->we_off_time, div);
+	if (weoff <= weon)
+		weoff = weon + 1;
+	if (weon > 0x0f)
+		return -1;
+	if (weoff > 0x3f)
+		return -1;
+
+	reon = ps_to_rfbi_ticks(t->re_on_time, div);
+	reoff = ps_to_rfbi_ticks(t->re_off_time, div);
+	if (reoff <= reon)
+		reoff = reon + 1;
+	if (reon > 0x0f)
+		return -1;
+	if (reoff > 0x3f)
+		return -1;
+
+	cson = ps_to_rfbi_ticks(t->cs_on_time, div);
+	csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
+	if (csoff <= cson)
+		csoff = cson + 1;
+	if (csoff < max(weoff, reoff))
+		csoff = max(weoff, reoff);
+	if (cson > 0x0f)
+		return -1;
+	if (csoff > 0x3f)
+		return -1;
+
+	l =  cson;
+	l |= csoff << 4;
+	l |= weon  << 10;
+	l |= weoff << 14;
+	l |= reon  << 20;
+	l |= reoff << 24;
+
+	t->tim[0] = l;
+
+	actim = ps_to_rfbi_ticks(t->access_time, div);
+	if (actim <= reon)
+		actim = reon + 1;
+	if (actim > 0x3f)
+		return -1;
+
+	wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
+	if (wecyc < weoff)
+		wecyc = weoff;
+	if (wecyc > 0x3f)
+		return -1;
+
+	recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
+	if (recyc < reoff)
+		recyc = reoff;
+	if (recyc > 0x3f)
+		return -1;
+
+	cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
+	if (cs_pulse > 0x3f)
+		return -1;
+
+	l =  wecyc;
+	l |= recyc    << 6;
+	l |= cs_pulse << 12;
+	l |= actim    << 22;
+
+	t->tim[1] = l;
+
+	t->tim[2] = div - 1;
+
+	t->converted = 1;
+
+	return 0;
+}
+
+static int rfbi_setup_tearsync(unsigned pin_cnt,
+			       unsigned hs_pulse_time, unsigned vs_pulse_time,
+			       int hs_pol_inv, int vs_pol_inv, int extif_div)
+{
+	int hs, vs;
+	int min;
+	u32 l;
+
+	if (pin_cnt != 1 && pin_cnt != 2)
+		return -EINVAL;
+
+	hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
+	vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
+	if (hs < 2)
+		return -EDOM;
+	if (pin_cnt == 2)
+		min = 2;
+	else
+		min = 4;
+	if (vs < min)
+		return -EDOM;
+	if (vs == hs)
+		return -EINVAL;
+	rfbi.tearsync_pin_cnt = pin_cnt;
+	dev_dbg(rfbi.fbdev->dev,
+		"setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n",
+		pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv);
+
+	rfbi_enable_clocks(1);
+	rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
+	rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
+
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	if (hs_pol_inv)
+		l &= ~(1 << 21);
+	else
+		l |= 1 << 21;
+	if (vs_pol_inv)
+		l &= ~(1 << 20);
+	else
+		l |= 1 << 20;
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+
+static int rfbi_enable_tearsync(int enable, unsigned line)
+{
+	u32 l;
+
+	dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n",
+		enable, line, rfbi.tearsync_mode);
+	if (line > (1 << 11) - 1)
+		return -EINVAL;
+
+	rfbi_enable_clocks(1);
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	l &= ~(0x3 << 2);
+	if (enable) {
+		rfbi.tearsync_mode = rfbi.tearsync_pin_cnt;
+		l |= rfbi.tearsync_mode << 2;
+	} else
+		rfbi.tearsync_mode = 0;
+	rfbi_write_reg(RFBI_CONFIG0, l);
+	rfbi_write_reg(RFBI_LINE_NUMBER, line);
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+
+static void rfbi_write_command(const void *buf, unsigned int len)
+{
+	rfbi_enable_clocks(1);
+	if (rfbi.bits_per_cycle == 16) {
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_CMD, *w++);
+	} else {
+		const u8 *b = buf;
+		BUG_ON(rfbi.bits_per_cycle != 8);
+		for (; len; len--)
+			rfbi_write_reg(RFBI_CMD, *b++);
+	}
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_read_data(void *buf, unsigned int len)
+{
+	rfbi_enable_clocks(1);
+	if (rfbi.bits_per_cycle == 16) {
+		u16 *w = buf;
+		BUG_ON(len & ~1);
+		for (; len; len -= 2) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*w++ = rfbi_read_reg(RFBI_READ);
+		}
+	} else {
+		u8 *b = buf;
+		BUG_ON(rfbi.bits_per_cycle != 8);
+		for (; len; len--) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*b++ = rfbi_read_reg(RFBI_READ);
+		}
+	}
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_write_data(const void *buf, unsigned int len)
+{
+	rfbi_enable_clocks(1);
+	if (rfbi.bits_per_cycle == 16) {
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_PARAM, *w++);
+	} else {
+		const u8 *b = buf;
+		BUG_ON(rfbi.bits_per_cycle != 8);
+		for (; len; len--)
+			rfbi_write_reg(RFBI_PARAM, *b++);
+	}
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_transfer_area(int width, int height,
+				void (callback)(void * data), void *data)
+{
+	u32 w;
+
+	BUG_ON(callback == NULL);
+
+	rfbi_enable_clocks(1);
+	omap_dispc_set_lcd_size(width, height);
+
+	rfbi.lcdc_callback = callback;
+	rfbi.lcdc_callback_data = data;
+
+	rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
+
+	w = rfbi_read_reg(RFBI_CONTROL);
+	w |= 1;				/* enable */
+	if (!rfbi.tearsync_mode)
+		w |= 1 << 4;		/* internal trigger, reset by HW */
+	rfbi_write_reg(RFBI_CONTROL, w);
+
+	omap_dispc_enable_lcd_out(1);
+}
+
+static inline void _stop_transfer(void)
+{
+	u32 w;
+
+	w = rfbi_read_reg(RFBI_CONTROL);
+	rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_dma_callback(void *data)
+{
+	_stop_transfer();
+	rfbi.lcdc_callback(rfbi.lcdc_callback_data);
+}
+
+static void rfbi_set_bits_per_cycle(int bpc)
+{
+	u32 l;
+
+	rfbi_enable_clocks(1);
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	l &= ~(0x03 << 0);
+
+	switch (bpc) {
+	case 8:
+		break;
+	case 16:
+		l |= 3;
+		break;
+	default:
+		BUG();
+	}
+	rfbi_write_reg(RFBI_CONFIG0, l);
+	rfbi.bits_per_cycle = bpc;
+	rfbi_enable_clocks(0);
+}
+
+static int rfbi_init(struct omapfb_device *fbdev)
+{
+	u32 l;
+	int r;
+
+	rfbi.fbdev = fbdev;
+	rfbi.base = io_p2v(RFBI_BASE);
+
+	if ((r = rfbi_get_clocks()) < 0)
+		return r;
+	rfbi_enable_clocks(1);
+
+	rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
+
+	/* Reset */
+	rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
+	while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
+
+	l = rfbi_read_reg(RFBI_SYSCONFIG);
+	/* Enable autoidle and smart-idle */
+	l |= (1 << 0) | (2 << 3);
+	rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+	/* 16-bit interface, ITE trigger mode, 16-bit data */
+	l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
+	l |= (0 << 9) | (1 << 20) | (1 << 21);
+	rfbi_write_reg(RFBI_CONFIG0, l);
+
+	rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
+
+	l = rfbi_read_reg(RFBI_CONTROL);
+	/* Select CS0, clear bypass mode */
+	l = (0x01 << 2);
+	rfbi_write_reg(RFBI_CONTROL, l);
+
+	if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
+		dev_err(fbdev->dev, "can't get DISPC irq\n");
+		rfbi_enable_clocks(0);
+		return r;
+	}
+
+	l = rfbi_read_reg(RFBI_REVISION);
+	pr_info("omapfb: RFBI version %d.%d initialized\n",
+		(l >> 4) & 0x0f, l & 0x0f);
+
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+
+static void rfbi_cleanup(void)
+{
+	omap_dispc_free_irq();
+	rfbi_put_clocks();
+}
+
+const struct lcd_ctrl_extif omap2_ext_if = {
+	.init			= rfbi_init,
+	.cleanup		= rfbi_cleanup,
+	.get_clk_info		= rfbi_get_clk_info,
+	.get_max_tx_rate	= rfbi_get_max_tx_rate,
+	.set_bits_per_cycle	= rfbi_set_bits_per_cycle,
+	.convert_timings	= rfbi_convert_timings,
+	.set_timings		= rfbi_set_timings,
+	.write_command		= rfbi_write_command,
+	.read_data		= rfbi_read_data,
+	.write_data		= rfbi_write_data,
+	.transfer_area		= rfbi_transfer_area,
+	.setup_tearsync		= rfbi_setup_tearsync,
+	.enable_tearsync	= rfbi_enable_tearsync,
+
+	.max_transmit_size	= (u32) ~0,
+};
+
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
new file mode 100644
index 0000000..81dbcf5
--- /dev/null
+++ b/drivers/video/omap/sossi.c
@@ -0,0 +1,686 @@
+/*
+ * OMAP1 Special OptimiSed Screen Interface support
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.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.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#include "lcdc.h"
+
+#define MODULE_NAME		"omapfb-sossi"
+
+#define OMAP_SOSSI_BASE         0xfffbac00
+#define SOSSI_ID_REG		0x00
+#define SOSSI_INIT1_REG		0x04
+#define SOSSI_INIT2_REG		0x08
+#define SOSSI_INIT3_REG		0x0c
+#define SOSSI_FIFO_REG		0x10
+#define SOSSI_REOTABLE_REG	0x14
+#define SOSSI_TEARING_REG	0x18
+#define SOSSI_INIT1B_REG	0x1c
+#define SOSSI_FIFOB_REG		0x20
+
+#define DMA_GSCR          0xfffedc04
+#define DMA_LCD_CCR       0xfffee3c2
+#define DMA_LCD_CTRL      0xfffee3c4
+#define DMA_LCD_LCH_CTRL  0xfffee3ea
+
+#define CONF_SOSSI_RESET_R      (1 << 23)
+
+#define RD_ACCESS		0
+#define WR_ACCESS		1
+
+#define SOSSI_MAX_XMIT_BYTES	(512 * 1024)
+
+static struct {
+	void __iomem	*base;
+	struct clk	*fck;
+	unsigned long	fck_hz;
+	spinlock_t	lock;
+	int		bus_pick_count;
+	int		bus_pick_width;
+	int		tearsync_mode;
+	int		tearsync_line;
+	void		(*lcdc_callback)(void *data);
+	void		*lcdc_callback_data;
+	int		vsync_dma_pending;
+	/* timing for read and write access */
+	int		clk_div;
+	u8		clk_tw0[2];
+	u8		clk_tw1[2];
+	/*
+	 * if last_access is the same as current we don't have to change
+	 * the timings
+	 */
+	int		last_access;
+
+	struct omapfb_device	*fbdev;
+} sossi;
+
+static inline u32 sossi_read_reg(int reg)
+{
+	return readl(sossi.base + reg);
+}
+
+static inline u16 sossi_read_reg16(int reg)
+{
+	return readw(sossi.base + reg);
+}
+
+static inline u8 sossi_read_reg8(int reg)
+{
+	return readb(sossi.base + reg);
+}
+
+static inline void sossi_write_reg(int reg, u32 value)
+{
+	writel(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg16(int reg, u16 value)
+{
+	writew(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg8(int reg, u8 value)
+{
+	writeb(value, sossi.base + reg);
+}
+
+static void sossi_set_bits(int reg, u32 bits)
+{
+	sossi_write_reg(reg, sossi_read_reg(reg) | bits);
+}
+
+static void sossi_clear_bits(int reg, u32 bits)
+{
+	sossi_write_reg(reg, sossi_read_reg(reg) & ~bits);
+}
+
+#define HZ_TO_PS(x)	(1000000000 / (x / 1000))
+
+static u32 ps_to_sossi_ticks(u32 ps, int div)
+{
+	u32 clk_period = HZ_TO_PS(sossi.fck_hz) * div;
+	return (clk_period + ps - 1) / clk_period;
+}
+
+static int calc_rd_timings(struct extif_timings *t)
+{
+	u32 tw0, tw1;
+	int reon, reoff, recyc, actim;
+	int div = t->clk_div;
+
+	/*
+	 * Make sure that after conversion it still holds that:
+	 * reoff > reon, recyc >= reoff, actim > reon
+	 */
+	reon = ps_to_sossi_ticks(t->re_on_time, div);
+	/* reon will be exactly one sossi tick */
+	if (reon > 1)
+		return -1;
+
+	reoff = ps_to_sossi_ticks(t->re_off_time, div);
+
+	if (reoff <= reon)
+		reoff = reon + 1;
+
+	tw0 = reoff - reon;
+	if (tw0 > 0x10)
+		return -1;
+
+	recyc = ps_to_sossi_ticks(t->re_cycle_time, div);
+	if (recyc <= reoff)
+		recyc = reoff + 1;
+
+	tw1 = recyc - tw0;
+	/* values less then 3 result in the SOSSI block resetting itself */
+	if (tw1 < 3)
+		tw1 = 3;
+	if (tw1 > 0x40)
+		return -1;
+
+	actim = ps_to_sossi_ticks(t->access_time, div);
+	if (actim < reoff)
+		actim++;
+	/*
+	 * access time (data hold time) will be exactly one sossi
+	 * tick
+	 */
+	if (actim - reoff > 1)
+		return -1;
+
+	t->tim[0] = tw0 - 1;
+	t->tim[1] = tw1 - 1;
+
+	return 0;
+}
+
+static int calc_wr_timings(struct extif_timings *t)
+{
+	u32 tw0, tw1;
+	int weon, weoff, wecyc;
+	int div = t->clk_div;
+
+	/*
+	 * Make sure that after conversion it still holds that:
+	 * weoff > weon, wecyc >= weoff
+	 */
+	weon = ps_to_sossi_ticks(t->we_on_time, div);
+	/* weon will be exactly one sossi tick */
+	if (weon > 1)
+		return -1;
+
+	weoff = ps_to_sossi_ticks(t->we_off_time, div);
+	if (weoff <= weon)
+		weoff = weon + 1;
+	tw0 = weoff - weon;
+	if (tw0 > 0x10)
+		return -1;
+
+	wecyc = ps_to_sossi_ticks(t->we_cycle_time, div);
+	if (wecyc <= weoff)
+		wecyc = weoff + 1;
+
+	tw1 = wecyc - tw0;
+	/* values less then 3 result in the SOSSI block resetting itself */
+	if (tw1 < 3)
+		tw1 = 3;
+	if (tw1 > 0x40)
+		return -1;
+
+	t->tim[2] = tw0 - 1;
+	t->tim[3] = tw1 - 1;
+
+	return 0;
+}
+
+static void _set_timing(int div, int tw0, int tw1)
+{
+	u32 l;
+
+#ifdef VERBOSE
+	dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n",
+		 tw0 + 1, tw1 + 1, div);
+#endif
+
+	clk_set_rate(sossi.fck, sossi.fck_hz / div);
+	clk_enable(sossi.fck);
+	l = sossi_read_reg(SOSSI_INIT1_REG);
+	l &= ~((0x0f << 20) | (0x3f << 24));
+	l |= (tw0 << 20) | (tw1 << 24);
+	sossi_write_reg(SOSSI_INIT1_REG, l);
+	clk_disable(sossi.fck);
+}
+
+static void _set_bits_per_cycle(int bus_pick_count, int bus_pick_width)
+{
+	u32 l;
+
+	l = sossi_read_reg(SOSSI_INIT3_REG);
+	l &= ~0x3ff;
+	l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
+	sossi_write_reg(SOSSI_INIT3_REG, l);
+}
+
+static void _set_tearsync_mode(int mode, unsigned line)
+{
+	u32 l;
+
+	l = sossi_read_reg(SOSSI_TEARING_REG);
+	l &= ~(((1 << 11) - 1) << 15);
+	l |= line << 15;
+	l &= ~(0x3 << 26);
+	l |= mode << 26;
+	sossi_write_reg(SOSSI_TEARING_REG, l);
+	if (mode)
+		sossi_set_bits(SOSSI_INIT2_REG, 1 << 6);	/* TE logic */
+	else
+		sossi_clear_bits(SOSSI_INIT2_REG, 1 << 6);
+}
+
+static inline void set_timing(int access)
+{
+	if (access != sossi.last_access) {
+		sossi.last_access = access;
+		_set_timing(sossi.clk_div,
+			    sossi.clk_tw0[access], sossi.clk_tw1[access]);
+	}
+}
+
+static void sossi_start_transfer(void)
+{
+	/* WE */
+	sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4);
+	/* CS active low */
+	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void sossi_stop_transfer(void)
+{
+	/* WE */
+	sossi_set_bits(SOSSI_INIT2_REG, 1 << 4);
+	/* CS active low */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void wait_end_of_write(void)
+{
+	/* Before reading we must check if some writings are going on */
+	while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3)));
+}
+
+static void send_data(const void *data, unsigned int len)
+{
+	while (len >= 4) {
+		sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data);
+		len -= 4;
+		data += 4;
+	}
+	while (len >= 2) {
+		sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data);
+		len -= 2;
+		data += 2;
+	}
+	while (len) {
+		sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data);
+		len--;
+		data++;
+	}
+}
+
+static void set_cycles(unsigned int len)
+{
+	unsigned long nr_cycles = len / (sossi.bus_pick_width / 8);
+
+	BUG_ON((nr_cycles - 1) & ~0x3ffff);
+
+	sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff);
+	sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
+}
+
+static int sossi_convert_timings(struct extif_timings *t)
+{
+	int r = 0;
+	int div = t->clk_div;
+
+	t->converted = 0;
+
+	if (div <= 0 || div > 8)
+		return -1;
+
+	/* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */
+	if ((r = calc_rd_timings(t)) < 0)
+		return r;
+
+	if ((r = calc_wr_timings(t)) < 0)
+		return r;
+
+	t->tim[4] = div;
+
+	t->converted = 1;
+
+	return 0;
+}
+
+static void sossi_set_timings(const struct extif_timings *t)
+{
+	BUG_ON(!t->converted);
+
+	sossi.clk_tw0[RD_ACCESS] = t->tim[0];
+	sossi.clk_tw1[RD_ACCESS] = t->tim[1];
+
+	sossi.clk_tw0[WR_ACCESS] = t->tim[2];
+	sossi.clk_tw1[WR_ACCESS] = t->tim[3];
+
+	sossi.clk_div = t->tim[4];
+}
+
+static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+	*clk_period = HZ_TO_PS(sossi.fck_hz);
+	*max_clk_div = 8;
+}
+
+static void sossi_set_bits_per_cycle(int bpc)
+{
+	int bus_pick_count, bus_pick_width;
+
+	/*
+	 * We set explicitly the the bus_pick_count as well, although
+	 * with remapping/reordering disabled it will be calculated by HW
+	 * as (32 / bus_pick_width).
+	 */
+	switch (bpc) {
+	case 8:
+		bus_pick_count = 4;
+		bus_pick_width = 8;
+		break;
+	case 16:
+		bus_pick_count = 2;
+		bus_pick_width = 16;
+		break;
+	default:
+		BUG();
+		return;
+	}
+	sossi.bus_pick_width = bus_pick_width;
+	sossi.bus_pick_count = bus_pick_count;
+}
+
+static int sossi_setup_tearsync(unsigned pin_cnt,
+				unsigned hs_pulse_time, unsigned vs_pulse_time,
+				int hs_pol_inv, int vs_pol_inv, int div)
+{
+	int hs, vs;
+	u32 l;
+
+	if (pin_cnt != 1 || div < 1 || div > 8)
+		return -EINVAL;
+
+	hs = ps_to_sossi_ticks(hs_pulse_time, div);
+	vs = ps_to_sossi_ticks(vs_pulse_time, div);
+	if (vs < 8 || vs <= hs || vs >= (1 << 12))
+		return -EDOM;
+	vs /= 8;
+	vs--;
+	if (hs > 8)
+		hs = 8;
+	if (hs)
+		hs--;
+
+	dev_dbg(sossi.fbdev->dev,
+		"setup_tearsync: hs %d vs %d hs_inv %d vs_inv %d\n",
+		hs, vs, hs_pol_inv, vs_pol_inv);
+
+	clk_enable(sossi.fck);
+	l = sossi_read_reg(SOSSI_TEARING_REG);
+	l &= ~((1 << 15) - 1);
+	l |= vs << 3;
+	l |= hs;
+	if (hs_pol_inv)
+		l |= 1 << 29;
+	else
+		l &= ~(1 << 29);
+	if (vs_pol_inv)
+		l |= 1 << 28;
+	else
+		l &= ~(1 << 28);
+	sossi_write_reg(SOSSI_TEARING_REG, l);
+	clk_disable(sossi.fck);
+
+	return 0;
+}
+
+static int sossi_enable_tearsync(int enable, unsigned line)
+{
+	int mode;
+
+	dev_dbg(sossi.fbdev->dev, "tearsync %d line %d\n", enable, line);
+	if (line >= 1 << 11)
+		return -EINVAL;
+	if (enable) {
+		if (line)
+			mode = 2;		/* HS or VS */
+		else
+			mode = 3;		/* VS only */
+	} else
+		mode = 0;
+	sossi.tearsync_line = line;
+	sossi.tearsync_mode = mode;
+
+	return 0;
+}
+
+static void sossi_write_command(const void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	send_data(data, len);
+	sossi_stop_transfer();
+	wait_end_of_write();
+	clk_disable(sossi.fck);
+}
+
+static void sossi_write_data(const void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	send_data(data, len);
+	sossi_stop_transfer();
+	wait_end_of_write();
+	clk_disable(sossi.fck);
+}
+
+static void sossi_transfer_area(int width, int height,
+				void (callback)(void *data), void *data)
+{
+	BUG_ON(callback == NULL);
+
+	sossi.lcdc_callback = callback;
+	sossi.lcdc_callback_data = data;
+
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	_set_tearsync_mode(sossi.tearsync_mode, sossi.tearsync_line);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(width * height * sossi.bus_pick_width / 8);
+
+	sossi_start_transfer();
+	if (sossi.tearsync_mode) {
+		/*
+		 * Wait for the sync signal and start the transfer only
+		 * then. We can't seem to be able to use HW sync DMA for
+		 * this since LCD DMA shows huge latencies, as if it
+		 * would ignore some of the DMA requests from SoSSI.
+		 */
+		unsigned long flags;
+
+		spin_lock_irqsave(&sossi.lock, flags);
+		sossi.vsync_dma_pending++;
+		spin_unlock_irqrestore(&sossi.lock, flags);
+	} else
+		/* Just start the transfer right away. */
+		omap_enable_lcd_dma();
+}
+
+static void sossi_dma_callback(void *data)
+{
+	omap_stop_lcd_dma();
+	sossi_stop_transfer();
+	clk_disable(sossi.fck);
+	sossi.lcdc_callback(sossi.lcdc_callback_data);
+}
+
+static void sossi_read_data(void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(RD_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	while (len >= 4) {
+		*(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG);
+		len -= 4;
+		data += 4;
+	}
+	while (len >= 2) {
+		*(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG);
+		len -= 2;
+		data += 2;
+	}
+	while (len) {
+		*(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG);
+		len--;
+		data++;
+	}
+	sossi_stop_transfer();
+	clk_disable(sossi.fck);
+}
+
+static irqreturn_t sossi_match_irq(int irq, void *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sossi.lock, flags);
+	if (sossi.vsync_dma_pending) {
+		sossi.vsync_dma_pending--;
+		omap_enable_lcd_dma();
+	}
+	spin_unlock_irqrestore(&sossi.lock, flags);
+	return IRQ_HANDLED;
+}
+
+static int sossi_init(struct omapfb_device *fbdev)
+{
+	u32 l, k;
+	struct clk *fck;
+	struct clk *dpll1out_ck;
+	int r;
+
+	sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE);
+	sossi.fbdev = fbdev;
+	spin_lock_init(&sossi.lock);
+
+	dpll1out_ck = clk_get(fbdev->dev, "ck_dpll1out");
+	if (IS_ERR(dpll1out_ck)) {
+		dev_err(fbdev->dev, "can't get DPLL1OUT clock\n");
+		return PTR_ERR(dpll1out_ck);
+	}
+	/*
+	 * We need the parent clock rate, which we might divide further
+	 * depending on the timing requirements of the controller. See
+	 * _set_timings.
+	 */
+	sossi.fck_hz = clk_get_rate(dpll1out_ck);
+	clk_put(dpll1out_ck);
+
+	fck = clk_get(fbdev->dev, "ck_sossi");
+	if (IS_ERR(fck)) {
+		dev_err(fbdev->dev, "can't get SoSSI functional clock\n");
+		return PTR_ERR(fck);
+	}
+	sossi.fck = fck;
+
+	/* Reset and enable the SoSSI module */
+	l = omap_readl(MOD_CONF_CTRL_1);
+	l |= CONF_SOSSI_RESET_R;
+	omap_writel(l, MOD_CONF_CTRL_1);
+	l &= ~CONF_SOSSI_RESET_R;
+	omap_writel(l, MOD_CONF_CTRL_1);
+
+	clk_enable(sossi.fck);
+	l = omap_readl(ARM_IDLECT2);
+	l &= ~(1 << 8);			/* DMACK_REQ */
+	omap_writel(l, ARM_IDLECT2);
+
+	l = sossi_read_reg(SOSSI_INIT2_REG);
+	/* Enable and reset the SoSSI block */
+	l |= (1 << 0) | (1 << 1);
+	sossi_write_reg(SOSSI_INIT2_REG, l);
+	/* Take SoSSI out of reset */
+	l &= ~(1 << 1);
+	sossi_write_reg(SOSSI_INIT2_REG, l);
+
+	sossi_write_reg(SOSSI_ID_REG, 0);
+	l = sossi_read_reg(SOSSI_ID_REG);
+	k = sossi_read_reg(SOSSI_ID_REG);
+
+	if (l != 0x55555555 || k != 0xaaaaaaaa) {
+		dev_err(fbdev->dev,
+			"invalid SoSSI sync pattern: %08x, %08x\n", l, k);
+		r = -ENODEV;
+		goto err;
+	}
+
+	if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) {
+		dev_err(fbdev->dev, "can't get LCDC IRQ\n");
+		r = -ENODEV;
+		goto err;
+	}
+
+	l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
+	l = sossi_read_reg(SOSSI_ID_REG);
+	dev_info(fbdev->dev, "SoSSI version %d.%d initialized\n",
+		l >> 16, l & 0xffff);
+
+	l = sossi_read_reg(SOSSI_INIT1_REG);
+	l |= (1 << 19); /* DMA_MODE */
+	l &= ~(1 << 31); /* REORDERING */
+	sossi_write_reg(SOSSI_INIT1_REG, l);
+
+	if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
+			     IRQT_FALLING,
+	     "sossi_match", sossi.fbdev->dev)) < 0) {
+		dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
+		goto err;
+	}
+
+	clk_disable(sossi.fck);
+	return 0;
+
+err:
+	clk_disable(sossi.fck);
+	clk_put(sossi.fck);
+	return r;
+}
+
+static void sossi_cleanup(void)
+{
+	omap_lcdc_free_dma_callback();
+	clk_put(sossi.fck);
+}
+
+struct lcd_ctrl_extif omap1_ext_if = {
+	.init			= sossi_init,
+	.cleanup		= sossi_cleanup,
+	.get_clk_info		= sossi_get_clk_info,
+	.convert_timings	= sossi_convert_timings,
+	.set_timings		= sossi_set_timings,
+	.set_bits_per_cycle	= sossi_set_bits_per_cycle,
+	.setup_tearsync		= sossi_setup_tearsync,
+	.enable_tearsync	= sossi_enable_tearsync,
+	.write_command		= sossi_write_command,
+	.read_data		= sossi_read_data,
+	.write_data		= sossi_write_data,
+	.transfer_area		= sossi_transfer_area,
+
+	.max_transmit_size	= SOSSI_MAX_XMIT_BYTES,
+};
+
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index e64f8b5..8503e73 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -52,7 +52,7 @@
 	struct {
 		__u8 red, green, blue;
 	}				palette[256];
-	u32				pseudo_palette[17];
+	u32				pseudo_palette[16];
 	
 	volatile struct cmap_regs	__iomem *cmap_regs;
 	unsigned long			cmap_regs_phys;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 0a04483..10c0cc6 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -24,7 +24,7 @@
  * License. See the file COPYING in the main directory of this archive for
  * more details.
  *
- * 
+ *
  */
 
 #include <linux/module.h>
@@ -58,7 +58,7 @@
 #endif
 
 /*
- * Driver data 
+ * Driver data
  */
 static char *mode __devinitdata = NULL;
 
@@ -82,12 +82,12 @@
 {
 	pm2type_t	type;		/* Board type */
 	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
-	u32 	   	memclock;	/* memclock */
+	u32		memclock;	/* memclock */
 	u32		video;		/* video flags before blanking */
 	u32		mem_config;	/* MemConfig reg at probe */
 	u32		mem_control;	/* MemControl reg at probe */
 	u32		boot_address;	/* BootAddress reg at probe */
-	u32             palette[16];
+	u32		palette[16];
 };
 
 /*
@@ -95,12 +95,12 @@
  * if we don't use modedb.
  */
 static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
-	.id =		"", 
+	.id =		"",
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_PSEUDOCOLOR,
 	.xpanstep =	1,
 	.ypanstep =	1,
-	.ywrapstep =	0, 
+	.ywrapstep =	0,
 	.accel =	FB_ACCEL_3DLABS_PERMEDIA2,
 };
 
@@ -109,26 +109,26 @@
  */
 static struct fb_var_screeninfo pm2fb_var __devinitdata = {
 	/* "640x480, 8 bpp @ 60 Hz */
-	.xres =		640,
-	.yres =		480,
-	.xres_virtual =	640,
-	.yres_virtual =	480,
-	.bits_per_pixel =8,
-	.red =		{0, 8, 0},
-	.blue =		{0, 8, 0},
-	.green =	{0, 8, 0},
-	.activate =	FB_ACTIVATE_NOW,
-	.height =	-1,
-	.width =	-1,
-	.accel_flags =	0,
-	.pixclock =	39721,
-	.left_margin =	40,
-	.right_margin =	24,
-	.upper_margin =	32,
-	.lower_margin =	11,
-	.hsync_len =	96,
-	.vsync_len =	2,
-	.vmode =	FB_VMODE_NONINTERLACED
+	.xres =			640,
+	.yres =			480,
+	.xres_virtual =		640,
+	.yres_virtual =		480,
+	.bits_per_pixel =	8,
+	.red =			{0, 8, 0},
+	.blue =			{0, 8, 0},
+	.green =		{0, 8, 0},
+	.activate =		FB_ACTIVATE_NOW,
+	.height =		-1,
+	.width =		-1,
+	.accel_flags =		0,
+	.pixclock =		39721,
+	.left_margin =		40,
+	.right_margin =		24,
+	.upper_margin =		32,
+	.lower_margin =		11,
+	.hsync_len =		96,
+	.vsync_len =		2,
+	.vmode =		FB_VMODE_NONINTERLACED
 };
 
 /*
@@ -166,7 +166,7 @@
 		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
 		index = PM2VR_RD_INDEXED_DATA;
 		break;
-	}	
+	}
 	mb();
 	return pm2_RD(p, index);
 }
@@ -182,7 +182,7 @@
 		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
 		index = PM2VR_RD_INDEXED_DATA;
 		break;
-	}	
+	}
 	wmb();
 	pm2_WR(p, index, v);
 	wmb();
@@ -197,7 +197,7 @@
 }
 
 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
-#define WAIT_FIFO(p,a)
+#define WAIT_FIFO(p, a)
 #else
 static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
 {
@@ -209,7 +209,7 @@
 /*
  * partial products for the supported horizontal resolutions.
  */
-#define PACKPP(p0,p1,p2)	(((p2) << 6) | ((p1) << 3) | (p0))
+#define PACKPP(p0, p1, p2)	(((p2) << 6) | ((p1) << 3) | (p0))
 static const struct {
 	u16 width;
 	u16 pp;
@@ -357,7 +357,7 @@
 static void reset_config(struct pm2fb_par* p)
 {
 	WAIT_FIFO(p, 52);
-	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
+	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG) &
 	       ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
 	pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
 	pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
@@ -367,7 +367,7 @@
 	pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
 	pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
 	pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
-	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0); 
+	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
 	pm2_WR(p, PM2R_LB_READ_MODE, 0);
 	pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
 	pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
@@ -535,7 +535,7 @@
 	vsync = video;
 
 	DPRINTK("video = 0x%x\n", video);
-	
+
 	/*
 	 * The hardware cursor needs +vsync to recognise vert retrace.
 	 * We may not be using the hardware cursor, but the X Glint
@@ -574,9 +574,9 @@
  */
 
 /**
- *      pm2fb_check_var - Optional function. Validates a var passed in. 
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer 
+ *	pm2fb_check_var - Optional function. Validates a var passed in.
+ *	@var: frame buffer variable screen structure
+ *	@info: frame buffer structure that represents a single frame buffer
  *
  *	Checks to see if the hardware supports the state requested by
  *	var passed in.
@@ -615,23 +615,23 @@
 
 	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
 	lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
-  
+
 	if (var->xres < 320 || var->xres > 1600) {
 		DPRINTK("width not supported: %u\n", var->xres);
 		return -EINVAL;
 	}
-  
+
 	if (var->yres < 200 || var->yres > 1200) {
 		DPRINTK("height not supported: %u\n", var->yres);
 		return -EINVAL;
 	}
-  
+
 	if (lpitch * var->yres_virtual > info->fix.smem_len) {
 		DPRINTK("no memory for screen (%ux%ux%u)\n",
 			var->xres, var->yres_virtual, var->bits_per_pixel);
 		return -EINVAL;
 	}
-  
+
 	if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
 		DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
 		return -EINVAL;
@@ -672,17 +672,17 @@
 		break;
 	}
 	var->height = var->width = -1;
-  
+
 	var->accel_flags = 0;	/* Can't mmap if this is on */
-	
+
 	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
 		var->xres, var->yres, var->bits_per_pixel);
 	return 0;
 }
 
 /**
- *      pm2fb_set_par - Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
+ *	pm2fb_set_par - Alters the hardware state.
+ *	@info: frame buffer structure that represents a single frame buffer
  *
  *	Using the fb_var_screeninfo in fb_info we set the resolution of the
  *	this particular framebuffer.
@@ -709,7 +709,7 @@
 	clear_palette(par);
 	if ( par->memclock )
 		set_memclock(par, par->memclock);
-    
+
 	width = (info->var.xres_virtual + 7) & ~7;
 	height = info->var.yres_virtual;
 	depth = (info->var.bits_per_pixel + 7) & ~7;
@@ -722,7 +722,7 @@
 		DPRINTK("pixclock too high (%uKHz)\n", pixclock);
 		return -EINVAL;
 	}
-    
+
 	hsstart = to3264(info->var.right_margin, depth, data64);
 	hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
 	hbend = hsend + to3264(info->var.left_margin, depth, data64);
@@ -737,7 +737,7 @@
 	base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
 	if (data64)
 		video |= PM2F_DATA_64_ENABLE;
-    
+
 	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
 		if (lowhsync) {
 			DPRINTK("ignoring +hsync, using -hsync.\n");
@@ -778,9 +778,9 @@
 		WAIT_FIFO(par, 1);
 		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
 	}
-    
+
 	set_aperture(par, depth);
-    
+
 	mb();
 	WAIT_FIFO(par, 19);
 	pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
@@ -847,22 +847,22 @@
 	set_pixclock(par, pixclock);
 	DPRINTK("Setting graphics mode at %dx%d depth %d\n",
 		info->var.xres, info->var.yres, info->var.bits_per_pixel);
-	return 0;	
+	return 0;
 }
 
 /**
- *  	pm2fb_setcolreg - Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *	@green: The green value which can be up to 16 bits wide 
+ *	pm2fb_setcolreg - Sets a color register.
+ *	@regno: boolean, 0 copy local, 1 get_user() function
+ *	@red: frame buffer colormap structure
+ *	@green: The green value which can be up to 16 bits wide
  *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.	
- *      @info: frame buffer info structure
- * 
- *  	Set a single color register. The values supplied have a 16 bit
- *  	magnitude which needs to be scaled in this function for the hardware.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *	@info: frame buffer info structure
+ *
+ *	Set a single color register. The values supplied have a 16 bit
+ *	magnitude which needs to be scaled in this function for the hardware.
  *	Pretty much a direct lift from tdfxfb.c.
- * 
+ *
  *	Returns negative errno on error, or zero on success.
  */
 static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -906,7 +906,7 @@
 	 *    (blue << blue.offset) | (transp << transp.offset)
 	 *    RAMDAC does not exist
 	 */
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF -(val)) >> 16)
 	switch (info->fix.visual) {
 	case FB_VISUAL_TRUECOLOR:
 	case FB_VISUAL_PSEUDOCOLOR:
@@ -916,9 +916,9 @@
 		transp = CNVT_TOHW(transp, info->var.transp.length);
 		break;
 	case FB_VISUAL_DIRECTCOLOR:
-		/* example here assumes 8 bit DAC. Might be different 
-		 * for your hardware */	
-		red = CNVT_TOHW(red, 8);       
+		/* example here assumes 8 bit DAC. Might be different
+		 * for your hardware */
+		red = CNVT_TOHW(red, 8);
 		green = CNVT_TOHW(green, 8);
 		blue = CNVT_TOHW(blue, 8);
 		/* hey, there is bug in transp handling... */
@@ -940,11 +940,11 @@
 
 		switch (info->var.bits_per_pixel) {
 		case 8:
-			break;	
-   		case 16:
+			break;
+		case 16:
 		case 24:
-		case 32:	
-           		par->palette[regno] = v;
+		case 32:
+			par->palette[regno] = v;
 			break;
 		}
 		return 0;
@@ -956,15 +956,15 @@
 }
 
 /**
- *      pm2fb_pan_display - Pans the display.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
+ *	pm2fb_pan_display - Pans the display.
+ *	@var: frame buffer variable screen structure
+ *	@info: frame buffer structure that represents a single frame buffer
  *
  *	Pan (or wrap, depending on the `vmode' field) the display using the
- *  	`xoffset' and `yoffset' fields of the `var' structure.
- *  	If the values don't fit, return -EINVAL.
+ *	`xoffset' and `yoffset' fields of the `var' structure.
+ *	If the values don't fit, return -EINVAL.
  *
- *      Returns negative errno on error, or zero on success.
+ *	Returns negative errno on error, or zero on success.
  *
  */
 static int pm2fb_pan_display(struct fb_var_screeninfo *var,
@@ -980,24 +980,24 @@
 	depth = (depth > 32) ? 32 : depth;
 	base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
 	WAIT_FIFO(p, 1);
-	pm2_WR(p, PM2R_SCREEN_BASE, base);    
+	pm2_WR(p, PM2R_SCREEN_BASE, base);
 	return 0;
 }
 
 /**
- *      pm2fb_blank - Blanks the display.
- *      @blank_mode: the blank mode we want. 
- *      @info: frame buffer structure that represents a single frame buffer
+ *	pm2fb_blank - Blanks the display.
+ *	@blank_mode: the blank mode we want.
+ *	@info: frame buffer structure that represents a single frame buffer
  *
- *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
- *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a 
- *      video mode which doesn't support it. Implements VESA suspend
- *      and powerdown modes on hardware that supports disabling hsync/vsync:
- *      blank_mode == 2: suspend vsync
- *      blank_mode == 3: suspend hsync
- *      blank_mode == 4: powerdown
+ *	Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *	blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *	video mode which doesn't support it. Implements VESA suspend
+ *	and powerdown modes on hardware that supports disabling hsync/vsync:
+ *	blank_mode == 2: suspend vsync
+ *	blank_mode == 3: suspend hsync
+ *	blank_mode == 4: powerdown
  *
- *      Returns negative errno on error, or zero on success.
+ *	Returns negative errno on error, or zero on success.
  *
  */
 static int pm2fb_blank(int blank_mode, struct fb_info *info)
@@ -1071,7 +1071,7 @@
 	pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x);
 	pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w);
 	wmb();
-	pm2_WR(par, PM2R_RENDER,PM2F_RENDER_RECTANGLE |
+	pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
 				(x<xsrc ? PM2F_INCREASE_X : 0) |
 				(y<ysrc ? PM2F_INCREASE_Y : 0) |
 				(copy ? 0 : PM2F_RENDER_FASTFILL));
@@ -1234,7 +1234,7 @@
 	DPRINTK("Adjusting register base for big-endian.\n");
 #endif
 	DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
-    
+
 	/* Registers - request region and map it. */
 	if ( !request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
 				 "pm2fb regbase") ) {
@@ -1317,17 +1317,17 @@
 	}
 
 	info->fbops		= &pm2fb_ops;
-	info->fix		= pm2fb_fix; 	
+	info->fix		= pm2fb_fix;
 	info->pseudo_palette	= default_par->palette;
 	info->flags		= FBINFO_DEFAULT |
-                                  FBINFO_HWACCEL_YPAN |
-	                          FBINFO_HWACCEL_COPYAREA |
-	                          FBINFO_HWACCEL_FILLRECT;
+				  FBINFO_HWACCEL_YPAN |
+				  FBINFO_HWACCEL_COPYAREA |
+				  FBINFO_HWACCEL_FILLRECT;
 
 	if (!mode)
 		mode = "640x480@60";
-	 
-	err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8); 
+
+	err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8);
 	if (!err || err == 4)
 		info->var = pm2fb_var;
 
@@ -1348,8 +1348,8 @@
 	return 0;
 
  err_exit_all:
-	fb_dealloc_cmap(&info->cmap);	
- err_exit_both:    
+	fb_dealloc_cmap(&info->cmap);
+ err_exit_both:
 	iounmap(info->screen_base);
 	release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
  err_exit_mmio:
@@ -1374,7 +1374,7 @@
 	struct pm2fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-    
+
 	iounmap(info->screen_base);
 	release_mem_region(fix->smem_start, fix->smem_len);
 	iounmap(par->v_regs);
@@ -1402,9 +1402,9 @@
 
 static struct pci_driver pm2fb_driver = {
 	.name		= "pm2fb",
-	.id_table 	= pm2fb_id_table,
-	.probe 		= pm2fb_probe,
-	.remove 	= __devexit_p(pm2fb_remove),
+	.id_table	= pm2fb_id_table,
+	.probe		= pm2fb_probe,
+	.remove		= __devexit_p(pm2fb_remove),
 };
 
 MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
@@ -1423,7 +1423,7 @@
 	if (!options || !*options)
 		return 0;
 
-	while ((this_opt = strsep(&options, ",")) != NULL) {	
+	while ((this_opt = strsep(&options, ",")) != NULL) {
 		if (!*this_opt)
 			continue;
 		if(!strcmp(this_opt, "lowhsync")) {
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index b52e883..5b3f54c 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -77,7 +77,7 @@
 	.xpanstep =	1,
 	.ypanstep =	1,
 	.ywrapstep =	0,
-	.accel =	FB_ACCEL_NONE,
+	.accel =	FB_ACCEL_3DLABS_PERMEDIA3,
 };
 
 /*
@@ -185,6 +185,238 @@
 	return 0;
 }
 
+/* acceleration */
+static int pm3fb_sync(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+
+	PM3_WAIT(par, 2);
+	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+	PM3_WRITE_REG(par, PM3Sync, 0);
+	mb();
+	do {
+		while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0);
+		rmb();
+	} while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
+
+	return 0;
+}
+
+static void pm3fb_init_engine(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	const u32 width = (info->var.xres_virtual + 7) & ~7;
+
+	PM3_WAIT(par, 50);
+	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+	PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
+	PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
+	PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
+	PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
+	PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
+	PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
+	PM3_WRITE_REG(par, PM3GIDMode, 0x0);
+	PM3_WRITE_REG(par, PM3DepthMode, 0x0);
+	PM3_WRITE_REG(par, PM3StencilMode, 0x0);
+	PM3_WRITE_REG(par, PM3StencilData, 0x0);
+	PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
+	PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LUTMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
+	PM3_WRITE_REG(par, PM3FogMode, 0x0);
+	PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
+	PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
+	PM3_WRITE_REG(par, PM3YUVMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
+	PM3_WRITE_REG(par, PM3DitherMode, 0x0);
+	PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
+	PM3_WRITE_REG(par, PM3RouterMode, 0x0);
+	PM3_WRITE_REG(par, PM3Window, 0x0);
+
+	PM3_WRITE_REG(par, PM3Config2D, 0x0);
+
+	PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);
+
+	PM3_WRITE_REG(par, PM3XBias, 0x0);
+	PM3_WRITE_REG(par, PM3YBias, 0x0);
+	PM3_WRITE_REG(par, PM3DeltaControl, 0x0);
+
+	PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);
+
+	PM3_WRITE_REG(par, PM3FBDestReadEnables,
+			   PM3FBDestReadEnables_E(0xff) |
+			   PM3FBDestReadEnables_R(0xff) |
+			   PM3FBDestReadEnables_ReferenceAlpha(0xff));
+	PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
+	PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
+	PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
+			   PM3FBDestReadBufferWidth_Width(width));
+
+	PM3_WRITE_REG(par, PM3FBDestReadMode,
+			   PM3FBDestReadMode_ReadEnable |
+			   PM3FBDestReadMode_Enable0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
+			   PM3FBSourceReadBufferWidth_Width(width));
+	PM3_WRITE_REG(par, PM3FBSourceReadMode,
+			   PM3FBSourceReadMode_Blocking |
+			   PM3FBSourceReadMode_ReadEnable);
+
+	PM3_WAIT(par, 2);
+	{
+		unsigned long rm = 1;
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_8BIT);
+			break;
+		case 16:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_16BIT);
+			break;
+		case 32:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_32BIT);
+			break;
+		default:
+			DPRINTK(1, "Unsupported depth %d\n",
+				info->var.bits_per_pixel);
+			break;
+		}
+		PM3_WRITE_REG(par, PM3RasterizerMode, rm);
+	}
+
+	PM3_WAIT(par, 20);
+	PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3FBWriteMode,
+			   PM3FBWriteMode_WriteEnable |
+			   PM3FBWriteMode_OpaqueSpan |
+			   PM3FBWriteMode_Enable0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
+			   PM3FBWriteBufferWidth_Width(width));
+
+	PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
+	{
+		/* size in lines of FB */
+		unsigned long sofb = info->screen_size /
+			info->fix.line_length;
+		if (sofb > 4095)
+			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
+		else
+			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);
+
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (2 << 3));
+			break;
+		case 16:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (1 << 3));
+			break;
+		case 32:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (0 << 3));
+			break;
+		default:
+			DPRINTK(1, "Unsupported depth %d\n",
+				info->current_par->depth);
+			break;
+		}
+	}
+
+	PM3_WRITE_REG(par, PM3dXDom, 0x0);
+	PM3_WRITE_REG(par, PM3dXSub, 0x0);
+	PM3_WRITE_REG(par, PM3dY, (1 << 16));
+	PM3_WRITE_REG(par, PM3StartXDom, 0x0);
+	PM3_WRITE_REG(par, PM3StartXSub, 0x0);
+	PM3_WRITE_REG(par, PM3StartY, 0x0);
+	PM3_WRITE_REG(par, PM3Count, 0x0);
+
+/* Disable LocalBuffer. better safe than sorry */
+	PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0);
+	PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LBWriteMode, 0x0);
+
+	pm3fb_sync(info);
+}
+
+static void pm3fb_fillrect (struct fb_info *info,
+				const struct fb_fillrect *region)
+{
+	struct pm3_par *par = info->par;
+	struct fb_fillrect modded;
+	int vxres, vyres;
+	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+		((u32*)info->pseudo_palette)[region->color] : region->color;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
+		region->rop != ROP_COPY ) {
+		cfb_fillrect(info, region);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if(!modded.width || !modded.height ||
+	   modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if(modded.dx + modded.width  > vxres)
+		modded.width  = vxres - modded.dx;
+	if(modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	if(info->var.bits_per_pixel == 8)
+		color |= color << 8;
+	if(info->var.bits_per_pixel <= 16)
+		color |= color << 16;
+
+	PM3_WAIT(par, 4);
+
+	PM3_WRITE_REG(par, PM3Config2D,
+				  PM3Config2D_UseConstantSource |
+				  PM3Config2D_ForegroundROPEnable |
+				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
+				  PM3Config2D_FBWriteEnable);
+
+	PM3_WRITE_REG(par, PM3ForegroundColor, color);
+
+	PM3_WRITE_REG(par, PM3RectanglePosition,
+		      (PM3RectanglePosition_XOffset(modded.dx)) |
+		      (PM3RectanglePosition_YOffset(modded.dy)));
+
+	PM3_WRITE_REG(par, PM3Render2D,
+		      PM3Render2D_XPositive |
+		      PM3Render2D_YPositive |
+		      PM3Render2D_Operation_Normal |
+		      PM3Render2D_SpanOperation |
+		      (PM3Render2D_Width(modded.width)) |
+		      (PM3Render2D_Height(modded.height)));
+}
+/* end of acceleration functions */
+
 /* write the mode to registers */
 static void pm3fb_write_mode(struct fb_info *info)
 {
@@ -380,8 +612,6 @@
 /*
  * hardware independent functions
  */
-int pm3fb_init(void);
-
 static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	u32 lpitch;
@@ -528,6 +758,7 @@
 	pm3fb_clear_colormap(par, 0, 0, 0);
 	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode,
 			  PM3RD_CursorMode_CURSOR_DISABLE);
+	pm3fb_init_engine(info);
 	pm3fb_write_mode(info);
 	return 0;
 }
@@ -675,10 +906,11 @@
 	.fb_set_par	= pm3fb_set_par,
 	.fb_setcolreg	= pm3fb_setcolreg,
 	.fb_pan_display	= pm3fb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
+	.fb_fillrect	= pm3fb_fillrect,
 	.fb_copyarea	= cfb_copyarea,
 	.fb_imageblit	= cfb_imageblit,
 	.fb_blank	= pm3fb_blank,
+	.fb_sync	= pm3fb_sync,
 };
 
 /* ------------------------------------------------------------------------- */
@@ -847,7 +1079,8 @@
 
 	info->fix = pm3fb_fix;
 	info->pseudo_palette = par->palette;
-	info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/
+	info->flags = FBINFO_DEFAULT |
+			FBINFO_HWACCEL_FILLRECT;/* | FBINFO_HWACCEL_YPAN;*/
 
 	/*
 	 * This should give a reasonable default video mode. The following is
@@ -935,35 +1168,12 @@
 
 MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
 
-#ifndef MODULE
-	/*
-	 *  Setup
-	 */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-static int __init pm3fb_setup(char *options)
+static int __init pm3fb_init(void)
 {
-	/* Parse user speficied options (`video=pm3fb:') */
-	return 0;
-}
-#endif /* MODULE */
-
-int __init pm3fb_init(void)
-{
-	/*
-	 *  For kernel boot options (in 'video=pm3fb:<options>' format)
-	 */
 #ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("pm3fb", &option))
+	if (fb_get_options("pm3fb", NULL))
 		return -ENODEV;
-	pm3fb_setup(option);
 #endif
-
 	return pci_register_driver(&pm3fb_driver);
 }
 
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 9cf92ba..3972aa8 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -27,7 +27,6 @@
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/ioctl.h>
 #include <linux/notifier.h>
@@ -46,6 +45,9 @@
 #include <asm/ps3fb.h>
 #include <asm/ps3.h>
 
+
+#define DEVICE_NAME		"ps3fb"
+
 #ifdef PS3FB_DEBUG
 #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
 #else
@@ -126,7 +128,6 @@
 
 struct ps3fb_priv {
 	unsigned int irq_no;
-	void *dev;
 
 	u64 context_handle, memory_handle;
 	void *xdr_ea;
@@ -171,7 +172,7 @@
 	{    0,    0,   0,   0 , 0} };
 
 /* default resolution */
-#define GPU_RES_INDEX 0		/* 720 x 480 */
+#define GPU_RES_INDEX	0		/* 720 x 480 */
 
 static const struct fb_videomode ps3fb_modedb[] = {
     /* 60 Hz broadcast modes (modes "1" to "5") */
@@ -298,10 +299,9 @@
 #define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
 
 static int ps3fb_mode;
-module_param(ps3fb_mode, bool, 0);
+module_param(ps3fb_mode, int, 0);
 
-static char *mode_option __initdata;
-
+static char *mode_option __devinitdata;
 
 static int ps3fb_get_res_table(u32 xres, u32 yres)
 {
@@ -681,15 +681,15 @@
 
 EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
 
-void ps3fb_flip_ctl(int on)
+void ps3fb_flip_ctl(int on, void *data)
 {
+	struct ps3fb_priv *priv = data;
 	if (on)
-		atomic_dec_if_positive(&ps3fb.ext_flip);
+		atomic_dec_if_positive(&priv->ext_flip);
 	else
-		atomic_inc(&ps3fb.ext_flip);
+		atomic_inc(&priv->ext_flip);
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
 
     /*
      * ioctl
@@ -812,6 +812,7 @@
 
 static int ps3fbd(void *arg)
 {
+	set_freezable();
 	while (!kthread_should_stop()) {
 		try_to_freeze();
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -851,37 +852,9 @@
 	return IRQ_HANDLED;
 }
 
-#ifndef MODULE
-static int __init ps3fb_setup(char *options)
-{
-	char *this_opt;
-	int mode = 0;
 
-	if (!options || !*options)
-		return 0;	/* no options */
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strncmp(this_opt, "mode:", 5))
-			mode = simple_strtoul(this_opt + 5, NULL, 0);
-		else
-			mode_option = this_opt;
-	}
-	return mode;
-}
-#endif	/* MODULE */
-
-    /*
-     *  Initialisation
-     */
-
-static void ps3fb_platform_release(struct device *device)
-{
-	/* This is called when the reference count goes to zero. */
-}
-
-static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
+				struct ps3_system_bus_device *dev)
 {
 	int error;
 
@@ -897,7 +870,6 @@
 		return -EINVAL;
 	}
 
-	ps3fb.dev = dev;
 	error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
 				   &ps3fb.irq_no);
 	if (error) {
@@ -907,7 +879,7 @@
 	}
 
 	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
-			    "ps3fb vsync", ps3fb.dev);
+			    DEVICE_NAME, dev);
 	if (error) {
 		printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
 		       error);
@@ -966,16 +938,45 @@
 };
 
 static struct fb_fix_screeninfo ps3fb_fix __initdata = {
-	.id =		"PS3 FB",
+	.id =		DEVICE_NAME,
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_TRUECOLOR,
 	.accel =	FB_ACCEL_NONE,
 };
 
-static int __init ps3fb_probe(struct platform_device *dev)
+static int ps3fb_set_sync(void)
+{
+	int status;
+
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC "
+		       "failed: %d\n", __func__, status);
+		return -1;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE "
+		       "failed: %d\n", __func__, status);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
 {
 	struct fb_info *info;
 	int retval = -ENOMEM;
+	u32 xres, yres;
 	u64 ddr_lpar = 0;
 	u64 lpar_dma_control = 0;
 	u64 lpar_driver_info = 0;
@@ -986,6 +987,30 @@
 	unsigned long offset;
 	struct task_struct *task;
 
+	status = ps3_open_hv_device(dev);
+	if (status) {
+		printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__);
+		goto err;
+	}
+
+	if (!ps3fb_mode)
+		ps3fb_mode = ps3av_get_mode();
+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+
+	if (ps3fb_mode > 0 &&
+	    !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+		DPRINTK("res_index:%d\n", ps3fb.res_index);
+	} else
+		ps3fb.res_index = GPU_RES_INDEX;
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_waitqueue_head(&ps3fb.wait_vsync);
+	ps3fb.num_frames = 1;
+
+	ps3fb_set_sync();
+
 	/* get gpu context handle */
 	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
 					 &ps3fb.memory_handle, &ddr_lpar);
@@ -1029,7 +1054,7 @@
 	 * leakage into userspace
 	 */
 	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
-	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
 	if (!info)
 		goto err_free_irq;
 
@@ -1061,19 +1086,20 @@
 	if (retval < 0)
 		goto err_fb_dealloc;
 
-	platform_set_drvdata(dev, info);
+	dev->core.driver_data = info;
 
 	printk(KERN_INFO
 	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
 	       info->node, ps3fb_videomemory.size >> 10);
 
-	task = kthread_run(ps3fbd, info, "ps3fbd");
+	task = kthread_run(ps3fbd, info, DEVICE_NAME);
 	if (IS_ERR(task)) {
 		retval = PTR_ERR(task);
 		goto err_unregister_framebuffer;
 	}
 
 	ps3fb.task = task;
+	ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb);
 
 	return 0;
 
@@ -1084,7 +1110,7 @@
 err_framebuffer_release:
 	framebuffer_release(info);
 err_free_irq:
-	free_irq(ps3fb.irq_no, ps3fb.dev);
+	free_irq(ps3fb.irq_no, dev);
 	ps3_irq_plug_destroy(ps3fb.irq_no);
 err_iounmap_dinfo:
 	iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1096,26 +1122,30 @@
 	return retval;
 }
 
-static void ps3fb_shutdown(struct platform_device *dev)
-{
-	ps3fb_flip_ctl(0);	/* flip off */
-	ps3fb.dinfo->irq.mask = 0;
-	free_irq(ps3fb.irq_no, ps3fb.dev);
-	ps3_irq_plug_destroy(ps3fb.irq_no);
-	iounmap((u8 __iomem *)ps3fb.dinfo);
-}
-
-void ps3fb_cleanup(void)
+static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 {
 	int status;
+	struct fb_info *info = dev->core.driver_data;
 
+	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+
+	ps3fb_flip_ctl(0, &ps3fb);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+
+	ps3av_register_flip_ctl(NULL, NULL);
 	if (ps3fb.task) {
 		struct task_struct *task = ps3fb.task;
 		ps3fb.task = NULL;
 		kthread_stop(task);
 	}
 	if (ps3fb.irq_no) {
-		free_irq(ps3fb.irq_no, ps3fb.dev);
+		free_irq(ps3fb.irq_no, dev);
 		ps3_irq_plug_destroy(ps3fb.irq_no);
 	}
 	iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1128,134 +1158,69 @@
 	if (status)
 		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
 
-	ps3av_dev_close();
-}
+	ps3_close_hv_device(dev);
+	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 
-EXPORT_SYMBOL_GPL(ps3fb_cleanup);
-
-static int ps3fb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	ps3fb_cleanup();
 	return 0;
 }
 
-static struct platform_driver ps3fb_driver = {
-	.probe	= ps3fb_probe,
-	.remove = ps3fb_remove,
-	.shutdown = ps3fb_shutdown,
-	.driver = { .name = "ps3fb" }
+static struct ps3_system_bus_driver ps3fb_driver = {
+	.match_id	= PS3_MATCH_ID_GRAPHICS,
+	.core.name	= DEVICE_NAME,
+	.core.owner	= THIS_MODULE,
+	.probe		= ps3fb_probe,
+	.remove		= ps3fb_shutdown,
+	.shutdown	= ps3fb_shutdown,
 };
 
-static struct platform_device ps3fb_device = {
-	.name	= "ps3fb",
-	.id	= 0,
-	.dev	= { .release = ps3fb_platform_release }
-};
-
-int ps3fb_set_sync(void)
+static int __init ps3fb_setup(void)
 {
-	int status;
+	char *options;
 
-#ifdef HEAD_A
-	status = lv1_gpu_context_attribute(0x0,
-					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
-	if (status) {
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
-		       __func__, status);
-		return -1;
-	}
+#ifdef MODULE
+	return 0;
 #endif
-#ifdef HEAD_B
-	status = lv1_gpu_context_attribute(0x0,
-					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 
-	if (status) {
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
-		       __func__, status);
-		return -1;
+	if (fb_get_options(DEVICE_NAME, &options))
+		return -ENXIO;
+
+	if (!options || !*options)
+		return 0;
+
+	while (1) {
+		char *this_opt = strsep(&options, ",");
+
+		if (!this_opt)
+			break;
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
 	}
-#endif
 	return 0;
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_set_sync);
-
 static int __init ps3fb_init(void)
 {
-	int error;
-#ifndef MODULE
-	int mode;
-	char *option = NULL;
+	if (!ps3fb_videomemory.address ||  ps3fb_setup())
+		return -ENXIO;
 
-	if (fb_get_options("ps3fb", &option))
-		goto err;
-#endif
+	return ps3_system_bus_driver_register(&ps3fb_driver);
+}
 
-	if (!ps3fb_videomemory.address)
-		goto err;
-
-	error = ps3av_dev_open();
-	if (error) {
-		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
-		goto err;
-	}
-
-	ps3fb_mode = ps3av_get_mode();
-	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
-#ifndef MODULE
-	mode = ps3fb_setup(option);	/* check boot option */
-	if (mode)
-		ps3fb_mode = mode;
-#endif
-	if (ps3fb_mode > 0) {
-		u32 xres, yres;
-		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
-		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
-		DPRINTK("res_index:%d\n", ps3fb.res_index);
-	} else
-		ps3fb.res_index = GPU_RES_INDEX;
-
-	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
-	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
-	init_waitqueue_head(&ps3fb.wait_vsync);
-	ps3fb.num_frames = 1;
-
-	error = platform_driver_register(&ps3fb_driver);
-	if (!error) {
-		error = platform_device_register(&ps3fb_device);
-		if (error)
-			platform_driver_unregister(&ps3fb_driver);
-	}
-
-	ps3fb_set_sync();
-
-	return error;
-
-err:
-	return -ENXIO;
+static void __exit ps3fb_exit(void)
+{
+	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+	ps3_system_bus_driver_unregister(&ps3fb_driver);
+	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 }
 
 module_init(ps3fb_init);
-
-#ifdef MODULE
-static void __exit ps3fb_exit(void)
-{
-	platform_device_unregister(&ps3fb_device);
-	platform_driver_unregister(&ps3fb_driver);
-}
-
 module_exit(ps3fb_exit);
 
 MODULE_LICENSE("GPL");
-#endif				/* MODULE */
+MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index df2909a..0f88c30 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -115,11 +115,11 @@
 enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 };
 
 struct pvr2_params { unsigned int val; char *name; };
-static struct pvr2_params cables[] __initdata = {
+static struct pvr2_params cables[] __devinitdata = {
 	{ CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
 };
 
-static struct pvr2_params outputs[] __initdata = {
+static struct pvr2_params outputs[] __devinitdata = {
 	{ VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
 };
 
@@ -147,16 +147,16 @@
 
 static struct fb_info *fb_info;
 
-static struct fb_fix_screeninfo pvr2_fix __initdata = {
+static struct fb_fix_screeninfo pvr2_fix __devinitdata = {
 	.id =		"NEC PowerVR2",
-	.type = 	FB_TYPE_PACKED_PIXELS,
-	.visual = 	FB_VISUAL_TRUECOLOR,
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
 	.ypanstep =	1,
 	.ywrapstep =	1,
-	.accel = 	FB_ACCEL_NONE,
+	.accel =	FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo pvr2_var __initdata = {
+static struct fb_var_screeninfo pvr2_var __devinitdata = {
 	.xres =		640,
 	.yres =		480,
 	.xres_virtual =	640,
@@ -195,10 +195,6 @@
 static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
 #endif
 
-/* Interface used by the world */
-
-int pvr2fb_setup(char*);
-
 static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue,
                             unsigned int transp, struct fb_info *info);
 static int pvr2fb_blank(int blank, struct fb_info *info);
@@ -227,12 +223,12 @@
 #ifdef CONFIG_SH_DMA
 	.fb_write	= pvr2fb_write,
 #endif
-	.fb_fillrect 	= cfb_fillrect,
+	.fb_fillrect	= cfb_fillrect,
 	.fb_copyarea	= cfb_copyarea,
 	.fb_imageblit	= cfb_imageblit,
 };
 
-static struct fb_videomode pvr2_modedb[] __initdata = {
+static struct fb_videomode pvr2_modedb[] __devinitdata = {
     /*
      * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with
      * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
@@ -252,7 +248,7 @@
 	/* 640x480 @ 60hz (VGA) */
 	"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,
 	0, FB_VMODE_YWRAP
-    }, 
+    },
 };
 
 #define NUM_TOTAL_MODES  ARRAY_SIZE(pvr2_modedb)
@@ -262,7 +258,7 @@
 #define DEFMODE_VGA	2
 
 static int defmode = DEFMODE_NTSC;
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 static inline void pvr2fb_set_pal_type(unsigned int type)
 {
@@ -293,7 +289,7 @@
 {
 	switch (var->bits_per_pixel) {
 	    case 16:        /* RGB 565 */
-	    	pvr2fb_set_pal_type(PAL_RGB565);
+		pvr2fb_set_pal_type(PAL_RGB565);
 		var->red.offset = 11;    var->red.length = 5;
 		var->green.offset = 5;   var->green.length = 6;
 		var->blue.offset = 0;    var->blue.length = 5;
@@ -306,7 +302,7 @@
 		var->transp.offset = 0;  var->transp.length = 0;
 		break;
 	    case 32:        /* ARGB 8888 */
-	    	pvr2fb_set_pal_type(PAL_ARGB8888);
+		pvr2fb_set_pal_type(PAL_ARGB8888);
 		var->red.offset = 16;    var->red.length = 8;
 		var->green.offset = 8;   var->green.length = 8;
 		var->blue.offset = 0;    var->blue.length = 8;
@@ -337,24 +333,25 @@
 		      ((blue  & 0xf800) >> 11);
 
 		pvr2fb_set_pal_entry(par, regno, tmp);
-		((u16*)(info->pseudo_palette))[regno] = tmp;
 		break;
 	    case 24: /* RGB 888 */
 		red >>= 8; green >>= 8; blue >>= 8;
-		((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
+		tmp = (red << 16) | (green << 8) | blue;
 		break;
 	    case 32: /* ARGB 8888 */
 		red >>= 8; green >>= 8; blue >>= 8;
 		tmp = (transp << 24) | (red << 16) | (green << 8) | blue;
 
 		pvr2fb_set_pal_entry(par, regno, tmp);
-		((u32*)(info->pseudo_palette))[regno] = tmp;
 		break;
 	    default:
 		pr_debug("Invalid bit depth %d?!?\n", info->var.bits_per_pixel);
 		return 1;
 	}
 
+	if (regno < 16)
+		((u32*)(info->pseudo_palette))[regno] = tmp;
+
 	return 0;
 }
 
@@ -379,13 +376,13 @@
 	var->vmode &= FB_VMODE_MASK;
 	if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
 		par->is_interlaced = 1;
-	/* 
+	/*
 	 * XXX: Need to be more creative with this (i.e. allow doublecan for
 	 * PAL/NTSC output).
 	 */
 	if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA)
 		par->is_doublescan = 1;
-	
+
 	par->hsync_total = var->left_margin + var->xres + var->right_margin +
 	                   var->hsync_len;
 	par->vsync_total = var->upper_margin + var->yres + var->lower_margin +
@@ -408,7 +405,7 @@
 	} else {
 		/* VGA mode */
 		/* XXX: What else needs to be checked? */
-		/* 
+		/*
 		 * XXX: We have a little freedom in VGA modes, what ranges
 		 * should be here (i.e. hsync/vsync totals, etc.)?
 		 */
@@ -419,8 +416,8 @@
 	/* Calculate the remainding offsets */
 	par->diwstart_h = par->borderstart_h + var->left_margin;
 	par->diwstart_v = par->borderstart_v + var->upper_margin;
-	par->borderstop_h = par->diwstart_h + var->xres + 
-			    var->right_margin;    
+	par->borderstop_h = par->diwstart_h + var->xres +
+			    var->right_margin;
 	par->borderstop_v = par->diwstart_v + var->yres +
 			    var->lower_margin;
 
@@ -465,12 +462,12 @@
 	set_color_bitfields(var);
 
 	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->xoffset || var->yoffset < 0 || 
+		if (var->xoffset || var->yoffset < 0 ||
 		    var->yoffset >= var->yres_virtual) {
 			var->xoffset = var->yoffset = 0;
 		} else {
 			if (var->xoffset > var->xres_virtual - var->xres ||
-		    	    var->yoffset > var->yres_virtual - var->yres || 
+			    var->yoffset > var->yres_virtual - var->yres ||
 			    var->xoffset < 0 || var->yoffset < 0)
 				var->xoffset = var->yoffset = 0;
 		}
@@ -478,7 +475,7 @@
 		var->xoffset = var->yoffset = 0;
 	}
 
-	/* 
+	/*
 	 * XXX: Need to be more creative with this (i.e. allow doublecan for
 	 * PAL/NTSC output).
 	 */
@@ -507,7 +504,7 @@
 		var->vsync_len    = par->borderstop_v +
 				   (par->vsync_total - par->borderstop_v);
 	}
-		
+
 	hsync_total = var->left_margin + var->xres + var->right_margin +
 		      var->hsync_len;
 	vtotal = var->upper_margin + var->yres + var->lower_margin +
@@ -531,7 +528,7 @@
 			}
 		}
 	}
-	
+
 	/* Check memory sizes */
 	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
 	if (line_length * var->yres_virtual > info->fix.smem_len)
@@ -552,7 +549,7 @@
 	          DISP_DIWADDRS);
 }
 
-/* 
+/*
  * Initialize the video mode.  Currently, the 16bpp and 24bpp modes aren't
  * very stable.  It's probably due to the fact that a lot of the 2D video
  * registers are still undocumented.
@@ -592,18 +589,18 @@
 	/* display window start position */
 	fb_writel(par->diwstart_h, DISP_DIWHSTRT);
 	fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT);
-	
+
 	/* misc. settings */
 	fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF);
 
 	/* clock doubler (for VGA), scan doubler, display enable */
-	fb_writel(((video_output == VO_VGA) << 23) | 
+	fb_writel(((video_output == VO_VGA) << 23) |
 	          (par->is_doublescan << 1) | 1, DISP_DIWMODE);
 
 	/* bits per pixel */
 	fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
 
-	/* video enable, color sync, interlace, 
+	/* video enable, color sync, interlace,
 	 * hsync and vsync polarity (currently unused) */
 	fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
 }
@@ -657,7 +654,7 @@
 static int pvr2_init_cable(void)
 {
 	if (cable_type < 0) {
-		fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000, 
+		fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
 	                  PCTRA);
 		cable_type = (fb_readw(PDTRA) >> 8) & 3;
 	}
@@ -687,7 +684,7 @@
 	pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
 	if (!pages)
 		return -ENOMEM;
-	
+
 	down_read(&current->mm->mmap_sem);
 	ret = get_user_pages(current, current->mm, (unsigned long)buf,
 			     nr_pages, WRITE, 0, pages, NULL);
@@ -700,7 +697,7 @@
 	}
 
 	dma_configure_channel(shdma, 0x12c1);
-	
+
 	dst   = (unsigned long)fb_info->screen_base + *ppos;
 	start = (unsigned long)page_address(pages[0]);
 	end   = (unsigned long)page_address(pages[nr_pages]);
@@ -744,7 +741,7 @@
 	kfree(pages);
 
 	return ret;
-} 
+}
 #endif /* CONFIG_SH_DMA */
 
 /**
@@ -765,21 +762,21 @@
  * in for flexibility anyways. Who knows, maybe someone has tv-out on a
  * PCI-based version of these things ;-)
  */
-static int __init pvr2fb_common_init(void)
+static int __devinit pvr2fb_common_init(void)
 {
 	struct pvr2fb_par *par = currentpar;
 	unsigned long modememused, rev;
 
 	fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start,
 					       pvr2_fix.smem_len);
-	
+
 	if (!fb_info->screen_base) {
 		printk(KERN_ERR "pvr2fb: Failed to remap smem space\n");
 		goto out_err;
 	}
 
 	par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start,
-					 		pvr2_fix.mmio_len);
+							pvr2_fix.mmio_len);
 	if (!par->mmio_base) {
 		printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n");
 		goto out_err;
@@ -820,7 +817,7 @@
 	printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n",
 	       fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f,
 	       modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10));
-	printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", 
+	printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
 	       fb_info->node, fb_info->var.xres, fb_info->var.yres,
 	       fb_info->var.bits_per_pixel,
 	       get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
@@ -878,8 +875,8 @@
 			video_output = VO_NTSC;
 		}
 	}
-	
-	/* 
+
+	/*
 	 * Nothing exciting about the DC PVR2 .. only a measly 8MiB.
 	 */
 	pvr2_fix.smem_start	= 0xa5000000;	/* RAM starts here */
@@ -903,7 +900,7 @@
 	return pvr2fb_common_init();
 }
 
-static void pvr2fb_dc_exit(void)
+static void __exit pvr2fb_dc_exit(void)
 {
 	if (fb_info->screen_base) {
 		iounmap(fb_info->screen_base);
@@ -987,13 +984,13 @@
 	return pci_register_driver(&pvr2fb_pci_driver);
 }
 
-static void pvr2fb_pci_exit(void)
+static void __exit pvr2fb_pci_exit(void)
 {
 	pci_unregister_driver(&pvr2fb_pci_driver);
 }
 #endif /* CONFIG_PCI */
 
-static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
+static int __devinit pvr2_get_param(const struct pvr2_params *p, const char *s,
                                    int val, int size)
 {
 	int i;
@@ -1021,7 +1018,7 @@
  */
 
 #ifndef MODULE
-int __init pvr2fb_setup(char *options)
+static int __init pvr2fb_setup(char *options)
 {
 	char *this_opt;
 	char cable_arg[80];
@@ -1061,7 +1058,7 @@
 	int (*init)(void);
 	void (*exit)(void);
 	char name[16];
-} board_list[] = {
+} board_driver[] = {
 #ifdef CONFIG_SH_DREAMCAST
 	{ pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" },
 #endif
@@ -1071,7 +1068,7 @@
 	{ 0, },
 };
 
-int __init pvr2fb_init(void)
+static int __init pvr2fb_init(void)
 {
 	int i, ret = -ENODEV;
 	int size;
@@ -1095,8 +1092,8 @@
 
 	currentpar = (struct pvr2fb_par *)(fb_info + 1);
 
-	for (i = 0; i < ARRAY_SIZE(board_list); i++) {
-		struct pvr2_board *pvr_board = board_list + i;
+	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+		struct pvr2_board *pvr_board = board_driver + i;
 
 		if (!pvr_board->init)
 			continue;
@@ -1118,13 +1115,13 @@
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(board_list); i++) {
-		struct pvr2_board *pvr_board = board_list + i;
+	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+		struct pvr2_board *pvr_board = board_driver + i;
 
 		if (pvr_board->exit)
 			pvr_board->exit();
 	}
-		
+
 #ifdef CONFIG_SH_STORE_QUEUES
 	sq_unmap(pvr2fb_map);
 #endif
@@ -1139,4 +1136,3 @@
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
 MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards");
 MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 48536c3..4beac1d 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -95,7 +95,7 @@
 	/* mapped in q40/config.c */
 	q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR;
 
-	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
 	if (!info)
 		return -ENOMEM;
 
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index ebb6756..4fb1624 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -752,7 +752,7 @@
 	struct fb_info *info;
 	char *monitor;
 
-	info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 16, &dev->dev);
 	if (!info)
 		return -ENOMEM;
 	par = info->par;
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index d5e2d9c..d53bf69 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -479,7 +479,7 @@
 	struct fb_var_screeninfo default_var;
 
 	struct fb_fix_screeninfo sisfb_fix;
-	u32		pseudo_palette[17];
+	u32		pseudo_palette[16];
 
 	struct sisfb_monitor {
 		u16 hmin;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 93d07ef..e8ccace 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1405,12 +1405,18 @@
 		}
 		break;
 	case 16:
+		if (regno >= 16)
+			break;
+
 		((u32 *)(info->pseudo_palette))[regno] =
 				(red & 0xf800)          |
 				((green & 0xfc00) >> 5) |
 				((blue & 0xf800) >> 11);
 		break;
 	case 32:
+		if (regno >= 16)
+			break;
+
 		red >>= 8;
 		green >>= 8;
 		blue >>= 8;
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 5c0dab6..89facb7 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1634,7 +1634,7 @@
 		      FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
 	info->fbops = &tgafb_ops;
 	info->screen_base = par->tga_fb_base;
-	info->pseudo_palette = (void *)(par + 1);
+	info->pseudo_palette = par->palette;
 
 	/* This should give a reasonable default video mode.  */
 	if (tga_bus_pci) {
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 55e8aa4..c699864 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -976,7 +976,7 @@
 		return 1;
 
 
-	if (bpp==8) {
+	if (bpp == 8) {
 		t_outb(0xFF,0x3C6);
 		t_outb(regno,0x3C8);
 
@@ -984,19 +984,21 @@
 		t_outb(green>>10,0x3C9);
 		t_outb(blue>>10,0x3C9);
 
-	} else if (bpp == 16) {	/* RGB 565 */
-		u32 col;
+	} else if (regno < 16) {
+		if (bpp == 16) {	/* RGB 565 */
+			u32 col;
 
-		col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
-			((blue & 0xF800) >> 11);
-		col |= col << 16;	
-		((u32 *)(info->pseudo_palette))[regno] = col;
-	} else if (bpp == 32)		/* ARGB 8888 */
-		((u32*)info->pseudo_palette)[regno] =
-			((transp & 0xFF00) <<16) 	|
-			((red & 0xFF00) << 8) 		|
-			((green & 0xFF00))		|
-			((blue & 0xFF00)>>8);
+			col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
+				((blue & 0xF800) >> 11);
+			col |= col << 16;
+			((u32 *)(info->pseudo_palette))[regno] = col;
+		} else if (bpp == 32)		/* ARGB 8888 */
+			((u32*)info->pseudo_palette)[regno] =
+				((transp & 0xFF00) <<16) 	|
+				((red & 0xFF00) << 8) 		|
+				((green & 0xFF00))		|
+				((blue & 0xFF00)>>8);
+	}
 
 //	debug("exit\n");
 	return 0;
diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
index 07389ba..e6f7c78 100644
--- a/drivers/video/tx3912fb.c
+++ b/drivers/video/tx3912fb.c
@@ -291,7 +291,7 @@
 	fb_info.fbops = &tx3912fb_ops;
 	fb_info.var = tx3912fb_var;
 	fb_info.fix = tx3912fb_fix;
-	fb_info.pseudo_palette = pseudo_palette;
+	fb_info.pseudo_palette = cfb8;
 	fb_info.flags = FBINFO_DEFAULT;
 
 	/* Clear the framebuffer */
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 30c0b94..4c3a633 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -68,26 +68,26 @@
 
 /* CRT timing register sets */
 
-struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
-struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
-struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
-struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
 
-struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
-struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
-struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
-struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
-struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
 
-struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
-struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
-struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
 
-struct svga_timing_regs vt8623_timing_regs     = {
+static struct svga_timing_regs vt8623_timing_regs     = {
 	vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
 	vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
 	vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
@@ -903,7 +903,7 @@
 
 /* Driver Initialisation */
 
-int __init vt8623fb_init(void)
+static int __init vt8623fb_init(void)
 {
 
 #ifndef MODULE
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index ca75b3a..6854fd6 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -1,8 +1,6 @@
-menu "Dallas's 1-wire bus"
-	depends on HAS_IOMEM
-
-config W1
+menuconfig W1
 	tristate "Dallas's 1-wire support"
+	depends on HAS_IOMEM
 	---help---
 	  Dallas' 1-wire bus is useful to connect slow 1-pin devices
 	  such as iButtons and thermal sensors.
@@ -12,8 +10,10 @@
 	  This W1 support can also be built as a module.  If so, the module
 	  will be called wire.ko.
 
+if W1
+
 config W1_CON
-	depends on CONNECTOR && W1
+	depends on CONNECTOR
 	bool "Userspace communication over connector"
 	default y
 	--- help ---
@@ -27,4 +27,4 @@
 source drivers/w1/masters/Kconfig
 source drivers/w1/slaves/Kconfig
 
-endmenu
+endif # W1
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 8f77933..8236d44 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -3,11 +3,10 @@
 #
 
 menu "1-wire Bus Masters"
-	depends on W1
 
 config W1_MASTER_MATROX
 	tristate "Matrox G400 transport layer for 1-wire"
-	depends on W1 && PCI
+	depends on PCI
 	help
 	  Say Y here if you want to communicate with your 1-wire devices
 	  using Matrox's G400 GPIO pins.
@@ -17,7 +16,7 @@
 
 config W1_MASTER_DS2490
 	tristate "DS2490 USB <-> W1 transport layer for 1-wire"
-  	depends on W1 && USB
+  	depends on USB
   	help
 	  Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges,
 	  for example DS9490*.
@@ -27,7 +26,7 @@
 
 config W1_MASTER_DS2482
 	tristate "Maxim DS2482 I2C to 1-Wire bridge"
-	depends on I2C && W1 && EXPERIMENTAL
+	depends on I2C && EXPERIMENTAL
 	help
 	  If you say yes here you get support for the Maxim DS2482
 	  I2C to 1-Wire bridge.
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index df95d6c..3df29a1 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -3,25 +3,21 @@
 #
 
 menu "1-wire Slaves"
-	depends on W1
 
 config W1_SLAVE_THERM
 	tristate "Thermal family implementation"
-	depends on W1
 	help
 	  Say Y here if you want to connect 1-wire thermal sensors to your
 	  wire.
 
 config W1_SLAVE_SMEM
 	tristate "Simple 64bit memory family implementation"
-	depends on W1
 	help
 	  Say Y here if you want to connect 1-wire
 	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
 
 config W1_SLAVE_DS2433
 	tristate "4kb EEPROM family support (DS2433)"
-	depends on W1
 	help
 	  Say Y here if you want to use a 1-wire
 	  4kb EEPROM family device (DS2433).
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index f5c5b76..c633210 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -805,6 +805,7 @@
 	struct w1_master *dev, *n;
 	int have_to_wait = 0;
 
+	set_freezable();
 	while (!kthread_should_stop() || have_to_wait) {
 		have_to_wait = 0;
 
diff --git a/fs/Kconfig b/fs/Kconfig
index 94b9d86..613df55 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -991,7 +991,7 @@
 
 config HUGETLBFS
 	bool "HugeTLB file system support"
-	depends on X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+	depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN
 	help
 	  hugetlbfs is a filesystem backing for HugeTLB pages, based on
 	  ramfs. For architectures that support it, say Y here and read
@@ -1675,6 +1675,7 @@
 config NFSD_V4
 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
 	depends on NFSD_V3 && EXPERIMENTAL
+	select RPCSEC_GSS_KRB5
 	help
 	  If you would like to include the NFSv4 server as well as the NFSv2
 	  and NFSv3 servers, say Y here.  This feature is experimental, and
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 73ce561..a666710 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -8,6 +8,7 @@
 	cmservice.o \
 	dir.o \
 	file.o \
+	flock.o \
 	fsclient.o \
 	inode.o \
 	main.o \
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index 2452579..c548aa3 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -37,6 +37,13 @@
 	AFS_FTYPE_SYMLINK	= 3,
 } afs_file_type_t;
 
+typedef enum {
+	AFS_LOCK_READ		= 0,	/* read lock request */
+	AFS_LOCK_WRITE		= 1,	/* write lock request */
+} afs_lock_type_t;
+
+#define AFS_LOCKWAIT		(5 * 60) /* time until a lock times out (seconds) */
+
 /*
  * AFS file identifier
  */
@@ -120,6 +127,7 @@
 	struct afs_fid		parent;		/* parent dir ID for non-dirs only */
 	time_t			mtime_client;	/* last time client changed data */
 	time_t			mtime_server;	/* last time server changed data */
+	s32			lock_count;	/* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */
 };
 
 /*
diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h
index a18c374..eb64732 100644
--- a/fs/afs/afs_fs.h
+++ b/fs/afs/afs_fs.h
@@ -31,6 +31,9 @@
 	FSGETVOLUMEINFO		= 148,	/* AFS Get information about a volume */
 	FSGETVOLUMESTATUS	= 149,	/* AFS Get volume status information */
 	FSGETROOTVOLUME		= 151,	/* AFS Get root volume name */
+	FSSETLOCK		= 156,	/* AFS Request a file lock */
+	FSEXTENDLOCK		= 157,	/* AFS Extend a file lock */
+	FSRELEASELOCK		= 158,	/* AFS Release a file lock */
 	FSLOOKUP		= 161,	/* AFS lookup file in directory */
 	FSFETCHDATA64		= 65537, /* AFS Fetch file data */
 	FSSTOREDATA64		= 65538, /* AFS Store file data */
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index bacf518..b824394 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -125,6 +125,9 @@
 		spin_unlock(&server->cb_lock);
 
 		queue_work(afs_callback_update_worker, &vnode->cb_broken_work);
+		if (list_empty(&vnode->granted_locks) &&
+		    !list_empty(&vnode->pending_locks))
+			afs_lock_may_be_available(vnode);
 		spin_unlock(&vnode->lock);
 	}
 }
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 546c595..33fe39a 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -44,6 +44,7 @@
 	.open		= afs_dir_open,
 	.release	= afs_release,
 	.readdir	= afs_readdir,
+	.lock		= afs_lock,
 };
 
 const struct inode_operations afs_dir_inode_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index aede7eb..525f7c5 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -34,6 +34,8 @@
 	.mmap		= generic_file_readonly_mmap,
 	.splice_read	= generic_file_splice_read,
 	.fsync		= afs_fsync,
+	.lock		= afs_lock,
+	.flock		= afs_flock,
 };
 
 const struct inode_operations afs_file_inode_operations = {
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
new file mode 100644
index 0000000..8f07f8d
--- /dev/null
+++ b/fs/afs/flock.c
@@ -0,0 +1,558 @@
+/* AFS file locking support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/smp_lock.h>
+#include "internal.h"
+
+#define AFS_LOCK_GRANTED	0
+#define AFS_LOCK_PENDING	1
+
+static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl);
+static void afs_fl_release_private(struct file_lock *fl);
+
+static struct workqueue_struct *afs_lock_manager;
+
+static struct file_lock_operations afs_lock_ops = {
+	.fl_copy_lock		= afs_fl_copy_lock,
+	.fl_release_private	= afs_fl_release_private,
+};
+
+/*
+ * initialise the lock manager thread if it isn't already running
+ */
+static int afs_init_lock_manager(void)
+{
+	if (!afs_lock_manager) {
+		afs_lock_manager = create_singlethread_workqueue("kafs_lockd");
+		if (!afs_lock_manager)
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+/*
+ * destroy the lock manager thread if it's running
+ */
+void __exit afs_kill_lock_manager(void)
+{
+	if (afs_lock_manager)
+		destroy_workqueue(afs_lock_manager);
+}
+
+/*
+ * if the callback is broken on this vnode, then the lock may now be available
+ */
+void afs_lock_may_be_available(struct afs_vnode *vnode)
+{
+	_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+	queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0);
+}
+
+/*
+ * the lock will time out in 5 minutes unless we extend it, so schedule
+ * extension in a bit less than that time
+ */
+static void afs_schedule_lock_extension(struct afs_vnode *vnode)
+{
+	queue_delayed_work(afs_lock_manager, &vnode->lock_work,
+			   AFS_LOCKWAIT * HZ / 2);
+}
+
+/*
+ * do work for a lock, including:
+ * - probing for a lock we're waiting on but didn't get immediately
+ * - extending a lock that's close to timing out
+ */
+void afs_lock_work(struct work_struct *work)
+{
+	struct afs_vnode *vnode =
+		container_of(work, struct afs_vnode, lock_work.work);
+	struct file_lock *fl;
+	afs_lock_type_t type;
+	struct key *key;
+	int ret;
+
+	_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+	spin_lock(&vnode->lock);
+
+	if (test_bit(AFS_VNODE_UNLOCKING, &vnode->flags)) {
+		_debug("unlock");
+		spin_unlock(&vnode->lock);
+
+		/* attempt to release the server lock; if it fails, we just
+		 * wait 5 minutes and it'll time out anyway */
+		ret = afs_vnode_release_lock(vnode, vnode->unlock_key);
+		if (ret < 0)
+			printk(KERN_WARNING "AFS:"
+			       " Failed to release lock on {%x:%x} error %d\n",
+			       vnode->fid.vid, vnode->fid.vnode, ret);
+
+		spin_lock(&vnode->lock);
+		key_put(vnode->unlock_key);
+		vnode->unlock_key = NULL;
+		clear_bit(AFS_VNODE_UNLOCKING, &vnode->flags);
+	}
+
+	/* if we've got a lock, then it must be time to extend that lock as AFS
+	 * locks time out after 5 minutes */
+	if (!list_empty(&vnode->granted_locks)) {
+		_debug("extend");
+
+		if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
+			BUG();
+		fl = list_entry(vnode->granted_locks.next,
+				struct file_lock, fl_u.afs.link);
+		key = key_get(fl->fl_file->private_data);
+		spin_unlock(&vnode->lock);
+
+		ret = afs_vnode_extend_lock(vnode, key);
+		clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+		key_put(key);
+		switch (ret) {
+		case 0:
+			afs_schedule_lock_extension(vnode);
+			break;
+		default:
+			/* ummm... we failed to extend the lock - retry
+			 * extension shortly */
+			printk(KERN_WARNING "AFS:"
+			       " Failed to extend lock on {%x:%x} error %d\n",
+			       vnode->fid.vid, vnode->fid.vnode, ret);
+			queue_delayed_work(afs_lock_manager, &vnode->lock_work,
+					   HZ * 10);
+			break;
+		}
+		_leave(" [extend]");
+		return;
+	}
+
+	/* if we don't have a granted lock, then we must've been called back by
+	 * the server, and so if might be possible to get a lock we're
+	 * currently waiting for */
+	if (!list_empty(&vnode->pending_locks)) {
+		_debug("get");
+
+		if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
+			BUG();
+		fl = list_entry(vnode->pending_locks.next,
+				struct file_lock, fl_u.afs.link);
+		key = key_get(fl->fl_file->private_data);
+		type = (fl->fl_type == F_RDLCK) ?
+			AFS_LOCK_READ : AFS_LOCK_WRITE;
+		spin_unlock(&vnode->lock);
+
+		ret = afs_vnode_set_lock(vnode, key, type);
+		clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+		switch (ret) {
+		case -EWOULDBLOCK:
+			_debug("blocked");
+			break;
+		case 0:
+			_debug("acquired");
+			if (type == AFS_LOCK_READ)
+				set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+			else
+				set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+			ret = AFS_LOCK_GRANTED;
+		default:
+			spin_lock(&vnode->lock);
+			/* the pending lock may have been withdrawn due to a
+			 * signal */
+			if (list_entry(vnode->pending_locks.next,
+				       struct file_lock, fl_u.afs.link) == fl) {
+				fl->fl_u.afs.state = ret;
+				if (ret == AFS_LOCK_GRANTED)
+					list_move_tail(&fl->fl_u.afs.link,
+						       &vnode->granted_locks);
+				else
+					list_del_init(&fl->fl_u.afs.link);
+				wake_up(&fl->fl_wait);
+				spin_unlock(&vnode->lock);
+			} else {
+				_debug("withdrawn");
+				clear_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+				clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+				spin_unlock(&vnode->lock);
+				afs_vnode_release_lock(vnode, key);
+				if (!list_empty(&vnode->pending_locks))
+					afs_lock_may_be_available(vnode);
+			}
+			break;
+		}
+		key_put(key);
+		_leave(" [pend]");
+		return;
+	}
+
+	/* looks like the lock request was withdrawn on a signal */
+	spin_unlock(&vnode->lock);
+	_leave(" [no locks]");
+}
+
+/*
+ * pass responsibility for the unlocking of a vnode on the server to the
+ * manager thread, lest a pending signal in the calling thread interrupt
+ * AF_RXRPC
+ * - the caller must hold the vnode lock
+ */
+static void afs_defer_unlock(struct afs_vnode *vnode, struct key *key)
+{
+	cancel_delayed_work(&vnode->lock_work);
+	if (!test_and_clear_bit(AFS_VNODE_READLOCKED, &vnode->flags) &&
+	    !test_and_clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags))
+		BUG();
+	if (test_and_set_bit(AFS_VNODE_UNLOCKING, &vnode->flags))
+		BUG();
+	vnode->unlock_key = key_get(key);
+	afs_lock_may_be_available(vnode);
+}
+
+/*
+ * request a lock on a file on the server
+ */
+static int afs_do_setlk(struct file *file, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+	afs_lock_type_t type;
+	struct key *key = file->private_data;
+	int ret;
+
+	_enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
+
+	/* only whole-file locks are supported */
+	if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
+		return -EINVAL;
+
+	ret = afs_init_lock_manager();
+	if (ret < 0)
+		return ret;
+
+	fl->fl_ops = &afs_lock_ops;
+	INIT_LIST_HEAD(&fl->fl_u.afs.link);
+	fl->fl_u.afs.state = AFS_LOCK_PENDING;
+
+	type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
+
+	lock_kernel();
+
+	/* make sure we've got a callback on this file and that our view of the
+	 * data version is up to date */
+	ret = afs_vnode_fetch_status(vnode, NULL, key);
+	if (ret < 0)
+		goto error;
+
+	if (vnode->status.lock_count != 0 && !(fl->fl_flags & FL_SLEEP)) {
+		ret = -EAGAIN;
+		goto error;
+	}
+
+	spin_lock(&vnode->lock);
+
+	if (list_empty(&vnode->pending_locks)) {
+		/* if there's no-one else with a lock on this vnode, then we
+		 * need to ask the server for a lock */
+		if (list_empty(&vnode->granted_locks)) {
+			_debug("not locked");
+			ASSERTCMP(vnode->flags &
+				  ((1 << AFS_VNODE_LOCKING) |
+				   (1 << AFS_VNODE_READLOCKED) |
+				   (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+			list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
+			set_bit(AFS_VNODE_LOCKING, &vnode->flags);
+			spin_unlock(&vnode->lock);
+
+			ret = afs_vnode_set_lock(vnode, key, type);
+			clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+			switch (ret) {
+			case 0:
+				goto acquired_server_lock;
+			case -EWOULDBLOCK:
+				spin_lock(&vnode->lock);
+				ASSERT(list_empty(&vnode->granted_locks));
+				ASSERTCMP(vnode->pending_locks.next, ==,
+					  &fl->fl_u.afs.link);
+				goto wait;
+			default:
+				spin_lock(&vnode->lock);
+				list_del_init(&fl->fl_u.afs.link);
+				spin_unlock(&vnode->lock);
+				goto error;
+			}
+		}
+
+		/* if we've already got a readlock on the server and no waiting
+		 * writelocks, then we might be able to instantly grant another
+		 * readlock */
+		if (type == AFS_LOCK_READ &&
+		    vnode->flags & (1 << AFS_VNODE_READLOCKED)) {
+			_debug("instant readlock");
+			ASSERTCMP(vnode->flags &
+				  ((1 << AFS_VNODE_LOCKING) |
+				   (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+			ASSERT(!list_empty(&vnode->granted_locks));
+			goto sharing_existing_lock;
+		}
+	}
+
+	/* otherwise, we need to wait for a local lock to become available */
+	_debug("wait local");
+	list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
+wait:
+	if (!(fl->fl_flags & FL_SLEEP)) {
+		_debug("noblock");
+		ret = -EAGAIN;
+		goto abort_attempt;
+	}
+	spin_unlock(&vnode->lock);
+
+	/* now we need to sleep and wait for the lock manager thread to get the
+	 * lock from the server */
+	_debug("sleep");
+	ret = wait_event_interruptible(fl->fl_wait,
+				       fl->fl_u.afs.state <= AFS_LOCK_GRANTED);
+	if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
+		ret = fl->fl_u.afs.state;
+		if (ret < 0)
+			goto error;
+		spin_lock(&vnode->lock);
+		goto given_lock;
+	}
+
+	/* we were interrupted, but someone may still be in the throes of
+	 * giving us the lock */
+	_debug("intr");
+	ASSERTCMP(ret, ==, -ERESTARTSYS);
+
+	spin_lock(&vnode->lock);
+	if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
+		ret = fl->fl_u.afs.state;
+		if (ret < 0) {
+			spin_unlock(&vnode->lock);
+			goto error;
+		}
+		goto given_lock;
+	}
+
+abort_attempt:
+	/* we aren't going to get the lock, either because we're unwilling to
+	 * wait, or because some signal happened */
+	_debug("abort");
+	if (list_empty(&vnode->granted_locks) &&
+	    vnode->pending_locks.next == &fl->fl_u.afs.link) {
+		if (vnode->pending_locks.prev != &fl->fl_u.afs.link) {
+			/* kick the next pending lock into having a go */
+			list_del_init(&fl->fl_u.afs.link);
+			afs_lock_may_be_available(vnode);
+		}
+	} else {
+		list_del_init(&fl->fl_u.afs.link);
+	}
+	spin_unlock(&vnode->lock);
+	goto error;
+
+acquired_server_lock:
+	/* we've acquired a server lock, but it needs to be renewed after 5
+	 * mins */
+	spin_lock(&vnode->lock);
+	afs_schedule_lock_extension(vnode);
+	if (type == AFS_LOCK_READ)
+		set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+	else
+		set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+sharing_existing_lock:
+	/* the lock has been granted as far as we're concerned... */
+	fl->fl_u.afs.state = AFS_LOCK_GRANTED;
+	list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks);
+given_lock:
+	/* ... but we do still need to get the VFS's blessing */
+	ASSERT(!(vnode->flags & (1 << AFS_VNODE_LOCKING)));
+	ASSERT((vnode->flags & ((1 << AFS_VNODE_READLOCKED) |
+				(1 << AFS_VNODE_WRITELOCKED))) != 0);
+	ret = posix_lock_file(file, fl, NULL);
+	if (ret < 0)
+		goto vfs_rejected_lock;
+	spin_unlock(&vnode->lock);
+
+	/* again, make sure we've got a callback on this file and, again, make
+	 * sure that our view of the data version is up to date (we ignore
+	 * errors incurred here and deal with the consequences elsewhere) */
+	afs_vnode_fetch_status(vnode, NULL, key);
+
+error:
+	unlock_kernel();
+	_leave(" = %d", ret);
+	return ret;
+
+vfs_rejected_lock:
+	/* the VFS rejected the lock we just obtained, so we have to discard
+	 * what we just got */
+	_debug("vfs refused %d", ret);
+	list_del_init(&fl->fl_u.afs.link);
+	if (list_empty(&vnode->granted_locks))
+		afs_defer_unlock(vnode, key);
+	spin_unlock(&vnode->lock);
+	goto abort_attempt;
+}
+
+/*
+ * unlock on a file on the server
+ */
+static int afs_do_unlk(struct file *file, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+	struct key *key = file->private_data;
+	int ret;
+
+	_enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
+
+	/* only whole-file unlocks are supported */
+	if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
+		return -EINVAL;
+
+	fl->fl_ops = &afs_lock_ops;
+	INIT_LIST_HEAD(&fl->fl_u.afs.link);
+	fl->fl_u.afs.state = AFS_LOCK_PENDING;
+
+	spin_lock(&vnode->lock);
+	ret = posix_lock_file(file, fl, NULL);
+	if (ret < 0) {
+		spin_unlock(&vnode->lock);
+		_leave(" = %d [vfs]", ret);
+		return ret;
+	}
+
+	/* discard the server lock only if all granted locks are gone */
+	if (list_empty(&vnode->granted_locks))
+		afs_defer_unlock(vnode, key);
+	spin_unlock(&vnode->lock);
+	_leave(" = 0");
+	return 0;
+}
+
+/*
+ * return information about a lock we currently hold, if indeed we hold one
+ */
+static int afs_do_getlk(struct file *file, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+	struct key *key = file->private_data;
+	int ret, lock_count;
+
+	_enter("");
+
+	fl->fl_type = F_UNLCK;
+
+	mutex_lock(&vnode->vfs_inode.i_mutex);
+
+	/* check local lock records first */
+	ret = 0;
+	if (posix_test_lock(file, fl) == 0) {
+		/* no local locks; consult the server */
+		ret = afs_vnode_fetch_status(vnode, NULL, key);
+		if (ret < 0)
+			goto error;
+		lock_count = vnode->status.lock_count;
+		if (lock_count) {
+			if (lock_count > 0)
+				fl->fl_type = F_RDLCK;
+			else
+				fl->fl_type = F_WRLCK;
+			fl->fl_start = 0;
+			fl->fl_end = OFFSET_MAX;
+		}
+	}
+
+error:
+	mutex_unlock(&vnode->vfs_inode.i_mutex);
+	_leave(" = %d [%hd]", ret, fl->fl_type);
+	return ret;
+}
+
+/*
+ * manage POSIX locks on a file
+ */
+int afs_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+
+	_enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}",
+	       vnode->fid.vid, vnode->fid.vnode, cmd,
+	       fl->fl_type, fl->fl_flags,
+	       (long long) fl->fl_start, (long long) fl->fl_end);
+
+	/* AFS doesn't support mandatory locks */
+	if ((vnode->vfs_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
+	    fl->fl_type != F_UNLCK)
+		return -ENOLCK;
+
+	if (IS_GETLK(cmd))
+		return afs_do_getlk(file, fl);
+	if (fl->fl_type == F_UNLCK)
+		return afs_do_unlk(file, fl);
+	return afs_do_setlk(file, fl);
+}
+
+/*
+ * manage FLOCK locks on a file
+ */
+int afs_flock(struct file *file, int cmd, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+
+	_enter("{%x:%u},%d,{t=%x,fl=%x}",
+	       vnode->fid.vid, vnode->fid.vnode, cmd,
+	       fl->fl_type, fl->fl_flags);
+
+	/*
+	 * No BSD flocks over NFS allowed.
+	 * Note: we could try to fake a POSIX lock request here by
+	 * using ((u32) filp | 0x80000000) or some such as the pid.
+	 * Not sure whether that would be unique, though, or whether
+	 * that would break in other places.
+	 */
+	if (!(fl->fl_flags & FL_FLOCK))
+		return -ENOLCK;
+
+	/* we're simulating flock() locks using posix locks on the server */
+	fl->fl_owner = (fl_owner_t) file;
+	fl->fl_start = 0;
+	fl->fl_end = OFFSET_MAX;
+
+	if (fl->fl_type == F_UNLCK)
+		return afs_do_unlk(file, fl);
+	return afs_do_setlk(file, fl);
+}
+
+/*
+ * the POSIX lock management core VFS code copies the lock record and adds the
+ * copy into its own list, so we need to add that copy to the vnode's lock
+ * queue in the same place as the original (which will be deleted shortly
+ * after)
+ */
+static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl)
+{
+	_enter("");
+
+	list_add(&new->fl_u.afs.link, &fl->fl_u.afs.link);
+}
+
+/*
+ * need to remove this lock from the vnode queue when it's removed from the
+ * VFS's list
+ */
+static void afs_fl_release_private(struct file_lock *fl)
+{
+	_enter("");
+
+	list_del_init(&fl->fl_u.afs.link);
+}
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 5dff130..023b95b 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -67,7 +67,7 @@
 	EXTRACT(status->group);
 	bp++; /* sync counter */
 	data_version |= (u64) ntohl(*bp++) << 32;
-	bp++; /* lock count */
+	EXTRACT(status->lock_count);
 	size |= (u64) ntohl(*bp++) << 32;
 	bp++; /* spare 4 */
 	*_bp = bp;
@@ -1748,3 +1748,156 @@
 
 	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
 }
+
+/*
+ * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
+ */
+static int afs_deliver_fs_xxxx_lock(struct afs_call *call,
+				    struct sk_buff *skb, bool last)
+{
+	const __be32 *bp;
+
+	_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+
+	afs_transfer_reply(call, skb);
+	if (!last)
+		return 0;
+
+	if (call->reply_size != call->reply_max)
+		return -EBADMSG;
+
+	/* unmarshall the reply once we've received all of it */
+	bp = call->buffer;
+	/* xdr_decode_AFSVolSync(&bp, call->replyX); */
+
+	_leave(" = 0 [done]");
+	return 0;
+}
+
+/*
+ * FS.SetLock operation type
+ */
+static const struct afs_call_type afs_RXFSSetLock = {
+	.name		= "FS.SetLock",
+	.deliver	= afs_deliver_fs_xxxx_lock,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * FS.ExtendLock operation type
+ */
+static const struct afs_call_type afs_RXFSExtendLock = {
+	.name		= "FS.ExtendLock",
+	.deliver	= afs_deliver_fs_xxxx_lock,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * FS.ReleaseLock operation type
+ */
+static const struct afs_call_type afs_RXFSReleaseLock = {
+	.name		= "FS.ReleaseLock",
+	.deliver	= afs_deliver_fs_xxxx_lock,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * get a lock on a file
+ */
+int afs_fs_set_lock(struct afs_server *server,
+		    struct key *key,
+		    struct afs_vnode *vnode,
+		    afs_lock_type_t type,
+		    const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter("");
+
+	call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSSETLOCK);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+	*bp++ = htonl(type);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * extend a lock on a file
+ */
+int afs_fs_extend_lock(struct afs_server *server,
+		       struct key *key,
+		       struct afs_vnode *vnode,
+		       const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter("");
+
+	call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSEXTENDLOCK);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * release a lock on a file
+ */
+int afs_fs_release_lock(struct afs_server *server,
+			struct key *key,
+			struct afs_vnode *vnode,
+			const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter("");
+
+	call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSRELEASELOCK);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 2c55dd9..6306438 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -351,10 +351,18 @@
 #define AFS_VNODE_ZAP_DATA	3		/* set if vnode's data should be invalidated */
 #define AFS_VNODE_DELETED	4		/* set if vnode deleted on server */
 #define AFS_VNODE_MOUNTPOINT	5		/* set if vnode is a mountpoint symlink */
+#define AFS_VNODE_LOCKING	6		/* set if waiting for lock on vnode */
+#define AFS_VNODE_READLOCKED	7		/* set if vnode is read-locked on the server */
+#define AFS_VNODE_WRITELOCKED	8		/* set if vnode is write-locked on the server */
+#define AFS_VNODE_UNLOCKING	9		/* set if vnode is being unlocked on the server */
 
 	long			acl_order;	/* ACL check count (callback break count) */
 
 	struct list_head	writebacks;	/* alterations in pagecache that need writing */
+	struct list_head	pending_locks;	/* locks waiting to be granted */
+	struct list_head	granted_locks;	/* locks granted on this file */
+	struct delayed_work	lock_work;	/* work to be done in locking */
+	struct key		*unlock_key;	/* key to be used in unlocking */
 
 	/* outstanding callback notification on this file */
 	struct rb_node		server_rb;	/* link in server->fs_vnodes */
@@ -474,6 +482,15 @@
 extern int afs_release(struct inode *, struct file *);
 
 /*
+ * flock.c
+ */
+extern void __exit afs_kill_lock_manager(void);
+extern void afs_lock_work(struct work_struct *);
+extern void afs_lock_may_be_available(struct afs_vnode *);
+extern int afs_lock(struct file *, int, struct file_lock *);
+extern int afs_flock(struct file *, int, struct file_lock *);
+
+/*
  * fsclient.c
  */
 extern int afs_fs_fetch_file_status(struct afs_server *, struct key *,
@@ -513,6 +530,15 @@
 				    struct afs_vnode *,
 				    struct afs_volume_status *,
 				    const struct afs_wait_mode *);
+extern int afs_fs_set_lock(struct afs_server *, struct key *,
+			   struct afs_vnode *, afs_lock_type_t,
+			   const struct afs_wait_mode *);
+extern int afs_fs_extend_lock(struct afs_server *, struct key *,
+			      struct afs_vnode *,
+			      const struct afs_wait_mode *);
+extern int afs_fs_release_lock(struct afs_server *, struct key *,
+			       struct afs_vnode *,
+			       const struct afs_wait_mode *);
 
 /*
  * inode.c
@@ -681,6 +707,10 @@
 extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *);
 extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *,
 				       struct afs_volume_status *);
+extern int afs_vnode_set_lock(struct afs_vnode *, struct key *,
+			      afs_lock_type_t);
+extern int afs_vnode_extend_lock(struct afs_vnode *, struct key *);
+extern int afs_vnode_release_lock(struct afs_vnode *, struct key *);
 
 /*
  * volume.c
diff --git a/fs/afs/main.c b/fs/afs/main.c
index cd21195..0f60f6b 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -168,6 +168,7 @@
 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
 
 	afs_fs_exit();
+	afs_kill_lock_manager();
 	afs_close_socket();
 	afs_purge_servers();
 	afs_callback_update_kill();
diff --git a/fs/afs/misc.c b/fs/afs/misc.c
index d1a889c..2d33a5f 100644
--- a/fs/afs/misc.c
+++ b/fs/afs/misc.c
@@ -35,6 +35,7 @@
 	case VOVERQUOTA:	return -EDQUOT;
 	case VBUSY:		return -EBUSY;
 	case VMOVED:		return -ENXIO;
+	case 0x2f6df0a:		return -EWOULDBLOCK;
 	case 0x2f6df0c:		return -EACCES;
 	case 0x2f6df0f:		return -EBUSY;
 	case 0x2f6df10:		return -EEXIST;
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 13df512..6edb566 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -201,23 +201,9 @@
  */
 static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	/* lock the list against modification */
 	down_read(&afs_proc_cells_sem);
-
-	/* allow for the header line */
-	if (!pos)
-		return (void *) 1;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &afs_proc_cells)
-		if (!pos--)
-			break;
-
-	return _p != &afs_proc_cells ? _p : NULL;
+	return seq_list_start_head(&afs_proc_cells, *_pos);
 }
 
 /*
@@ -225,14 +211,7 @@
  */
 static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = v == (void *) 1 ? afs_proc_cells.next : _p->next;
-
-	return _p != &afs_proc_cells ? _p : NULL;
+	return seq_list_next(v, &afs_proc_cells, pos);
 }
 
 /*
@@ -250,7 +229,7 @@
 {
 	struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
 
-	if (v == (void *) 1) {
+	if (v == &afs_proc_cells) {
 		/* display header on line 1 */
 		seq_puts(m, "USE NAME\n");
 		return 0;
@@ -503,26 +482,13 @@
  */
 static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = m->private;
-	loff_t pos = *_pos;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
 
 	/* lock the list against modification */
 	down_read(&cell->vl_sem);
-
-	/* allow for the header line */
-	if (!pos)
-		return (void *) 1;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &cell->vl_list)
-		if (!pos--)
-			break;
-
-	return _p != &cell->vl_list ? _p : NULL;
+	return seq_list_start_head(&cell->vl_list, *_pos);
 }
 
 /*
@@ -531,17 +497,10 @@
 static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
 					loff_t *_pos)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = p->private;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
-
-	(*_pos)++;
-
-	_p = v;
-	_p = (v == (void *) 1) ? cell->vl_list.next : _p->next;
-
-	return (_p != &cell->vl_list) ? _p : NULL;
+	return seq_list_next(v, &cell->vl_list, _pos);
 }
 
 /*
@@ -569,11 +528,12 @@
  */
 static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
 {
+	struct afs_cell *cell = m->private;
 	struct afs_vlocation *vlocation =
 		list_entry(v, struct afs_vlocation, link);
 
 	/* display header on line 1 */
-	if (v == (void *) 1) {
+	if (v == &cell->vl_list) {
 		seq_puts(m, "USE STT VLID[0]  VLID[1]  VLID[2]  NAME\n");
 		return 0;
 	}
@@ -734,26 +694,13 @@
 static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
 	__acquires(m->private->servers_lock)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = m->private;
-	loff_t pos = *_pos;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
 
 	/* lock the list against modification */
 	read_lock(&cell->servers_lock);
-
-	/* allow for the header line */
-	if (!pos)
-		return (void *) 1;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &cell->servers)
-		if (!pos--)
-			break;
-
-	return _p != &cell->servers ? _p : NULL;
+	return seq_list_start_head(&cell->servers, *_pos);
 }
 
 /*
@@ -762,17 +709,10 @@
 static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
 					loff_t *_pos)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = p->private;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
-
-	(*_pos)++;
-
-	_p = v;
-	_p = v == (void *) 1 ? cell->servers.next : _p->next;
-
-	return _p != &cell->servers ? _p : NULL;
+	return seq_list_next(v, &cell->servers, _pos);
 }
 
 /*
@@ -791,11 +731,12 @@
  */
 static int afs_proc_cell_servers_show(struct seq_file *m, void *v)
 {
+	struct afs_cell *cell = m->private;
 	struct afs_server *server = list_entry(v, struct afs_server, link);
 	char ipaddr[20];
 
 	/* display header on line 1 */
-	if (v == (void *) 1) {
+	if (v == &cell->servers) {
 		seq_puts(m, "USE ADDR            STATE\n");
 		return 0;
 	}
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 2e8496b..993cdf1 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -460,6 +460,9 @@
 	spin_lock_init(&vnode->writeback_lock);
 	spin_lock_init(&vnode->lock);
 	INIT_LIST_HEAD(&vnode->writebacks);
+	INIT_LIST_HEAD(&vnode->pending_locks);
+	INIT_LIST_HEAD(&vnode->granted_locks);
+	INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);
 	INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
 }
 
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index 232c55d..2f05c4f 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -561,7 +561,7 @@
 /*
  * create a hard link
  */
-extern int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
+int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
 			  struct key *key, const char *name)
 {
 	struct afs_server *server;
@@ -887,11 +887,6 @@
 	       vnode->fid.unique,
 	       key_serial(key));
 
-	/* this op will fetch the status */
-	spin_lock(&vnode->lock);
-	vnode->update_cnt++;
-	spin_unlock(&vnode->lock);
-
 	do {
 		/* pick a server to query */
 		server = afs_volume_pick_fileserver(vnode);
@@ -905,20 +900,127 @@
 	} while (!afs_volume_release_fileserver(vnode, server, ret));
 
 	/* adjust the flags */
-	if (ret == 0) {
-		afs_vnode_finalise_status_update(vnode, server);
+	if (ret == 0)
 		afs_put_server(server);
-	} else {
-		afs_vnode_status_update_failed(vnode, ret);
-	}
 
 	_leave(" = %d", ret);
 	return ret;
 
 no_server:
-	spin_lock(&vnode->lock);
-	vnode->update_cnt--;
-	ASSERTCMP(vnode->update_cnt, >=, 0);
-	spin_unlock(&vnode->lock);
+	return PTR_ERR(server);
+}
+
+/*
+ * get a lock on a file
+ */
+int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key,
+		       afs_lock_type_t type)
+{
+	struct afs_server *server;
+	int ret;
+
+	_enter("%s{%x:%u.%u},%x,%u",
+	       vnode->volume->vlocation->vldb.name,
+	       vnode->fid.vid,
+	       vnode->fid.vnode,
+	       vnode->fid.unique,
+	       key_serial(key), type);
+
+	do {
+		/* pick a server to query */
+		server = afs_volume_pick_fileserver(vnode);
+		if (IS_ERR(server))
+			goto no_server;
+
+		_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+		ret = afs_fs_set_lock(server, key, vnode, type, &afs_sync_call);
+
+	} while (!afs_volume_release_fileserver(vnode, server, ret));
+
+	/* adjust the flags */
+	if (ret == 0)
+		afs_put_server(server);
+
+	_leave(" = %d", ret);
+	return ret;
+
+no_server:
+	return PTR_ERR(server);
+}
+
+/*
+ * extend a lock on a file
+ */
+int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key)
+{
+	struct afs_server *server;
+	int ret;
+
+	_enter("%s{%x:%u.%u},%x",
+	       vnode->volume->vlocation->vldb.name,
+	       vnode->fid.vid,
+	       vnode->fid.vnode,
+	       vnode->fid.unique,
+	       key_serial(key));
+
+	do {
+		/* pick a server to query */
+		server = afs_volume_pick_fileserver(vnode);
+		if (IS_ERR(server))
+			goto no_server;
+
+		_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+		ret = afs_fs_extend_lock(server, key, vnode, &afs_sync_call);
+
+	} while (!afs_volume_release_fileserver(vnode, server, ret));
+
+	/* adjust the flags */
+	if (ret == 0)
+		afs_put_server(server);
+
+	_leave(" = %d", ret);
+	return ret;
+
+no_server:
+	return PTR_ERR(server);
+}
+
+/*
+ * release a lock on a file
+ */
+int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key)
+{
+	struct afs_server *server;
+	int ret;
+
+	_enter("%s{%x:%u.%u},%x",
+	       vnode->volume->vlocation->vldb.name,
+	       vnode->fid.vid,
+	       vnode->fid.vnode,
+	       vnode->fid.unique,
+	       key_serial(key));
+
+	do {
+		/* pick a server to query */
+		server = afs_volume_pick_fileserver(vnode);
+		if (IS_ERR(server))
+			goto no_server;
+
+		_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+		ret = afs_fs_release_lock(server, key, vnode, &afs_sync_call);
+
+	} while (!afs_volume_release_fileserver(vnode, server, ret));
+
+	/* adjust the flags */
+	if (ret == 0)
+		afs_put_server(server);
+
+	_leave(" = %d", ret);
+	return ret;
+
+no_server:
 	return PTR_ERR(server);
 }
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index edc6748..b4a7588 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -53,7 +53,7 @@
 };
 
 /**
- * anon_inode_getfd - creates a new file instance by hooking it up to and
+ * anon_inode_getfd - creates a new file instance by hooking it up to an
  *                    anonymous inode, and a dentry that describe the "class"
  *                    of the file
  *
@@ -66,7 +66,7 @@
  *
  * Creates a new file by hooking it on a single inode. This is useful for files
  * that do not need to have a full-fledged inode in order to operate correctly.
- * All the files created with anon_inode_getfd() will share a single inode, by
+ * All the files created with anon_inode_getfd() will share a single inode,
  * hence saving memory and avoiding code duplication for the file/inode/dentry
  * setup.
  */
@@ -142,9 +142,9 @@
 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 /*
- * A single inode exist for all anon_inode files. Contrary to pipes,
- * anon_inode inodes has no per-instance data associated, so we can avoid
- * the allocation of multiple of them.
+ * A single inode exists for all anon_inode files. Contrary to pipes,
+ * anon_inode inodes have no associated per-instance data, so we need
+ * only allocate one of them.
  */
 static struct inode *anon_inode_mkinode(void)
 {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 08e4414..a27e42b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -45,7 +45,7 @@
 
 static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
-static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
 
 /*
  * If we don't support core dumping, then supply a NULL so we
@@ -80,7 +80,7 @@
 		.hasvdso	= 1
 };
 
-#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
+#define BAD_ADDR(x) IS_ERR_VALUE(x)
 
 static int set_brk(unsigned long start, unsigned long end)
 {
@@ -285,33 +285,70 @@
 #ifndef elf_map
 
 static unsigned long elf_map(struct file *filep, unsigned long addr,
-		struct elf_phdr *eppnt, int prot, int type)
+		struct elf_phdr *eppnt, int prot, int type,
+		unsigned long total_size)
 {
 	unsigned long map_addr;
-	unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
+	unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr);
+	unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
+	addr = ELF_PAGESTART(addr);
+	size = ELF_PAGEALIGN(size);
 
-	down_write(&current->mm->mmap_sem);
 	/* mmap() will return -EINVAL if given a zero size, but a
 	 * segment with zero filesize is perfectly valid */
-	if (eppnt->p_filesz + pageoffset)
-		map_addr = do_mmap(filep, ELF_PAGESTART(addr),
-				   eppnt->p_filesz + pageoffset, prot, type,
-				   eppnt->p_offset - pageoffset);
-	else
-		map_addr = ELF_PAGESTART(addr);
+	if (!size)
+		return addr;
+
+	down_write(&current->mm->mmap_sem);
+	/*
+	* total_size is the size of the ELF (interpreter) image.
+	* The _first_ mmap needs to know the full size, otherwise
+	* randomization might put this image into an overlapping
+	* position with the ELF binary image. (since size < total_size)
+	* So we first map the 'big' image - and unmap the remainder at
+	* the end. (which unmap is needed for ELF images with holes.)
+	*/
+	if (total_size) {
+		total_size = ELF_PAGEALIGN(total_size);
+		map_addr = do_mmap(filep, addr, total_size, prot, type, off);
+		if (!BAD_ADDR(map_addr))
+			do_munmap(current->mm, map_addr+size, total_size-size);
+	} else
+		map_addr = do_mmap(filep, addr, size, prot, type, off);
+
 	up_write(&current->mm->mmap_sem);
 	return(map_addr);
 }
 
 #endif /* !elf_map */
 
+static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
+{
+	int i, first_idx = -1, last_idx = -1;
+
+	for (i = 0; i < nr; i++) {
+		if (cmds[i].p_type == PT_LOAD) {
+			last_idx = i;
+			if (first_idx == -1)
+				first_idx = i;
+		}
+	}
+	if (first_idx == -1)
+		return 0;
+
+	return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz -
+				ELF_PAGESTART(cmds[first_idx].p_vaddr);
+}
+
+
 /* This is much more generalized than the library routine read function,
    so we keep this separate.  Technically the library read function
    is only provided so that we can read a.out libraries that have
    an ELF header */
 
 static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
-		struct file *interpreter, unsigned long *interp_load_addr)
+		struct file *interpreter, unsigned long *interp_map_addr,
+		unsigned long no_base)
 {
 	struct elf_phdr *elf_phdata;
 	struct elf_phdr *eppnt;
@@ -319,6 +356,7 @@
 	int load_addr_set = 0;
 	unsigned long last_bss = 0, elf_bss = 0;
 	unsigned long error = ~0UL;
+	unsigned long total_size;
 	int retval, i, size;
 
 	/* First of all, some simple consistency checks */
@@ -357,6 +395,12 @@
 		goto out_close;
 	}
 
+	total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
+	if (!total_size) {
+		error = -EINVAL;
+		goto out_close;
+	}
+
 	eppnt = elf_phdata;
 	for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
 		if (eppnt->p_type == PT_LOAD) {
@@ -374,9 +418,14 @@
 			vaddr = eppnt->p_vaddr;
 			if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
 				elf_type |= MAP_FIXED;
+			else if (no_base && interp_elf_ex->e_type == ET_DYN)
+				load_addr = -vaddr;
 
 			map_addr = elf_map(interpreter, load_addr + vaddr,
-					   eppnt, elf_prot, elf_type);
+					   eppnt, elf_prot, elf_type, total_size);
+			total_size = 0;
+			if (!*interp_map_addr)
+				*interp_map_addr = map_addr;
 			error = map_addr;
 			if (BAD_ADDR(map_addr))
 				goto out_close;
@@ -442,8 +491,7 @@
 			goto out_close;
 	}
 
-	*interp_load_addr = load_addr;
-	error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
+	error = load_addr;
 
 out_close:
 	kfree(elf_phdata);
@@ -540,7 +588,8 @@
 	int elf_exec_fileno;
 	int retval, i;
 	unsigned int size;
-	unsigned long elf_entry, interp_load_addr = 0;
+	unsigned long elf_entry;
+	unsigned long interp_load_addr = 0;
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long reloc_func_desc = 0;
 	char passed_fileno[6];
@@ -808,9 +857,7 @@
 	current->mm->start_stack = bprm->p;
 
 	/* Now we do a little grungy work by mmaping the ELF image into
-	   the correct location in memory.  At this point, we assume that
-	   the image should be loaded at fixed address, not at a variable
-	   address. */
+	   the correct location in memory. */
 	for(i = 0, elf_ppnt = elf_phdata;
 	    i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
 		int elf_prot = 0, elf_flags;
@@ -864,11 +911,15 @@
 			 * default mmap base, as well as whatever program they
 			 * might try to exec.  This is because the brk will
 			 * follow the loader, and is not movable.  */
+#ifdef CONFIG_X86
+			load_bias = 0;
+#else
 			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
+#endif
 		}
 
 		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-				elf_prot, elf_flags);
+				elf_prot, elf_flags,0);
 		if (BAD_ADDR(error)) {
 			send_sig(SIGKILL, current, 0);
 			retval = IS_ERR((void *)error) ?
@@ -944,13 +995,25 @@
 	}
 
 	if (elf_interpreter) {
-		if (interpreter_type == INTERPRETER_AOUT)
+		if (interpreter_type == INTERPRETER_AOUT) {
 			elf_entry = load_aout_interp(&loc->interp_ex,
 						     interpreter);
-		else
+		} else {
+			unsigned long uninitialized_var(interp_map_addr);
+
 			elf_entry = load_elf_interp(&loc->interp_elf_ex,
 						    interpreter,
-						    &interp_load_addr);
+						    &interp_map_addr,
+						    load_bias);
+			if (!BAD_ADDR(elf_entry)) {
+				/*
+				 * load_elf_interp() returns relocation
+				 * adjustment
+				 */
+				interp_load_addr = elf_entry;
+				elf_entry += loc->interp_elf_ex.e_entry;
+			}
+		}
 		if (BAD_ADDR(elf_entry)) {
 			force_sig(SIGSEGV, current);
 			retval = IS_ERR((void *)elf_entry) ?
diff --git a/fs/block_dev.c b/fs/block_dev.c
index b3e9bfa..3635315 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -588,12 +588,10 @@
 
 long nr_blockdev_pages(void)
 {
-	struct list_head *p;
+	struct block_device *bdev;
 	long ret = 0;
 	spin_lock(&bdev_lock);
-	list_for_each(p, &all_bdevs) {
-		struct block_device *bdev;
-		bdev = list_entry(p, struct block_device, bd_list);
+	list_for_each_entry(bdev, &all_bdevs, bd_list) {
 		ret += bdev->bd_inode->i_mapping->nrpages;
 	}
 	spin_unlock(&bdev_lock);
@@ -874,7 +872,7 @@
  */
 static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
 {
-	int ret;
+	int err;
 
 	if (!bo)
 		return -EINVAL;
@@ -882,15 +880,18 @@
 	if (!bd_holder_grab_dirs(bdev, bo))
 		return -EBUSY;
 
-	ret = add_symlink(bo->sdir, bo->sdev);
-	if (ret == 0) {
-		ret = add_symlink(bo->hdir, bo->hdev);
-		if (ret)
-			del_symlink(bo->sdir, bo->sdev);
+	err = add_symlink(bo->sdir, bo->sdev);
+	if (err)
+		return err;
+
+	err = add_symlink(bo->hdir, bo->hdev);
+	if (err) {
+		del_symlink(bo->sdir, bo->sdev);
+		return err;
 	}
-	if (ret == 0)
-		list_add_tail(&bo->list, &bdev->bd_holder_list);
-	return ret;
+
+	list_add_tail(&bo->list, &bdev->bd_holder_list);
+	return 0;
 }
 
 /**
@@ -948,7 +949,7 @@
 static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
 				struct kobject *kobj)
 {
-	int res;
+	int err;
 	struct bd_holder *bo, *found;
 
 	if (!kobj)
@@ -959,21 +960,24 @@
 		return -ENOMEM;
 
 	mutex_lock(&bdev->bd_mutex);
-	res = bd_claim(bdev, holder);
-	if (res == 0) {
-		found = find_bd_holder(bdev, bo);
-		if (found == NULL) {
-			res = add_bd_holder(bdev, bo);
-			if (res)
-				bd_release(bdev);
-		}
-	}
 
-	if (res || found)
-		free_bd_holder(bo);
+	err = bd_claim(bdev, holder);
+	if (err)
+		goto fail;
+
+	found = find_bd_holder(bdev, bo);
+	if (found)
+		goto fail;
+
+	err = add_bd_holder(bdev, bo);
+	if (err)
+		bd_release(bdev);
+	else
+		bo = NULL;
+fail:
 	mutex_unlock(&bdev->bd_mutex);
-
-	return res;
+	free_bd_holder(bo);
+	return err;
 }
 
 /**
@@ -987,15 +991,12 @@
 static void bd_release_from_kobject(struct block_device *bdev,
 					struct kobject *kobj)
 {
-	struct bd_holder *bo;
-
 	if (!kobj)
 		return;
 
 	mutex_lock(&bdev->bd_mutex);
 	bd_release(bdev);
-	if ((bo = del_bd_holder(bdev, kobj)))
-		free_bd_holder(bo);
+	free_bd_holder(del_bd_holder(bdev, kobj));
 	mutex_unlock(&bdev->bd_mutex);
 }
 
diff --git a/fs/buffer.c b/fs/buffer.c
index aa68206..0f90067 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -356,7 +356,7 @@
 	for_each_online_pgdat(pgdat) {
 		zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
 		if (*zones)
-			try_to_free_pages(zones, GFP_NOFS);
+			try_to_free_pages(zones, 0, GFP_NOFS);
 	}
 }
 
@@ -676,6 +676,39 @@
 EXPORT_SYMBOL(mark_buffer_dirty_inode);
 
 /*
+ * Mark the page dirty, and set it dirty in the radix tree, and mark the inode
+ * dirty.
+ *
+ * If warn is true, then emit a warning if the page is not uptodate and has
+ * not been truncated.
+ */
+static int __set_page_dirty(struct page *page,
+		struct address_space *mapping, int warn)
+{
+	if (unlikely(!mapping))
+		return !TestSetPageDirty(page);
+
+	if (TestSetPageDirty(page))
+		return 0;
+
+	write_lock_irq(&mapping->tree_lock);
+	if (page->mapping) {	/* Race with truncate? */
+		WARN_ON_ONCE(warn && !PageUptodate(page));
+
+		if (mapping_cap_account_dirty(mapping)) {
+			__inc_zone_page_state(page, NR_FILE_DIRTY);
+			task_io_account_write(PAGE_CACHE_SIZE);
+		}
+		radix_tree_tag_set(&mapping->page_tree,
+				page_index(page), PAGECACHE_TAG_DIRTY);
+	}
+	write_unlock_irq(&mapping->tree_lock);
+	__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+
+	return 1;
+}
+
+/*
  * Add a page to the dirty page list.
  *
  * It is a sad fact of life that this function is called from several places
@@ -702,7 +735,7 @@
  */
 int __set_page_dirty_buffers(struct page *page)
 {
-	struct address_space * const mapping = page_mapping(page);
+	struct address_space *mapping = page_mapping(page);
 
 	if (unlikely(!mapping))
 		return !TestSetPageDirty(page);
@@ -719,21 +752,7 @@
 	}
 	spin_unlock(&mapping->private_lock);
 
-	if (TestSetPageDirty(page))
-		return 0;
-
-	write_lock_irq(&mapping->tree_lock);
-	if (page->mapping) {	/* Race with truncate? */
-		if (mapping_cap_account_dirty(mapping)) {
-			__inc_zone_page_state(page, NR_FILE_DIRTY);
-			task_io_account_write(PAGE_CACHE_SIZE);
-		}
-		radix_tree_tag_set(&mapping->page_tree,
-				page_index(page), PAGECACHE_TAG_DIRTY);
-	}
-	write_unlock_irq(&mapping->tree_lock);
-	__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
-	return 1;
+	return __set_page_dirty(page, mapping, 1);
 }
 EXPORT_SYMBOL(__set_page_dirty_buffers);
 
@@ -982,7 +1001,7 @@
 	struct buffer_head *bh;
 
 	page = find_or_create_page(inode->i_mapping, index,
-		mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+		(mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
 	if (!page)
 		return NULL;
 
@@ -1026,11 +1045,6 @@
 /*
  * Create buffers for the specified block device block's page.  If
  * that page was dirty, the buffers are set dirty also.
- *
- * Except that's a bug.  Attaching dirty buffers to a dirty
- * blockdev's page can result in filesystem corruption, because
- * some of those buffers may be aliases of filesystem data.
- * grow_dev_page() will go BUG() if this happens.
  */
 static int
 grow_buffers(struct block_device *bdev, sector_t block, int size)
@@ -1137,8 +1151,9 @@
  */
 void fastcall mark_buffer_dirty(struct buffer_head *bh)
 {
+	WARN_ON_ONCE(!buffer_uptodate(bh));
 	if (!buffer_dirty(bh) && !test_set_buffer_dirty(bh))
-		__set_page_dirty_nobuffers(bh->b_page);
+		__set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0);
 }
 
 /*
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 8b0cbf4..bd0f2f2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -849,6 +849,7 @@
 	__u16  netfid;
 	int rc;
 
+	set_freezable();
 	do {
 		if (try_to_freeze()) 
 			continue;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f4e9266..0a1b8bd 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -363,6 +363,7 @@
 			GFP_KERNEL);
 	}
 
+	set_freezable();
 	while (!kthread_should_stop()) {
 		if (try_to_freeze())
 			continue;
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 1d71639..96df1d5 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -29,6 +29,7 @@
   */
 
 #include <linux/fs.h>
+#include <linux/exportfs.h>
  
 #ifdef CONFIG_CIFS_EXPERIMENTAL
  
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 6b44cdc..e440a7b 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -63,6 +63,7 @@
 #include <linux/wireless.h>
 #include <linux/atalk.h>
 #include <linux/blktrace_api.h>
+#include <linux/loop.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci.h>
@@ -3489,6 +3490,9 @@
 
 IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32)
 IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
+
+/* loop */
+IGNORE_IOCTL(LOOP_CLR_FD)
 };
 
 #define IOCTL_HASHSIZE 256
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 7b48c03..3b0185f 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -29,10 +29,11 @@
 
 struct configfs_dirent {
 	atomic_t		s_count;
+	int			s_dependent_count;
 	struct list_head	s_sibling;
 	struct list_head	s_children;
 	struct list_head	s_links;
-	void 			* s_element;
+	void			* s_element;
 	int			s_type;
 	umode_t			s_mode;
 	struct dentry		* s_dentry;
@@ -41,8 +42,8 @@
 
 #define CONFIGFS_ROOT		0x0001
 #define CONFIGFS_DIR		0x0002
-#define CONFIGFS_ITEM_ATTR 	0x0004
-#define CONFIGFS_ITEM_LINK 	0x0020
+#define CONFIGFS_ITEM_ATTR	0x0004
+#define CONFIGFS_ITEM_LINK	0x0020
 #define CONFIGFS_USET_DIR	0x0040
 #define CONFIGFS_USET_DEFAULT	0x0080
 #define CONFIGFS_USET_DROPPING	0x0100
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 5e6e37e..2f436d4 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -355,6 +355,10 @@
 			/* Mark that we've taken i_mutex */
 			sd->s_type |= CONFIGFS_USET_DROPPING;
 
+			/*
+			 * Yup, recursive.  If there's a problem, blame
+			 * deep nesting of default_groups
+			 */
 			ret = configfs_detach_prep(sd->s_dentry);
 			if (!ret)
 				continue;
@@ -562,7 +566,7 @@
 
 /*
  * All of link_obj/unlink_obj/link_group/unlink_group require that
- * subsys->su_sem is held.
+ * subsys->su_mutex is held.
  */
 
 static void unlink_obj(struct config_item *item)
@@ -714,6 +718,28 @@
 }
 
 /*
+ * After the item has been detached from the filesystem view, we are
+ * ready to tear it out of the hierarchy.  Notify the client before
+ * we do that so they can perform any cleanup that requires
+ * navigating the hierarchy.  A client does not need to provide this
+ * callback.  The subsystem semaphore MUST be held by the caller, and
+ * references must be valid for both items.  It also assumes the
+ * caller has validated ci_type.
+ */
+static void client_disconnect_notify(struct config_item *parent_item,
+				     struct config_item *item)
+{
+	struct config_item_type *type;
+
+	type = parent_item->ci_type;
+	BUG_ON(!type);
+
+	if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)
+		type->ct_group_ops->disconnect_notify(to_config_group(parent_item),
+						      item);
+}
+
+/*
  * Drop the initial reference from make_item()/make_group()
  * This function assumes that reference is held on item
  * and that item holds a valid reference to the parent.  Also, it
@@ -733,11 +759,244 @@
 	 */
 	if (type->ct_group_ops && type->ct_group_ops->drop_item)
 		type->ct_group_ops->drop_item(to_config_group(parent_item),
-						item);
+					      item);
 	else
 		config_item_put(item);
 }
 
+#ifdef DEBUG
+static void configfs_dump_one(struct configfs_dirent *sd, int level)
+{
+	printk(KERN_INFO "%*s\"%s\":\n", level, " ", configfs_get_name(sd));
+
+#define type_print(_type) if (sd->s_type & _type) printk(KERN_INFO "%*s %s\n", level, " ", #_type);
+	type_print(CONFIGFS_ROOT);
+	type_print(CONFIGFS_DIR);
+	type_print(CONFIGFS_ITEM_ATTR);
+	type_print(CONFIGFS_ITEM_LINK);
+	type_print(CONFIGFS_USET_DIR);
+	type_print(CONFIGFS_USET_DEFAULT);
+	type_print(CONFIGFS_USET_DROPPING);
+#undef type_print
+}
+
+static int configfs_dump(struct configfs_dirent *sd, int level)
+{
+	struct configfs_dirent *child_sd;
+	int ret = 0;
+
+	configfs_dump_one(sd, level);
+
+	if (!(sd->s_type & (CONFIGFS_DIR|CONFIGFS_ROOT)))
+		return 0;
+
+	list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+		ret = configfs_dump(child_sd, level + 2);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+#endif
+
+
+/*
+ * configfs_depend_item() and configfs_undepend_item()
+ *
+ * WARNING: Do not call these from a configfs callback!
+ *
+ * This describes these functions and their helpers.
+ *
+ * Allow another kernel system to depend on a config_item.  If this
+ * happens, the item cannot go away until the dependant can live without
+ * it.  The idea is to give client modules as simple an interface as
+ * possible.  When a system asks them to depend on an item, they just
+ * call configfs_depend_item().  If the item is live and the client
+ * driver is in good shape, we'll happily do the work for them.
+ *
+ * Why is the locking complex?  Because configfs uses the VFS to handle
+ * all locking, but this function is called outside the normal
+ * VFS->configfs path.  So it must take VFS locks to prevent the
+ * VFS->configfs stuff (configfs_mkdir(), configfs_rmdir(), etc).  This is
+ * why you can't call these functions underneath configfs callbacks.
+ *
+ * Note, btw, that this can be called at *any* time, even when a configfs
+ * subsystem isn't registered, or when configfs is loading or unloading.
+ * Just like configfs_register_subsystem().  So we take the same
+ * precautions.  We pin the filesystem.  We lock each i_mutex _in_order_
+ * on our way down the tree.  If we can find the target item in the
+ * configfs tree, it must be part of the subsystem tree as well, so we
+ * do not need the subsystem semaphore.  Holding the i_mutex chain locks
+ * out mkdir() and rmdir(), who might be racing us.
+ */
+
+/*
+ * configfs_depend_prep()
+ *
+ * Only subdirectories count here.  Files (CONFIGFS_NOT_PINNED) are
+ * attributes.  This is similar but not the same to configfs_detach_prep().
+ * Note that configfs_detach_prep() expects the parent to be locked when it
+ * is called, but we lock the parent *inside* configfs_depend_prep().  We
+ * do that so we can unlock it if we find nothing.
+ *
+ * Here we do a depth-first search of the dentry hierarchy looking for
+ * our object.  We take i_mutex on each step of the way down.  IT IS
+ * ESSENTIAL THAT i_mutex LOCKING IS ORDERED.  If we come back up a branch,
+ * we'll drop the i_mutex.
+ *
+ * If the target is not found, -ENOENT is bubbled up and we have released
+ * all locks.  If the target was found, the locks will be cleared by
+ * configfs_depend_rollback().
+ *
+ * This adds a requirement that all config_items be unique!
+ *
+ * This is recursive because the locking traversal is tricky.  There isn't
+ * much on the stack, though, so folks that need this function - be careful
+ * about your stack!  Patches will be accepted to make it iterative.
+ */
+static int configfs_depend_prep(struct dentry *origin,
+				struct config_item *target)
+{
+	struct configfs_dirent *child_sd, *sd = origin->d_fsdata;
+	int ret = 0;
+
+	BUG_ON(!origin || !sd);
+
+	/* Lock this guy on the way down */
+	mutex_lock(&sd->s_dentry->d_inode->i_mutex);
+	if (sd->s_element == target)  /* Boo-yah */
+		goto out;
+
+	list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+		if (child_sd->s_type & CONFIGFS_DIR) {
+			ret = configfs_depend_prep(child_sd->s_dentry,
+						   target);
+			if (!ret)
+				goto out;  /* Child path boo-yah */
+		}
+	}
+
+	/* We looped all our children and didn't find target */
+	mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
+	ret = -ENOENT;
+
+out:
+	return ret;
+}
+
+/*
+ * This is ONLY called if configfs_depend_prep() did its job.  So we can
+ * trust the entire path from item back up to origin.
+ *
+ * We walk backwards from item, unlocking each i_mutex.  We finish by
+ * unlocking origin.
+ */
+static void configfs_depend_rollback(struct dentry *origin,
+				     struct config_item *item)
+{
+	struct dentry *dentry = item->ci_dentry;
+
+	while (dentry != origin) {
+		mutex_unlock(&dentry->d_inode->i_mutex);
+		dentry = dentry->d_parent;
+	}
+
+	mutex_unlock(&origin->d_inode->i_mutex);
+}
+
+int configfs_depend_item(struct configfs_subsystem *subsys,
+			 struct config_item *target)
+{
+	int ret;
+	struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;
+	struct config_item *s_item = &subsys->su_group.cg_item;
+
+	/*
+	 * Pin the configfs filesystem.  This means we can safely access
+	 * the root of the configfs filesystem.
+	 */
+	ret = configfs_pin_fs();
+	if (ret)
+		return ret;
+
+	/*
+	 * Next, lock the root directory.  We're going to check that the
+	 * subsystem is really registered, and so we need to lock out
+	 * configfs_[un]register_subsystem().
+	 */
+	mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
+
+	root_sd = configfs_sb->s_root->d_fsdata;
+
+	list_for_each_entry(p, &root_sd->s_children, s_sibling) {
+		if (p->s_type & CONFIGFS_DIR) {
+			if (p->s_element == s_item) {
+				subsys_sd = p;
+				break;
+			}
+		}
+	}
+
+	if (!subsys_sd) {
+		ret = -ENOENT;
+		goto out_unlock_fs;
+	}
+
+	/* Ok, now we can trust subsys/s_item */
+
+	/* Scan the tree, locking i_mutex recursively, return 0 if found */
+	ret = configfs_depend_prep(subsys_sd->s_dentry, target);
+	if (ret)
+		goto out_unlock_fs;
+
+	/* We hold all i_mutexes from the subsystem down to the target */
+	p = target->ci_dentry->d_fsdata;
+	p->s_dependent_count += 1;
+
+	configfs_depend_rollback(subsys_sd->s_dentry, target);
+
+out_unlock_fs:
+	mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
+
+	/*
+	 * If we succeeded, the fs is pinned via other methods.  If not,
+	 * we're done with it anyway.  So release_fs() is always right.
+	 */
+	configfs_release_fs();
+
+	return ret;
+}
+EXPORT_SYMBOL(configfs_depend_item);
+
+/*
+ * Release the dependent linkage.  This is much simpler than
+ * configfs_depend_item() because we know that that the client driver is
+ * pinned, thus the subsystem is pinned, and therefore configfs is pinned.
+ */
+void configfs_undepend_item(struct configfs_subsystem *subsys,
+			    struct config_item *target)
+{
+	struct configfs_dirent *sd;
+
+	/*
+	 * Since we can trust everything is pinned, we just need i_mutex
+	 * on the item.
+	 */
+	mutex_lock(&target->ci_dentry->d_inode->i_mutex);
+
+	sd = target->ci_dentry->d_fsdata;
+	BUG_ON(sd->s_dependent_count < 1);
+
+	sd->s_dependent_count -= 1;
+
+	/*
+	 * After this unlock, we cannot trust the item to stay alive!
+	 * DO NOT REFERENCE item after this unlock.
+	 */
+	mutex_unlock(&target->ci_dentry->d_inode->i_mutex);
+}
+EXPORT_SYMBOL(configfs_undepend_item);
 
 static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
@@ -783,7 +1042,7 @@
 
 	snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
 
-	down(&subsys->su_sem);
+	mutex_lock(&subsys->su_mutex);
 	group = NULL;
 	item = NULL;
 	if (type->ct_group_ops->make_group) {
@@ -797,7 +1056,7 @@
 		if (item)
 			link_obj(parent_item, item);
 	}
-	up(&subsys->su_sem);
+	mutex_unlock(&subsys->su_mutex);
 
 	kfree(name);
 	if (!item) {
@@ -841,13 +1100,16 @@
 out_unlink:
 	if (ret) {
 		/* Tear down everything we built up */
-		down(&subsys->su_sem);
+		mutex_lock(&subsys->su_mutex);
+
+		client_disconnect_notify(parent_item, item);
 		if (group)
 			unlink_group(group);
 		else
 			unlink_obj(item);
 		client_drop_item(parent_item, item);
-		up(&subsys->su_sem);
+
+		mutex_unlock(&subsys->su_mutex);
 
 		if (module_got)
 			module_put(owner);
@@ -881,6 +1143,13 @@
 	if (sd->s_type & CONFIGFS_USET_DEFAULT)
 		return -EPERM;
 
+	/*
+	 * Here's where we check for dependents.  We're protected by
+	 * i_mutex.
+	 */
+	if (sd->s_dependent_count)
+		return -EBUSY;
+
 	/* Get a working ref until we have the child */
 	parent_item = configfs_get_config_item(dentry->d_parent);
 	subsys = to_config_group(parent_item)->cg_subsys;
@@ -910,17 +1179,19 @@
 	if (sd->s_type & CONFIGFS_USET_DIR) {
 		configfs_detach_group(item);
 
-		down(&subsys->su_sem);
+		mutex_lock(&subsys->su_mutex);
+		client_disconnect_notify(parent_item, item);
 		unlink_group(to_config_group(item));
 	} else {
 		configfs_detach_item(item);
 
-		down(&subsys->su_sem);
+		mutex_lock(&subsys->su_mutex);
+		client_disconnect_notify(parent_item, item);
 		unlink_obj(item);
 	}
 
 	client_drop_item(parent_item, item);
-	up(&subsys->su_sem);
+	mutex_unlock(&subsys->su_mutex);
 
 	/* Drop our reference from above */
 	config_item_put(item);
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index 3527c7c..a3658f9 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -27,19 +27,26 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
-#include <asm/semaphore.h>
 
 #include <linux/configfs.h>
 #include "configfs_internal.h"
 
+/*
+ * A simple attribute can only be 4096 characters.  Why 4k?  Because the
+ * original code limited it to PAGE_SIZE.  That's a bad idea, though,
+ * because an attribute of 16k on ia64 won't work on x86.  So we limit to
+ * 4k, our minimum common page size.
+ */
+#define SIMPLE_ATTR_SIZE 4096
 
 struct configfs_buffer {
 	size_t			count;
 	loff_t			pos;
 	char			* page;
 	struct configfs_item_operations	* ops;
-	struct semaphore	sem;
+	struct mutex		mutex;
 	int			needs_read_fill;
 };
 
@@ -69,7 +76,7 @@
 
 	count = ops->show_attribute(item,attr,buffer->page);
 	buffer->needs_read_fill = 0;
-	BUG_ON(count > (ssize_t)PAGE_SIZE);
+	BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
 	if (count >= 0)
 		buffer->count = count;
 	else
@@ -102,7 +109,7 @@
 	struct configfs_buffer * buffer = file->private_data;
 	ssize_t retval = 0;
 
-	down(&buffer->sem);
+	mutex_lock(&buffer->mutex);
 	if (buffer->needs_read_fill) {
 		if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
 			goto out;
@@ -112,7 +119,7 @@
 	retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
 					 buffer->count);
 out:
-	up(&buffer->sem);
+	mutex_unlock(&buffer->mutex);
 	return retval;
 }
 
@@ -137,8 +144,8 @@
 	if (!buffer->page)
 		return -ENOMEM;
 
-	if (count >= PAGE_SIZE)
-		count = PAGE_SIZE - 1;
+	if (count >= SIMPLE_ATTR_SIZE)
+		count = SIMPLE_ATTR_SIZE - 1;
 	error = copy_from_user(buffer->page,buf,count);
 	buffer->needs_read_fill = 1;
 	/* if buf is assumed to contain a string, terminate it by \0,
@@ -193,13 +200,13 @@
 	struct configfs_buffer * buffer = file->private_data;
 	ssize_t len;
 
-	down(&buffer->sem);
+	mutex_lock(&buffer->mutex);
 	len = fill_write_buffer(buffer, buf, count);
 	if (len > 0)
 		len = flush_write_buffer(file->f_path.dentry, buffer, count);
 	if (len > 0)
 		*ppos += len;
-	up(&buffer->sem);
+	mutex_unlock(&buffer->mutex);
 	return len;
 }
 
@@ -253,7 +260,7 @@
 		error = -ENOMEM;
 		goto Enomem;
 	}
-	init_MUTEX(&buffer->sem);
+	mutex_init(&buffer->mutex);
 	buffer->needs_read_fill = 1;
 	buffer->ops = ops;
 	file->private_data = buffer;
@@ -292,6 +299,7 @@
 	if (buffer) {
 		if (buffer->page)
 			free_page((unsigned long)buffer->page);
+		mutex_destroy(&buffer->mutex);
 		kfree(buffer);
 	}
 	return 0;
diff --git a/fs/configfs/item.c b/fs/configfs/item.c
index 2442120..76dc4c3 100644
--- a/fs/configfs/item.c
+++ b/fs/configfs/item.c
@@ -62,7 +62,6 @@
  *	dynamically allocated string that @item->ci_name points to.
  *	Otherwise, use the static @item->ci_namebuf array.
  */
-
 int config_item_set_name(struct config_item * item, const char * fmt, ...)
 {
 	int error = 0;
@@ -139,12 +138,7 @@
 	return item;
 }
 
-/**
- *	config_item_cleanup - free config_item resources.
- *	@item:	item.
- */
-
-void config_item_cleanup(struct config_item * item)
+static void config_item_cleanup(struct config_item * item)
 {
 	struct config_item_type * t = item->ci_type;
 	struct config_group * s = item->ci_group;
@@ -179,39 +173,35 @@
 		kref_put(&item->ci_kref, config_item_release);
 }
 
-
 /**
  *	config_group_init - initialize a group for use
  *	@k:	group
  */
-
 void config_group_init(struct config_group *group)
 {
 	config_item_init(&group->cg_item);
 	INIT_LIST_HEAD(&group->cg_children);
 }
 
-
 /**
- *	config_group_find_obj - search for item in group.
+ *	config_group_find_item - search for item in group.
  *	@group:	group we're looking in.
  *	@name:	item's name.
  *
- *	Lock group via @group->cg_subsys, and iterate over @group->cg_list,
- *	looking for a matching config_item. If matching item is found
- *	take a reference and return the item.
+ *	Iterate over @group->cg_list, looking for a matching config_item.
+ *	If matching item is found take a reference and return the item.
+ *	Caller must have locked group via @group->cg_subsys->su_mtx.
  */
-
-struct config_item * config_group_find_obj(struct config_group * group, const char * name)
+struct config_item *config_group_find_item(struct config_group *group,
+					   const char *name)
 {
 	struct list_head * entry;
 	struct config_item * ret = NULL;
 
-        /* XXX LOCKING! */
 	list_for_each(entry,&group->cg_children) {
 		struct config_item * item = to_item(entry);
 		if (config_item_name(item) &&
-                    !strcmp(config_item_name(item), name)) {
+		    !strcmp(config_item_name(item), name)) {
 			ret = config_item_get(item);
 			break;
 		}
@@ -219,9 +209,8 @@
 	return ret;
 }
 
-
 EXPORT_SYMBOL(config_item_init);
 EXPORT_SYMBOL(config_group_init);
 EXPORT_SYMBOL(config_item_get);
 EXPORT_SYMBOL(config_item_put);
-EXPORT_SYMBOL(config_group_find_obj);
+EXPORT_SYMBOL(config_group_find_item);
diff --git a/fs/dcache.c b/fs/dcache.c
index 0e73aa0..cb9d050 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -883,6 +883,11 @@
 	return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
 
+static struct shrinker dcache_shrinker = {
+	.shrink = shrink_dcache_memory,
+	.seeks = DEFAULT_SEEKS,
+};
+
 /**
  * d_alloc	-	allocate a dcache entry
  * @parent: parent of entry to allocate
@@ -2115,7 +2120,7 @@
 	dentry_cache = KMEM_CACHE(dentry,
 		SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
 	
-	set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
+	register_shrinker(&dcache_shrinker);
 
 	/* Hash may have been set up in dcache_init_early */
 	if (!hashdist)
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 5069b2c..2f8e3c8 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -133,14 +133,6 @@
 	return len;
 }
 
-#define __CONFIGFS_ATTR(_name,_mode,_read,_write) {                           \
-	.attr   = { .ca_name = __stringify(_name),                            \
-		    .ca_mode = _mode,                                         \
-		    .ca_owner = THIS_MODULE },                                \
-	.show   = _read,                                                      \
-	.store  = _write,                                                     \
-}
-
 #define CLUSTER_ATTR(name, check_zero)                                        \
 static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len)  \
 {                                                                             \
@@ -615,7 +607,7 @@
 int dlm_config_init(void)
 {
 	config_group_init(&clusters_root.subsys.su_group);
-	init_MUTEX(&clusters_root.subsys.su_sem);
+	mutex_init(&clusters_root.subsys.su_mutex);
 	return configfs_register_subsystem(&clusters_root.subsys);
 }
 
@@ -759,9 +751,9 @@
 	if (!space_list)
 		return NULL;
 
-	down(&space_list->cg_subsys->su_sem);
-	i = config_group_find_obj(space_list, name);
-	up(&space_list->cg_subsys->su_sem);
+	mutex_lock(&space_list->cg_subsys->su_mutex);
+	i = config_group_find_item(space_list, name);
+	mutex_unlock(&space_list->cg_subsys->su_mutex);
 
 	return to_space(i);
 }
@@ -780,7 +772,7 @@
 	if (!comm_list)
 		return NULL;
 
-	down(&clusters_root.subsys.su_sem);
+	mutex_lock(&clusters_root.subsys.su_mutex);
 
 	list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
 		cm = to_comm(i);
@@ -800,7 +792,7 @@
 			break;
 		}
 	}
-	up(&clusters_root.subsys.su_sem);
+	mutex_unlock(&clusters_root.subsys.su_mutex);
 
 	if (!found)
 		cm = NULL;
diff --git a/fs/dquot.c b/fs/dquot.c
index 8819d28..7e27315 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -538,6 +538,11 @@
 	return (dqstats.free_dquots / 100) * sysctl_vfs_cache_pressure;
 }
 
+static struct shrinker dqcache_shrinker = {
+	.shrink = shrink_dqcache_memory,
+	.seeks = DEFAULT_SEEKS,
+};
+
 /*
  * Put reference to dquot
  * NOTE: If you change this function please check whether dqput_blocks() works right...
@@ -1870,7 +1875,7 @@
 	printk("Dquot-cache hash table entries: %ld (order %ld, %ld bytes)\n",
 			nr_hash, order, (PAGE_SIZE << order));
 
-	set_shrinker(DEFAULT_SEEKS, shrink_dqcache_memory);
+	register_shrinker(&dqcache_shrinker);
 
 	return 0;
 }
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 03ea769..59375ef 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -20,7 +20,7 @@
 	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
 		if (inode->i_state & (I_FREEING|I_WILL_FREE))
 			continue;
-		invalidate_mapping_pages(inode->i_mapping, 0, -1);
+		__invalidate_mapping_pages(inode->i_mapping, 0, -1, true);
 	}
 	spin_unlock(&inode_lock);
 }
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 83e94fe..e77a2ec 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -282,7 +282,7 @@
 	struct dentry *lower_dentry;
 	struct vfsmount *lower_mnt;
 	char *encoded_name;
-	unsigned int encoded_namelen;
+	int encoded_namelen;
 	struct ecryptfs_crypt_stat *crypt_stat = NULL;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
 	char *page_virt = NULL;
@@ -473,7 +473,7 @@
 	struct dentry *lower_dir_dentry;
 	umode_t mode;
 	char *encoded_symname;
-	unsigned int encoded_symlen;
+	int encoded_symlen;
 	struct ecryptfs_crypt_stat *crypt_stat = NULL;
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
index ed4a207..5276b19 100644
--- a/fs/efs/namei.c
+++ b/fs/efs/namei.c
@@ -75,6 +75,38 @@
 	return NULL;
 }
 
+struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *efs_get_parent(struct dentry *child)
 {
 	struct dentry *parent;
diff --git a/fs/efs/super.c b/fs/efs/super.c
index e0a6839..d360c81 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -11,6 +11,7 @@
 #include <linux/efs_fs.h>
 #include <linux/efs_vh.h>
 #include <linux/efs_fs_sb.h>
+#include <linux/exportfs.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
@@ -113,6 +114,7 @@
 };
 
 static struct export_operations efs_export_ops = {
+	.get_dentry	= efs_get_dentry,
 	.get_parent	= efs_get_parent,
 };
 
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index e98f6cd..8adb32a 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -1,15 +1,45 @@
 
+#include <linux/exportfs.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/module.h>
+#include <linux/mount.h>
 #include <linux/namei.h>
 
-struct export_operations export_op_default;
-
-#define	CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-
 #define dprintk(fmt, args...) do{}while(0)
 
+
+static int get_name(struct dentry *dentry, char *name,
+		struct dentry *child);
+
+
+static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj)
+{
+	struct dentry *result = ERR_PTR(-ESTALE);
+
+	if (sb->s_export_op->get_dentry) {
+		result = sb->s_export_op->get_dentry(sb, obj);
+		if (!result)
+			result = ERR_PTR(-ESTALE);
+	}
+
+	return result;
+}
+
+static int exportfs_get_name(struct dentry *dir, char *name,
+		struct dentry *child)
+{
+	struct export_operations *nop = dir->d_sb->s_export_op;
+
+	if (nop->get_name)
+		return nop->get_name(dir, name, child);
+	else
+		return get_name(dir, name, child);
+}
+
+/*
+ * Check if the dentry or any of it's aliases is acceptable.
+ */
 static struct dentry *
 find_acceptable_alias(struct dentry *result,
 		int (*acceptable)(void *context, struct dentry *dentry),
@@ -17,6 +47,9 @@
 {
 	struct dentry *dentry, *toput = NULL;
 
+	if (acceptable(context, result))
+		return result;
+
 	spin_lock(&dcache_lock);
 	list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
 		dget_locked(dentry);
@@ -37,6 +70,150 @@
 	return NULL;
 }
 
+/*
+ * Find root of a disconnected subtree and return a reference to it.
+ */
+static struct dentry *
+find_disconnected_root(struct dentry *dentry)
+{
+	dget(dentry);
+	spin_lock(&dentry->d_lock);
+	while (!IS_ROOT(dentry) &&
+	       (dentry->d_parent->d_flags & DCACHE_DISCONNECTED)) {
+		struct dentry *parent = dentry->d_parent;
+		dget(parent);
+		spin_unlock(&dentry->d_lock);
+		dput(dentry);
+		dentry = parent;
+		spin_lock(&dentry->d_lock);
+	}
+	spin_unlock(&dentry->d_lock);
+	return dentry;
+}
+
+
+/*
+ * Make sure target_dir is fully connected to the dentry tree.
+ *
+ * It may already be, as the flag isn't always updated when connection happens.
+ */
+static int
+reconnect_path(struct super_block *sb, struct dentry *target_dir)
+{
+	char nbuf[NAME_MAX+1];
+	int noprogress = 0;
+	int err = -ESTALE;
+
+	/*
+	 * It is possible that a confused file system might not let us complete
+	 * the path to the root.  For example, if get_parent returns a directory
+	 * in which we cannot find a name for the child.  While this implies a
+	 * very sick filesystem we don't want it to cause knfsd to spin.  Hence
+	 * the noprogress counter.  If we go through the loop 10 times (2 is
+	 * probably enough) without getting anywhere, we just give up
+	 */
+	while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
+		struct dentry *pd = find_disconnected_root(target_dir);
+
+		if (!IS_ROOT(pd)) {
+			/* must have found a connected parent - great */
+			spin_lock(&pd->d_lock);
+			pd->d_flags &= ~DCACHE_DISCONNECTED;
+			spin_unlock(&pd->d_lock);
+			noprogress = 0;
+		} else if (pd == sb->s_root) {
+			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
+			spin_lock(&pd->d_lock);
+			pd->d_flags &= ~DCACHE_DISCONNECTED;
+			spin_unlock(&pd->d_lock);
+			noprogress = 0;
+		} else {
+			/*
+			 * We have hit the top of a disconnected path, try to
+			 * find parent and connect.
+			 *
+			 * Racing with some other process renaming a directory
+			 * isn't much of a problem here.  If someone renames
+			 * the directory, it will end up properly connected,
+			 * which is what we want
+			 *
+			 * Getting the parent can't be supported generically,
+			 * the locking is too icky.
+			 *
+			 * Instead we just return EACCES.  If server reboots
+			 * or inodes get flushed, you lose
+			 */
+			struct dentry *ppd = ERR_PTR(-EACCES);
+			struct dentry *npd;
+
+			mutex_lock(&pd->d_inode->i_mutex);
+			if (sb->s_export_op->get_parent)
+				ppd = sb->s_export_op->get_parent(pd);
+			mutex_unlock(&pd->d_inode->i_mutex);
+
+			if (IS_ERR(ppd)) {
+				err = PTR_ERR(ppd);
+				dprintk("%s: get_parent of %ld failed, err %d\n",
+					__FUNCTION__, pd->d_inode->i_ino, err);
+				dput(pd);
+				break;
+			}
+
+			dprintk("%s: find name of %lu in %lu\n", __FUNCTION__,
+				pd->d_inode->i_ino, ppd->d_inode->i_ino);
+			err = exportfs_get_name(ppd, nbuf, pd);
+			if (err) {
+				dput(ppd);
+				dput(pd);
+				if (err == -ENOENT)
+					/* some race between get_parent and
+					 * get_name?  just try again
+					 */
+					continue;
+				break;
+			}
+			dprintk("%s: found name: %s\n", __FUNCTION__, nbuf);
+			mutex_lock(&ppd->d_inode->i_mutex);
+			npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
+			mutex_unlock(&ppd->d_inode->i_mutex);
+			if (IS_ERR(npd)) {
+				err = PTR_ERR(npd);
+				dprintk("%s: lookup failed: %d\n",
+					__FUNCTION__, err);
+				dput(ppd);
+				dput(pd);
+				break;
+			}
+			/* we didn't really want npd, we really wanted
+			 * a side-effect of the lookup.
+			 * hopefully, npd == pd, though it isn't really
+			 * a problem if it isn't
+			 */
+			if (npd == pd)
+				noprogress = 0;
+			else
+				printk("%s: npd != pd\n", __FUNCTION__);
+			dput(npd);
+			dput(ppd);
+			if (IS_ROOT(pd)) {
+				/* something went wrong, we have to give up */
+				dput(pd);
+				break;
+			}
+		}
+		dput(pd);
+	}
+
+	if (target_dir->d_flags & DCACHE_DISCONNECTED) {
+		/* something went wrong - oh-well */
+		if (!err)
+			err = -ESTALE;
+		return err;
+	}
+
+	return 0;
+}
+
 /**
  * find_exported_dentry - helper routine to implement export_operations->decode_fh
  * @sb:		The &super_block identifying the filesystem
@@ -74,184 +251,58 @@
 		     int (*acceptable)(void *context, struct dentry *de),
 		     void *context)
 {
-	struct dentry *result = NULL;
-	struct dentry *target_dir;
-	int err;
-	struct export_operations *nops = sb->s_export_op;
-	struct dentry *alias;
-	int noprogress;
-	char nbuf[NAME_MAX+1];
+	struct dentry *result, *alias;
+	int err = -ESTALE;
 
 	/*
 	 * Attempt to find the inode.
 	 */
-	result = CALL(sb->s_export_op,get_dentry)(sb,obj);
-	err = -ESTALE;
-	if (result == NULL)
-		goto err_out;
-	if (IS_ERR(result)) {
-		err = PTR_ERR(result);
-		goto err_out;
-	}
-	if (S_ISDIR(result->d_inode->i_mode) &&
-	    (result->d_flags & DCACHE_DISCONNECTED)) {
-		/* it is an unconnected directory, we must connect it */
-		;
-	} else {
-		if (acceptable(context, result))
-			return result;
-		if (S_ISDIR(result->d_inode->i_mode)) {
+	result = exportfs_get_dentry(sb, obj);
+	if (IS_ERR(result))
+		return result;
+
+	if (S_ISDIR(result->d_inode->i_mode)) {
+		if (!(result->d_flags & DCACHE_DISCONNECTED)) {
+			if (acceptable(context, result))
+				return result;
 			err = -EACCES;
 			goto err_result;
 		}
 
+		err = reconnect_path(sb, result);
+		if (err)
+			goto err_result;
+	} else {
+		struct dentry *target_dir, *nresult;
+		char nbuf[NAME_MAX+1];
+
 		alias = find_acceptable_alias(result, acceptable, context);
 		if (alias)
 			return alias;
-	}			
 
-	/* It's a directory, or we are required to confirm the file's
-	 * location in the tree based on the parent information
- 	 */
-	dprintk("find_exported_dentry: need to look harder for %s/%d\n",sb->s_id,*(int*)obj);
-	if (S_ISDIR(result->d_inode->i_mode))
-		target_dir = dget(result);
-	else {
 		if (parent == NULL)
 			goto err_result;
 
-		target_dir = CALL(sb->s_export_op,get_dentry)(sb,parent);
-		if (IS_ERR(target_dir))
+		target_dir = exportfs_get_dentry(sb,parent);
+		if (IS_ERR(target_dir)) {
 			err = PTR_ERR(target_dir);
-		if (target_dir == NULL || IS_ERR(target_dir))
 			goto err_result;
-	}
-	/*
-	 * Now we need to make sure that target_dir is properly connected.
-	 * It may already be, as the flag isn't always updated when connection
-	 * happens.
-	 * So, we walk up parent links until we find a connected directory,
-	 * or we run out of directories.  Then we find the parent, find
-	 * the name of the child in that parent, and do a lookup.
-	 * This should connect the child into the parent
-	 * We then repeat.
-	 */
-
-	/* it is possible that a confused file system might not let us complete 
-	 * the path to the root.  For example, if get_parent returns a directory
-	 * in which we cannot find a name for the child.  While this implies a
-	 * very sick filesystem we don't want it to cause knfsd to spin.  Hence
-	 * the noprogress counter.  If we go through the loop 10 times (2 is
-	 * probably enough) without getting anywhere, we just give up
-	 */
-	noprogress= 0;
-	while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
-		struct dentry *pd = target_dir;
-
-		dget(pd);
-		spin_lock(&pd->d_lock);
-		while (!IS_ROOT(pd) &&
-				(pd->d_parent->d_flags&DCACHE_DISCONNECTED)) {
-			struct dentry *parent = pd->d_parent;
-
-			dget(parent);
-			spin_unlock(&pd->d_lock);
-			dput(pd);
-			pd = parent;
-			spin_lock(&pd->d_lock);
 		}
-		spin_unlock(&pd->d_lock);
 
-		if (!IS_ROOT(pd)) {
-			/* must have found a connected parent - great */
-			spin_lock(&pd->d_lock);
-			pd->d_flags &= ~DCACHE_DISCONNECTED;
-			spin_unlock(&pd->d_lock);
-			noprogress = 0;
-		} else if (pd == sb->s_root) {
-			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
-			spin_lock(&pd->d_lock);
-			pd->d_flags &= ~DCACHE_DISCONNECTED;
-			spin_unlock(&pd->d_lock);
-			noprogress = 0;
-		} else {
-			/* we have hit the top of a disconnected path.  Try
-			 * to find parent and connect
-			 * note: racing with some other process renaming a
-			 * directory isn't much of a problem here.  If someone
-			 * renames the directory, it will end up properly
-			 * connected, which is what we want
-			 */
-			struct dentry *ppd;
-			struct dentry *npd;
-
-			mutex_lock(&pd->d_inode->i_mutex);
-			ppd = CALL(nops,get_parent)(pd);
-			mutex_unlock(&pd->d_inode->i_mutex);
-
-			if (IS_ERR(ppd)) {
-				err = PTR_ERR(ppd);
-				dprintk("find_exported_dentry: get_parent of %ld failed, err %d\n",
-					pd->d_inode->i_ino, err);
-				dput(pd);
-				break;
-			}
-			dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino);
-			err = CALL(nops,get_name)(ppd, nbuf, pd);
-			if (err) {
-				dput(ppd);
-				dput(pd);
-				if (err == -ENOENT)
-					/* some race between get_parent and
-					 * get_name?  just try again
-					 */
-					continue;
-				break;
-			}
-			dprintk("find_exported_dentry: found name: %s\n", nbuf);
-			mutex_lock(&ppd->d_inode->i_mutex);
-			npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
-			mutex_unlock(&ppd->d_inode->i_mutex);
-			if (IS_ERR(npd)) {
-				err = PTR_ERR(npd);
-				dprintk("find_exported_dentry: lookup failed: %d\n", err);
-				dput(ppd);
-				dput(pd);
-				break;
-			}
-			/* we didn't really want npd, we really wanted
-			 * a side-effect of the lookup.
-			 * hopefully, npd == pd, though it isn't really
-			 * a problem if it isn't
-			 */
-			if (npd == pd)
-				noprogress = 0;
-			else
-				printk("find_exported_dentry: npd != pd\n");
-			dput(npd);
-			dput(ppd);
-			if (IS_ROOT(pd)) {
-				/* something went wrong, we have to give up */
-				dput(pd);
-				break;
-			}
+		err = reconnect_path(sb, target_dir);
+		if (err) {
+			dput(target_dir);
+			goto err_result;
 		}
-		dput(pd);
-	}
 
-	if (target_dir->d_flags & DCACHE_DISCONNECTED) {
-		/* something went wrong - oh-well */
-		if (!err)
-			err = -ESTALE;
-		goto err_target;
-	}
-	/* if we weren't after a directory, have one more step to go */
-	if (result != target_dir) {
-		struct dentry *nresult;
-		err = CALL(nops,get_name)(target_dir, nbuf, result);
+		/*
+		 * As we weren't after a directory, have one more step to go.
+		 */
+		err = exportfs_get_name(target_dir, nbuf, result);
 		if (!err) {
 			mutex_lock(&target_dir->d_inode->i_mutex);
-			nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
+			nresult = lookup_one_len(nbuf, target_dir,
+						 strlen(nbuf));
 			mutex_unlock(&target_dir->d_inode->i_mutex);
 			if (!IS_ERR(nresult)) {
 				if (nresult->d_inode) {
@@ -261,11 +312,8 @@
 					dput(nresult);
 			}
 		}
+		dput(target_dir);
 	}
-	dput(target_dir);
-	/* now result is properly connected, it is our best bet */
-	if (acceptable(context, result))
-		return result;
 
 	alias = find_acceptable_alias(result, acceptable, context);
 	if (alias)
@@ -275,32 +323,16 @@
 	dput(result);
 	/* It might be justifiable to return ESTALE here,
 	 * but the filehandle at-least looks reasonable good
-	 * and it just be a permission problem, so returning
+	 * and it may just be a permission problem, so returning
 	 * -EACCESS is safer
 	 */
 	return ERR_PTR(-EACCES);
 
- err_target:
-	dput(target_dir);
  err_result:
 	dput(result);
- err_out:
 	return ERR_PTR(err);
 }
 
-
-
-static struct dentry *get_parent(struct dentry *child)
-{
-	/* get_parent cannot be supported generically, the locking
-	 * is too icky.
-	 * instead, we just return EACCES.  If server reboots or inodes
-	 * get flushed, you lose
-	 */
-	return ERR_PTR(-EACCES);
-}
-
-
 struct getdents_callback {
 	char *name;		/* name that was found. It already points to a
 				   buffer NAME_MAX+1 is size */
@@ -390,61 +422,6 @@
 	return error;
 }
 
-
-static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
-{
-
-	/* iget isn't really right if the inode is currently unallocated!!
-	 * This should really all be done inside each filesystem
-	 *
-	 * ext2fs' read_inode has been strengthed to return a bad_inode if
-	 * the inode had been deleted.
-	 *
-	 * Currently we don't know the generation for parent directory, so
-	 * a generation of 0 means "accept any"
-	 */
-	struct inode *inode;
-	struct dentry *result;
-	if (ino == 0)
-		return ERR_PTR(-ESTALE);
-	inode = iget(sb, ino);
-	if (inode == NULL)
-		return ERR_PTR(-ENOMEM);
-	if (is_bad_inode(inode)
-	    || (generation && inode->i_generation != generation)
-		) {
-		/* we didn't find the right inode.. */
-		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
-			inode->i_ino,
-			inode->i_nlink, atomic_read(&inode->i_count),
-			inode->i_generation,
-			generation);
-
-		iput(inode);
-		return ERR_PTR(-ESTALE);
-	}
-	/* now to find a dentry.
-	 * If possible, get a well-connected one
-	 */
-	result = d_alloc_anon(inode);
-	if (!result) {
-		iput(inode);
-		return ERR_PTR(-ENOMEM);
-	}
-	return result;
-}
-
-
-static struct dentry *get_object(struct super_block *sb, void *vobjp)
-{
-	__u32 *objp = vobjp;
-	unsigned long ino = objp[0];
-	__u32 generation = objp[1];
-
-	return export_iget(sb, ino, generation);
-}
-
-
 /**
  * export_encode_fh - default export_operations->encode_fh function
  * @dentry:  the dentry to encode
@@ -517,16 +494,40 @@
 				   acceptable, context);
 }
 
-struct export_operations export_op_default = {
-	.decode_fh	= export_decode_fh,
-	.encode_fh	= export_encode_fh,
+int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+		int connectable)
+{
+ 	struct export_operations *nop = dentry->d_sb->s_export_op;
+	int error;
 
-	.get_name	= get_name,
-	.get_parent	= get_parent,
-	.get_dentry	= get_object,
-};
+	if (nop->encode_fh)
+		error = nop->encode_fh(dentry, fh, max_len, connectable);
+	else
+		error = export_encode_fh(dentry, fh, max_len, connectable);
 
-EXPORT_SYMBOL(export_op_default);
+	return error;
+}
+EXPORT_SYMBOL_GPL(exportfs_encode_fh);
+
+struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len,
+		int fileid_type, int (*acceptable)(void *, struct dentry *),
+		void *context)
+{
+	struct export_operations *nop = mnt->mnt_sb->s_export_op;
+	struct dentry *result;
+
+	if (nop->decode_fh) {
+		result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
+			acceptable, context);
+	} else {
+		result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
+			acceptable, context);
+	}
+
+	return result;
+}
+EXPORT_SYMBOL_GPL(exportfs_decode_fh);
+
 EXPORT_SYMBOL(find_exported_dentry);
 
 MODULE_LICENSE("GPL");
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 04afeec..ab79612 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -24,9 +24,9 @@
 #include "acl.h"
 
 /*
- * Called when an inode is released. Note that this is different
- * from ext2_open_file: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
+ * Called when filp is released. This happens when all file descriptors
+ * for a single struct file are closed. Note that different open() calls
+ * for the same file yield different struct file structures.
  */
 static int ext2_release_file (struct inode * inode, struct file * filp)
 {
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 5de5061..3eefa97 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -25,6 +25,7 @@
 #include <linux/parser.h>
 #include <linux/random.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/seq_file.h>
@@ -1099,15 +1100,18 @@
 	struct super_block *sb = dentry->d_sb;
 	struct ext2_sb_info *sbi = EXT2_SB(sb);
 	struct ext2_super_block *es = sbi->s_es;
-	unsigned long overhead;
-	int i;
 	u64 fsid;
 
 	if (test_opt (sb, MINIX_DF))
-		overhead = 0;
-	else {
+		sbi->s_overhead_last = 0;
+	else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+		unsigned long i, overhead = 0;
+		smp_rmb();
+
 		/*
-		 * Compute the overhead (FS structures)
+		 * Compute the overhead (FS structures). This is constant
+		 * for a given filesystem unless the number of block groups
+		 * changes so we cache the previous value until it does.
 		 */
 
 		/*
@@ -1131,17 +1135,22 @@
 		 */
 		overhead += (sbi->s_groups_count *
 			     (2 + sbi->s_itb_per_group));
+		sbi->s_overhead_last = overhead;
+		smp_wmb();
+		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
 	}
 
 	buf->f_type = EXT2_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
 	buf->f_bfree = ext2_count_free_blocks(sb);
+	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
 	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = ext2_count_free_inodes(sb);
+	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT2_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 2a85dde..de4e316 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -3195,7 +3195,7 @@
 	 */
 
 	journal = EXT3_JOURNAL(inode);
-	if (is_journal_aborted(journal) || IS_RDONLY(inode))
+	if (is_journal_aborted(journal))
 		return -EROFS;
 
 	journal_lock_updates(journal);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 9bb046d..1586807 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1019,6 +1019,11 @@
 
 		if (!inode)
 			return ERR_PTR(-EACCES);
+
+		if (is_bad_inode(inode)) {
+			iput(inode);
+			return ERR_PTR(-ENOENT);
+		}
 	}
 	return d_splice_alias(inode, dentry);
 }
@@ -1054,6 +1059,11 @@
 	if (!inode)
 		return ERR_PTR(-EACCES);
 
+	if (is_bad_inode(inode)) {
+		iput(inode);
+		return ERR_PTR(-ENOENT);
+	}
+
 	parent = d_alloc_anon(inode);
 	if (!parent) {
 		iput(inode);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 6e30629..4f84dc8 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -29,12 +29,14 @@
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
+#include <linux/log2.h>
 
 #include <asm/uaccess.h>
 
@@ -459,6 +461,14 @@
 
 static void ext3_destroy_inode(struct inode *inode)
 {
+	if (!list_empty(&(EXT3_I(inode)->i_orphan))) {
+		printk("EXT3 Inode %p: orphan list check failed!\n",
+			EXT3_I(inode));
+		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+				EXT3_I(inode), sizeof(struct ext3_inode_info),
+				false);
+		dump_stack();
+	}
 	kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
 }
 
@@ -1566,7 +1576,7 @@
 		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
 		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
 		if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
-		    (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
+		    (!is_power_of_2(sbi->s_inode_size)) ||
 		    (sbi->s_inode_size > blocksize)) {
 			printk (KERN_ERR
 				"EXT3-fs: unsupported inode size: %d\n",
@@ -2075,6 +2085,7 @@
 			       unsigned int journal_inum)
 {
 	journal_t *journal;
+	int err;
 
 	if (sb->s_flags & MS_RDONLY) {
 		printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to "
@@ -2082,13 +2093,15 @@
 		return -EROFS;
 	}
 
-	if (!(journal = ext3_get_journal(sb, journal_inum)))
+	journal = ext3_get_journal(sb, journal_inum);
+	if (!journal)
 		return -EINVAL;
 
 	printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",
 	       journal_inum);
 
-	if (journal_create(journal)) {
+	err = journal_create(journal);
+	if (err) {
 		printk(KERN_ERR "EXT3-fs: error creating journal.\n");
 		journal_destroy(journal);
 		return -EIO;
@@ -2139,12 +2152,14 @@
 
 	journal_lock_updates(journal);
 	journal_flush(journal);
+	lock_super(sb);
 	if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
 	    sb->s_flags & MS_RDONLY) {
 		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
 		sb->s_dirt = 0;
 		ext3_commit_super(sb, es, 1);
 	}
+	unlock_super(sb);
 	journal_unlock_updates(journal);
 }
 
@@ -2333,7 +2348,13 @@
 			    (sbi->s_mount_state & EXT3_VALID_FS))
 				es->s_state = cpu_to_le16(sbi->s_mount_state);
 
+			/*
+			 * We have to unlock super so that we can wait for
+			 * transactions.
+			 */
+			unlock_super(sb);
 			ext3_mark_recovery_complete(sb, es);
+			lock_super(sb);
 		} else {
 			__le32 ret;
 			if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
@@ -2406,19 +2427,19 @@
 	struct super_block *sb = dentry->d_sb;
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	struct ext3_super_block *es = sbi->s_es;
-	ext3_fsblk_t overhead;
-	int i;
 	u64 fsid;
 
-	if (test_opt (sb, MINIX_DF))
-		overhead = 0;
-	else {
-		unsigned long ngroups;
-		ngroups = EXT3_SB(sb)->s_groups_count;
+	if (test_opt(sb, MINIX_DF)) {
+		sbi->s_overhead_last = 0;
+	} else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+		unsigned long ngroups = sbi->s_groups_count, i;
+		ext3_fsblk_t overhead = 0;
 		smp_rmb();
 
 		/*
-		 * Compute the overhead (FS structures)
+		 * Compute the overhead (FS structures).  This is constant
+		 * for a given filesystem unless the number of block groups
+		 * changes so we cache the previous value until it does.
 		 */
 
 		/*
@@ -2442,18 +2463,23 @@
 		 * Every block group has an inode bitmap, a block
 		 * bitmap, and an inode table.
 		 */
-		overhead += (ngroups * (2 + EXT3_SB(sb)->s_itb_per_group));
+		overhead += ngroups * (2 + sbi->s_itb_per_group);
+		sbi->s_overhead_last = overhead;
+		smp_wmb();
+		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
 	}
 
 	buf->f_type = EXT3_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
 	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
 	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT3_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 3b64bb1..9de54ae 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1585,7 +1585,7 @@
 	ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
 
 	if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
-	    in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+	    in_range(ext4_inode_bitmap(sb, gdp), ret_block, num) ||
 	    in_range(ret_block, ext4_inode_table(sb, gdp),
 		     EXT4_SB(sb)->s_itb_per_group) ||
 	    in_range(ret_block + num - 1, ext4_inode_table(sb, gdp),
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 2811e57..2de339d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1017,6 +1017,11 @@
 
 		if (!inode)
 			return ERR_PTR(-EACCES);
+
+		if (is_bad_inode(inode)) {
+			iput(inode);
+			return ERR_PTR(-ENOENT);
+		}
 	}
 	return d_splice_alias(inode, dentry);
 }
@@ -1052,6 +1057,11 @@
 	if (!inode)
 		return ERR_PTR(-EACCES);
 
+	if (is_bad_inode(inode)) {
+		iput(inode);
+		return ERR_PTR(-ENOENT);
+	}
+
 	parent = d_alloc_anon(inode);
 	if (!parent) {
 		iput(inode);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 175b68c..b806e68 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -29,6 +29,7 @@
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
 #include <linux/mount.h>
@@ -510,6 +511,14 @@
 
 static void ext4_destroy_inode(struct inode *inode)
 {
+	if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
+		printk("EXT4 Inode %p: orphan list check failed!\n",
+			EXT4_I(inode));
+		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+				EXT4_I(inode), sizeof(struct ext4_inode_info),
+				true);
+		dump_stack();
+	}
 	kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
@@ -2150,6 +2159,7 @@
 			       unsigned int journal_inum)
 {
 	journal_t *journal;
+	int err;
 
 	if (sb->s_flags & MS_RDONLY) {
 		printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to "
@@ -2157,13 +2167,15 @@
 		return -EROFS;
 	}
 
-	if (!(journal = ext4_get_journal(sb, journal_inum)))
+	journal = ext4_get_journal(sb, journal_inum);
+	if (!journal)
 		return -EINVAL;
 
 	printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n",
 	       journal_inum);
 
-	if (jbd2_journal_create(journal)) {
+	err = jbd2_journal_create(journal);
+	if (err) {
 		printk(KERN_ERR "EXT4-fs: error creating journal.\n");
 		jbd2_journal_destroy(journal);
 		return -EIO;
@@ -2214,12 +2226,14 @@
 
 	jbd2_journal_lock_updates(journal);
 	jbd2_journal_flush(journal);
+	lock_super(sb);
 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
 	    sb->s_flags & MS_RDONLY) {
 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
 		sb->s_dirt = 0;
 		ext4_commit_super(sb, es, 1);
 	}
+	unlock_super(sb);
 	jbd2_journal_unlock_updates(journal);
 }
 
@@ -2408,7 +2422,13 @@
 			    (sbi->s_mount_state & EXT4_VALID_FS))
 				es->s_state = cpu_to_le16(sbi->s_mount_state);
 
+			/*
+			 * We have to unlock super so that we can wait for
+			 * transactions.
+			 */
+			unlock_super(sb);
 			ext4_mark_recovery_complete(sb, es);
+			lock_super(sb);
 		} else {
 			__le32 ret;
 			if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -2481,19 +2501,19 @@
 	struct super_block *sb = dentry->d_sb;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct ext4_super_block *es = sbi->s_es;
-	ext4_fsblk_t overhead;
-	int i;
 	u64 fsid;
 
-	if (test_opt (sb, MINIX_DF))
-		overhead = 0;
-	else {
-		unsigned long ngroups;
-		ngroups = EXT4_SB(sb)->s_groups_count;
+	if (test_opt(sb, MINIX_DF)) {
+		sbi->s_overhead_last = 0;
+	} else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+		unsigned long ngroups = sbi->s_groups_count, i;
+		ext4_fsblk_t overhead = 0;
 		smp_rmb();
 
 		/*
-		 * Compute the overhead (FS structures)
+		 * Compute the overhead (FS structures).  This is constant
+		 * for a given filesystem unless the number of block groups
+		 * changes so we cache the previous value until it does.
 		 */
 
 		/*
@@ -2517,18 +2537,23 @@
 		 * Every block group has an inode bitmap, a block
 		 * bitmap, and an inode table.
 		 */
-		overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group));
+		overhead += ngroups * (2 + sbi->s_itb_per_group);
+		sbi->s_overhead_last = overhead;
+		smp_wmb();
+		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
 	}
 
 	buf->f_type = EXT4_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = ext4_blocks_count(es) - overhead;
+	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
 	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
 	if (buf->f_bfree < ext4_r_blocks_count(es))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT4_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index ccf161d..72cbcd6 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -313,7 +313,7 @@
 	wchar_t bufuname[14];
 	unsigned char xlate_len, nr_slots;
 	wchar_t *unicode = NULL;
-	unsigned char work[8], bufname[260];	/* 256 + 4 */
+	unsigned char work[MSDOS_NAME], bufname[260];	/* 256 + 4 */
 	int uni_xlate = sbi->options.unicode_xlate;
 	int utf8 = sbi->options.utf8;
 	int anycase = (sbi->options.name_check != 's');
@@ -351,7 +351,8 @@
 		if (work[0] == 0x05)
 			work[0] = 0xE5;
 		for (i = 0, j = 0, last_u = 0; i < 8;) {
-			if (!work[i]) break;
+			if (!work[i])
+				break;
 			chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
 						&bufuname[j++], opt_shortname,
 						de->lcase & CASE_LOWER_BASE);
@@ -365,13 +366,15 @@
 		}
 		j = last_u;
 		fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
-		for (i = 0; i < 3;) {
-			if (!de->ext[i]) break;
-			chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i,
+		for (i = 8; i < MSDOS_NAME;) {
+			if (!work[i])
+				break;
+			chl = fat_shortname2uni(nls_disk, &work[i],
+						MSDOS_NAME - i,
 						&bufuname[j++], opt_shortname,
 						de->lcase & CASE_LOWER_EXT);
 			if (chl <= 1) {
-				if (de->ext[i] != ' ')
+				if (work[i] != ' ')
 					last_u = j;
 			} else {
 				last_u = j;
@@ -445,7 +448,7 @@
 	int fill_len;
 	wchar_t bufuname[14];
 	wchar_t *unicode = NULL;
-	unsigned char c, work[8], bufname[56], *ptname = bufname;
+	unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname;
 	unsigned long lpos, dummy, *furrfu = &lpos;
 	int uni_xlate = sbi->options.unicode_xlate;
 	int isvfat = sbi->options.isvfat;
@@ -527,7 +530,8 @@
 	if (work[0] == 0x05)
 		work[0] = 0xE5;
 	for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) {
-		if (!(c = work[i])) break;
+		if (!(c = work[i]))
+			break;
 		chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
 					&bufuname[j++], opt_shortname,
 					de->lcase & CASE_LOWER_BASE);
@@ -549,9 +553,10 @@
 	j = last_u;
 	fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
 	ptname[i++] = '.';
-	for (i2 = 0; i2 < 3;) {
-		if (!(c = de->ext[i2])) break;
-		chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2,
+	for (i2 = 8; i2 < MSDOS_NAME;) {
+		if (!(c = work[i2]))
+			break;
+		chl = fat_shortname2uni(nls_disk, &work[i2], MSDOS_NAME - i2,
 					&bufuname[j++], opt_shortname,
 					de->lcase & CASE_LOWER_EXT);
 		if (chl <= 1) {
@@ -563,8 +568,8 @@
 			}
 		} else {
 			last_u = j;
-			for (chi = 0; chi < chl && i2 < 3; chi++) {
-				ptname[i++] = de->ext[i2++];
+			for (chi = 0; chi < chl && i2 < MSDOS_NAME; chi++) {
+				ptname[i++] = work[i2++];
 				last = i;
 			}
 		}
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index ab171ea..2c1b73f 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -17,6 +17,8 @@
 	int (*ent_next)(struct fat_entry *);
 };
 
+static DEFINE_SPINLOCK(fat12_entry_lock);
+
 static void fat12_ent_blocknr(struct super_block *sb, int entry,
 			      int *offset, sector_t *blocknr)
 {
@@ -116,10 +118,13 @@
 	u8 **ent12_p = fatent->u.ent12_p;
 	int next;
 
+	spin_lock(&fat12_entry_lock);
 	if (fatent->entry & 1)
 		next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
 	else
 		next = (*ent12_p[1] << 8) | *ent12_p[0];
+	spin_unlock(&fat12_entry_lock);
+
 	next &= 0x0fff;
 	if (next >= BAD_FAT12)
 		next = FAT_ENT_EOF;
@@ -151,6 +156,7 @@
 	if (new == FAT_ENT_EOF)
 		new = EOF_FAT12;
 
+	spin_lock(&fat12_entry_lock);
 	if (fatent->entry & 1) {
 		*ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
 		*ent12_p[1] = new >> 4;
@@ -158,6 +164,7 @@
 		*ent12_p[0] = new & 0xff;
 		*ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
 	}
+	spin_unlock(&fat12_entry_lock);
 
 	mark_buffer_dirty(fatent->bhs[0]);
 	if (fatent->nr_bhs == 2)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 479722d..0a7ddb3 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -20,6 +20,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/mount.h>
 #include <linux/vfs.h>
 #include <linux/parser.h>
@@ -354,8 +355,7 @@
 	} else { /* not a directory */
 		inode->i_generation |= 1;
 		inode->i_mode = MSDOS_MKMODE(de->attr,
-		    ((sbi->options.showexec &&
-			!is_exec(de->ext))
+		    ((sbi->options.showexec && !is_exec(de->name + 8))
 			? S_IRUGO|S_IWUGO : S_IRWXUGO)
 		    & ~sbi->options.fs_fmask) | S_IFREG;
 		MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index 8a4dfef..3c96d6e 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -80,7 +80,7 @@
  *	a d_name with size len.
  */
 #define VXFS_DIRPAD		4
-#define VXFS_NAMEMIN		((int)((struct vxfs_direct *)0)->d_name)
+#define VXFS_NAMEMIN		offsetof(struct vxfs_direct, d_name)
 #define VXFS_DIRROUND(len)	((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
 #define VXFS_DIRLEN(len)	(VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
 
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c
index c1f4400..1ab3e9d 100644
--- a/fs/gfs2/eaops.c
+++ b/fs/gfs2/eaops.c
@@ -11,6 +11,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
+#include <linux/capability.h>
 #include <linux/xattr.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/lm_interface.h>
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index 99ea565..b8312ed 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -11,6 +11,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/lm_interface.h>
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 90ebab7..050d29c 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -62,8 +62,10 @@
 		if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
 		    (head->key_type == HFSPLUS_KEY_BINARY))
 			tree->keycmp = hfsplus_cat_bin_cmp_key;
-		else
+		else {
 			tree->keycmp = hfsplus_cat_case_cmp_key;
+			HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD;
+		}
 	} else {
 		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
 		goto fail_page;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 80b5682..1955ee6 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -36,6 +36,8 @@
 	u16 type;
 
 	sb = dir->i_sb;
+
+	dentry->d_op = &hfsplus_dentry_operations;
 	dentry->d_fsdata = NULL;
 	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
 	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 3915635..d9f5eda 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -150,6 +150,7 @@
 #define HFSPLUS_SB_NODECOMPOSE	0x0002
 #define HFSPLUS_SB_FORCE	0x0004
 #define HFSPLUS_SB_HFSX		0x0008
+#define HFSPLUS_SB_CASEFOLD	0x0010
 
 
 struct hfsplus_inode_info {
@@ -321,6 +322,7 @@
 /* inode.c */
 extern const struct address_space_operations hfsplus_aops;
 extern const struct address_space_operations hfsplus_btree_aops;
+extern struct dentry_operations hfsplus_dentry_operations;
 
 void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
 void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
@@ -353,6 +355,8 @@
 int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
 int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
 int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
+int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str);
+int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2);
 
 /* wrapper.c */
 int hfsplus_read_wrapper(struct super_block *);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 409ce54..6f7c662 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -131,6 +131,11 @@
 	.writepages	= hfsplus_writepages,
 };
 
+struct dentry_operations hfsplus_dentry_operations = {
+	.d_hash       = hfsplus_hash_dentry,
+	.d_compare    = hfsplus_compare_dentry,
+};
+
 static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry,
 					  struct nameidata *nd)
 {
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index ebd1b38..6d87a2a 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -283,11 +283,10 @@
 	struct nls_table *nls = NULL;
 	int err = -EINVAL;
 
-	sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL);
+	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
 
-	memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
 	sb->s_fs_info = sbi;
 	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 	hfsplus_fill_defaults(sbi);
@@ -381,6 +380,7 @@
 		iput(root);
 		goto cleanup;
 	}
+	sb->s_root->d_op = &hfsplus_dentry_operations;
 
 	str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
 	str.name = HFSP_HIDDENDIR_NAME;
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 689c8bd..9e10f94 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -239,61 +239,201 @@
 	return res;
 }
 
-int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, const char *astr, int len)
+/*
+ * Convert one or more ASCII characters into a single unicode character.
+ * Returns the number of ASCII characters corresponding to the unicode char.
+ */
+static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
+			      wchar_t *uc)
 {
-	struct nls_table *nls = HFSPLUS_SB(sb).nls;
-	int size, off, decompose;
+	int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc);
+	if (size <= 0) {
+		*uc = '?';
+		size = 1;
+	}
+	switch (*uc) {
+	case 0x2400:
+		*uc = 0;
+		break;
+	case ':':
+		*uc = '/';
+		break;
+	}
+	return size;
+}
+
+/* Decomposes a single unicode character. */
+static inline u16 *decompose_unichar(wchar_t uc, int *size)
+{
+	int off;
+
+	off = hfsplus_decompose_table[(uc >> 12) & 0xf];
+	if (off == 0 || off == 0xffff)
+		return NULL;
+
+	off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)];
+	if (!off)
+		return NULL;
+
+	off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)];
+	if (!off)
+		return NULL;
+
+	off = hfsplus_decompose_table[off + (uc & 0xf)];
+	*size = off & 3;
+	if (*size == 0)
+		return NULL;
+	return hfsplus_decompose_table + (off / 4);
+}
+
+int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
+		    const char *astr, int len)
+{
+	int size, dsize, decompose;
+	u16 *dstr, outlen = 0;
 	wchar_t c;
-	u16 outlen = 0;
 
 	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
-
 	while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
-		size = nls->char2uni(astr, len, &c);
-		if (size <= 0) {
-			c = '?';
-			size = 1;
-		}
-		astr += size;
-		len -= size;
-		switch (c) {
-		case 0x2400:
-			c = 0;
-			break;
-		case ':':
-			c = '/';
-			break;
-		}
-		if (c >= 0xc0 && decompose) {
-			off = hfsplus_decompose_table[(c >> 12) & 0xf];
-			if (!off)
-				goto done;
-			if (off == 0xffff) {
-				goto done;
-			}
-			off = hfsplus_decompose_table[off + ((c >> 8) & 0xf)];
-			if (!off)
-				goto done;
-			off = hfsplus_decompose_table[off + ((c >> 4) & 0xf)];
-			if (!off)
-				goto done;
-			off = hfsplus_decompose_table[off + (c & 0xf)];
-			size = off & 3;
-			if (!size)
-				goto done;
-			off /= 4;
-			if (outlen + size > HFSPLUS_MAX_STRLEN)
+		size = asc2unichar(sb, astr, len, &c);
+
+		if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+			if (outlen + dsize > HFSPLUS_MAX_STRLEN)
 				break;
 			do {
-				ustr->unicode[outlen++] = cpu_to_be16(hfsplus_decompose_table[off++]);
-			} while (--size > 0);
-			continue;
-		}
-	done:
-		ustr->unicode[outlen++] = cpu_to_be16(c);
+				ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
+			} while (--dsize > 0);
+		} else
+			ustr->unicode[outlen++] = cpu_to_be16(c);
+
+		astr += size;
+		len -= size;
 	}
 	ustr->length = cpu_to_be16(outlen);
 	if (len > 0)
 		return -ENAMETOOLONG;
 	return 0;
 }
+
+/*
+ * Hash a string to an integer as appropriate for the HFS+ filesystem.
+ * Composed unicode characters are decomposed and case-folding is performed
+ * if the appropriate bits are (un)set on the superblock.
+ */
+int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str)
+{
+	struct super_block *sb = dentry->d_sb;
+	const char *astr;
+	const u16 *dstr;
+	int casefold, decompose, size, dsize, len;
+	unsigned long hash;
+	wchar_t c;
+	u16 c2;
+
+	casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
+	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	hash = init_name_hash();
+	astr = str->name;
+	len = str->len;
+	while (len > 0) {
+		size = asc2unichar(sb, astr, len, &c);
+		astr += size;
+		len -= size;
+
+		if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+			do {
+				c2 = *dstr++;
+				if (!casefold || (c2 = case_fold(c2)))
+					hash = partial_name_hash(c2, hash);
+			} while (--dsize > 0);
+		} else {
+			c2 = c;
+			if (!casefold || (c2 = case_fold(c2)))
+				hash = partial_name_hash(c2, hash);
+		}
+	}
+	str->hash = end_name_hash(hash);
+
+	return 0;
+}
+
+/*
+ * Compare strings with HFS+ filename ordering.
+ * Composed unicode characters are decomposed and case-folding is performed
+ * if the appropriate bits are (un)set on the superblock.
+ */
+int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2)
+{
+	struct super_block *sb = dentry->d_sb;
+	int casefold, decompose, size;
+	int dsize1, dsize2, len1, len2;
+	const u16 *dstr1, *dstr2;
+	const char *astr1, *astr2;
+	u16 c1, c2;
+	wchar_t c;
+
+	casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
+	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	astr1 = s1->name;
+	len1 = s1->len;
+	astr2 = s2->name;
+	len2 = s2->len;
+	dsize1 = dsize2 = 0;
+	dstr1 = dstr2 = NULL;
+
+	while (len1 > 0 && len2 > 0) {
+		if (!dsize1) {
+			size = asc2unichar(sb, astr1, len1, &c);
+			astr1 += size;
+			len1 -= size;
+
+			if (!decompose || !(dstr1 = decompose_unichar(c, &dsize1))) {
+				c1 = c;
+				dstr1 = &c1;
+				dsize1 = 1;
+			}
+		}
+
+		if (!dsize2) {
+			size = asc2unichar(sb, astr2, len2, &c);
+			astr2 += size;
+			len2 -= size;
+
+			if (!decompose || !(dstr2 = decompose_unichar(c, &dsize2))) {
+				c2 = c;
+				dstr2 = &c2;
+				dsize2 = 1;
+			}
+		}
+
+		c1 = *dstr1;
+		c2 = *dstr2;
+		if (casefold) {
+			if  (!(c1 = case_fold(c1))) {
+				dstr1++;
+				dsize1--;
+				continue;
+			}
+			if (!(c2 = case_fold(c2))) {
+				dstr2++;
+				dsize2--;
+				continue;
+			}
+		}
+		if (c1 < c2)
+			return -1;
+		else if (c1 > c2)
+			return 1;
+
+		dstr1++;
+		dsize1--;
+		dstr2++;
+		dsize2--;
+	}
+
+	if (len1 < len2)
+		return -1;
+	if (len1 > len2)
+		return 1;
+	return 0;
+}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e6b46b3..d145cb7 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -13,15 +13,18 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/file.h>
+#include <linux/kernel.h>
 #include <linux/writeback.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/capability.h>
+#include <linux/ctype.h>
 #include <linux/backing-dev.h>
 #include <linux/hugetlb.h>
 #include <linux/pagevec.h>
+#include <linux/parser.h>
 #include <linux/mman.h>
 #include <linux/quotaops.h>
 #include <linux/slab.h>
@@ -47,6 +50,21 @@
 
 int sysctl_hugetlb_shm_group;
 
+enum {
+	Opt_size, Opt_nr_inodes,
+	Opt_mode, Opt_uid, Opt_gid,
+	Opt_err,
+};
+
+static match_table_t tokens = {
+	{Opt_size,	"size=%s"},
+	{Opt_nr_inodes,	"nr_inodes=%s"},
+	{Opt_mode,	"mode=%o"},
+	{Opt_uid,	"uid=%u"},
+	{Opt_gid,	"gid=%u"},
+	{Opt_err,	NULL},
+};
+
 static void huge_pagevec_release(struct pagevec *pvec)
 {
 	int i;
@@ -594,46 +612,73 @@
 static int
 hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
 {
-	char *opt, *value, *rest;
+	char *p, *rest;
+	substring_t args[MAX_OPT_ARGS];
+	int option;
 
 	if (!options)
 		return 0;
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
+
+	while ((p = strsep(&options, ",")) != NULL) {
+		int token;
+		if (!*p)
 			continue;
 
-		value = strchr(opt, '=');
-		if (!value || !*value)
-			return -EINVAL;
-		else
-			*value++ = '\0';
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_uid:
+			if (match_int(&args[0], &option))
+ 				goto bad_val;
+			pconfig->uid = option;
+			break;
 
-		if (!strcmp(opt, "uid"))
-			pconfig->uid = simple_strtoul(value, &value, 0);
-		else if (!strcmp(opt, "gid"))
-			pconfig->gid = simple_strtoul(value, &value, 0);
-		else if (!strcmp(opt, "mode"))
-			pconfig->mode = simple_strtoul(value,&value,0) & 0777U;
-		else if (!strcmp(opt, "size")) {
-			unsigned long long size = memparse(value, &rest);
+		case Opt_gid:
+			if (match_int(&args[0], &option))
+ 				goto bad_val;
+			pconfig->gid = option;
+			break;
+
+		case Opt_mode:
+			if (match_octal(&args[0], &option))
+ 				goto bad_val;
+			pconfig->mode = option & 0777U;
+			break;
+
+		case Opt_size: {
+ 			unsigned long long size;
+			/* memparse() will accept a K/M/G without a digit */
+			if (!isdigit(*args[0].from))
+				goto bad_val;
+			size = memparse(args[0].from, &rest);
 			if (*rest == '%') {
 				size <<= HPAGE_SHIFT;
 				size *= max_huge_pages;
 				do_div(size, 100);
-				rest++;
 			}
 			pconfig->nr_blocks = (size >> HPAGE_SHIFT);
-			value = rest;
-		} else if (!strcmp(opt,"nr_inodes")) {
-			pconfig->nr_inodes = memparse(value, &rest);
-			value = rest;
-		} else
-			return -EINVAL;
+			break;
+		}
 
-		if (*value)
+		case Opt_nr_inodes:
+			/* memparse() will accept a K/M/G without a digit */
+			if (!isdigit(*args[0].from))
+				goto bad_val;
+			pconfig->nr_inodes = memparse(args[0].from, &rest);
+			break;
+
+		default:
+			printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
+				 p);
 			return -EINVAL;
+			break;
+		}
 	}
 	return 0;
+
+bad_val:
+ 	printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
+	       args[0].from, p);
+ 	return 1;
 }
 
 static int
@@ -651,7 +696,6 @@
 	config.gid = current->fsgid;
 	config.mode = 0755;
 	ret = hugetlbfs_parse_options(data, &config);
-
 	if (ret)
 		return ret;
 
diff --git a/fs/inode.c b/fs/inode.c
index 9a012cc..320e088 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -145,7 +145,7 @@
 		mapping->a_ops = &empty_aops;
  		mapping->host = inode;
 		mapping->flags = 0;
-		mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
+		mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE);
 		mapping->assoc_mapping = NULL;
 		mapping->backing_dev_info = &default_backing_dev_info;
 
@@ -462,6 +462,11 @@
 	return (inodes_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
 
+static struct shrinker icache_shrinker = {
+	.shrink = shrink_icache_memory,
+	.seeks = DEFAULT_SEEKS,
+};
+
 static void __wait_on_freeing_inode(struct inode *inode);
 /*
  * Called with the inode lock held.
@@ -519,7 +524,13 @@
  *	new_inode 	- obtain an inode
  *	@sb: superblock
  *
- *	Allocates a new inode for given superblock.
+ *	Allocates a new inode for given superblock. The default gfp_mask
+ *	for allocations related to inode->i_mapping is GFP_HIGHUSER_PAGECACHE.
+ *	If HIGHMEM pages are unsuitable or it is known that pages allocated
+ *	for the page cache are not reclaimable or migratable,
+ *	mapping_set_gfp_mask() must be called with suitable flags on the
+ *	newly created inode's mapping
+ *
  */
 struct inode *new_inode(struct super_block *sb)
 {
@@ -1379,7 +1390,7 @@
 					 SLAB_MEM_SPREAD),
 					 init_once,
 					 NULL);
-	set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
+	register_shrinker(&icache_shrinker);
 
 	/* Hash may have been set up in inode_init_early */
 	if (!hashdist)
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 8c90cbc..c2a773e 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -12,7 +12,6 @@
 #include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/module.h>
-#include <linux/kallsyms.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -21,7 +20,6 @@
 		unsigned long arg)
 {
 	int error = -ENOTTY;
-	void *f;
 
 	if (!filp->f_op)
 		goto out;
@@ -31,16 +29,10 @@
 		if (error == -ENOIOCTLCMD)
 			error = -EINVAL;
 		goto out;
-	} else if ((f = filp->f_op->ioctl)) {
+	} else if (filp->f_op->ioctl) {
 		lock_kernel();
-		if (!filp->f_op->ioctl) {
-			printk("%s: ioctl %p disappeared\n", __FUNCTION__, f);
-			print_symbol("symbol: %s\n", (unsigned long)f);
-			dump_stack();
-		} else {
-			error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
-						  filp, cmd, arg);
-		}
+		error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
+					  filp, cmd, arg);
 		unlock_kernel();
 	}
 
@@ -182,11 +174,3 @@
  out:
 	return error;
 }
-
-/*
- * Platforms implementing 32 bit compatibility ioctl handlers in
- * modules need this exported
- */
-#ifdef CONFIG_COMPAT
-EXPORT_SYMBOL(sys_ioctl);
-#endif
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 0e94c31..1ba407c 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -7,34 +7,18 @@
  *
  *  Steve Beynon		       : Missing last directory entries fixed
  *  (stephen@askone.demon.co.uk)      : 21st June 1996
- * 
+ *
  *  isofs directory handling functions
  */
 #include <linux/smp_lock.h>
 #include "isofs.h"
 
-static int isofs_readdir(struct file *, void *, filldir_t);
-
-const struct file_operations isofs_dir_operations =
-{
-	.read		= generic_read_dir,
-	.readdir	= isofs_readdir,
-};
-
-/*
- * directories can handle most operations...
- */
-const struct inode_operations isofs_dir_inode_operations =
-{
-	.lookup		= isofs_lookup,
-};
-
 int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
 {
 	char * old = de->name;
 	int len = de->name_len[0];
 	int i;
-			
+
 	for (i = 0; i < len; i++) {
 		unsigned char c = old[i];
 		if (!c)
@@ -62,22 +46,27 @@
 }
 
 /* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */
-int get_acorn_filename(struct iso_directory_record * de,
-			    char * retname, struct inode * inode)
+int get_acorn_filename(struct iso_directory_record *de,
+			    char *retname, struct inode *inode)
 {
 	int std;
-	unsigned char * chr;
+	unsigned char *chr;
 	int retnamlen = isofs_name_translate(de, retname, inode);
-	if (retnamlen == 0) return 0;
+
+	if (retnamlen == 0)
+		return 0;
 	std = sizeof(struct iso_directory_record) + de->name_len[0];
-	if (std & 1) std++;
-	if ((*((unsigned char *) de) - std) != 32) return retnamlen;
+	if (std & 1)
+		std++;
+	if ((*((unsigned char *) de) - std) != 32)
+		return retnamlen;
 	chr = ((unsigned char *) de) + std;
-	if (strncmp(chr, "ARCHIMEDES", 10)) return retnamlen;
-	if ((*retname == '_') && ((chr[19] & 1) == 1)) *retname = '!';
+	if (strncmp(chr, "ARCHIMEDES", 10))
+		return retnamlen;
+	if ((*retname == '_') && ((chr[19] & 1) == 1))
+		*retname = '!';
 	if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
-		&& ((chr[12] & 0xf0) == 0xf0))
-	{
+		&& ((chr[12] & 0xf0) == 0xf0)) {
 		retname[retnamlen] = ',';
 		sprintf(retname+retnamlen+1, "%3.3x",
 			((chr[12] & 0xf) << 8) | chr[11]);
@@ -91,7 +80,7 @@
  */
 static int do_isofs_readdir(struct inode *inode, struct file *filp,
 		void *dirent, filldir_t filldir,
-		char * tmpname, struct iso_directory_record * tmpde)
+		char *tmpname, struct iso_directory_record *tmpde)
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
@@ -121,9 +110,11 @@
 
 		de_len = *(unsigned char *) de;
 
-		/* If the length byte is zero, we should move on to the next
-		   CDROM sector.  If we are at the end of the directory, we
-		   kick out of the while loop. */
+		/*
+		 * If the length byte is zero, we should move on to the next
+		 * CDROM sector.  If we are at the end of the directory, we
+		 * kick out of the while loop.
+		 */
 
 		if (de_len == 0) {
 			brelse(bh);
@@ -157,11 +148,10 @@
 
 		if (first_de) {
 			isofs_normalize_block_and_offset(de,
-							 &block_saved,
-							 &offset_saved);
+							&block_saved,
+							&offset_saved);
 			inode_number = isofs_get_ino(block_saved,
-						     offset_saved,
-						     bufbits);
+							offset_saved, bufbits);
 		}
 
 		if (de->flags[-sbi->s_high_sierra] & 0x80) {
@@ -199,7 +189,7 @@
 		 */
 		if ((sbi->s_hide == 'y' &&
 				(de->flags[-sbi->s_high_sierra] & 1)) ||
-		      (sbi->s_showassoc =='n' &&
+				(sbi->s_showassoc =='n' &&
 				(de->flags[-sbi->s_high_sierra] & 4))) {
 			filp->f_pos += de_len;
 			continue;
@@ -240,7 +230,8 @@
 
 		continue;
 	}
-	if (bh) brelse(bh);
+	if (bh)
+		brelse(bh);
 	return 0;
 }
 
@@ -253,8 +244,8 @@
 		void *dirent, filldir_t filldir)
 {
 	int result;
-	char * tmpname;
-	struct iso_directory_record * tmpde;
+	char *tmpname;
+	struct iso_directory_record *tmpde;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 
 	tmpname = (char *)__get_free_page(GFP_KERNEL);
@@ -270,3 +261,19 @@
 	unlock_kernel();
 	return result;
 }
+
+const struct file_operations isofs_dir_operations =
+{
+	.read = generic_read_dir,
+	.readdir = isofs_readdir,
+};
+
+/*
+ * directories can handle most operations...
+ */
+const struct inode_operations isofs_dir_inode_operations =
+{
+	.lookup = isofs_lookup,
+};
+
+
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 5c3eecf..4f5418b 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -73,20 +73,20 @@
 	kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
 }
 
-static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
 	struct iso_inode_info *ei = foo;
 
 	inode_init_once(&ei->vfs_inode);
 }
- 
+
 static int init_inodecache(void)
 {
 	isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
-					     sizeof(struct iso_inode_info),
-					     0, (SLAB_RECLAIM_ACCOUNT|
-						SLAB_MEM_SPREAD),
-					     init_once, NULL);
+					sizeof(struct iso_inode_info),
+					0, (SLAB_RECLAIM_ACCOUNT|
+					SLAB_MEM_SPREAD),
+					init_once, NULL);
 	if (isofs_inode_cachep == NULL)
 		return -ENOMEM;
 	return 0;
@@ -150,9 +150,9 @@
 	uid_t uid;
 	char *iocharset;
 	unsigned char utf8;
-        /* LVE */
-        s32 session;
-        s32 sbsector;
+	/* LVE */
+	s32 session;
+	s32 sbsector;
 };
 
 /*
@@ -197,7 +197,7 @@
 	hash = init_name_hash();
 	while (len--) {
 		c = tolower(*name++);
-		hash = partial_name_hash(tolower(c), hash);
+		hash = partial_name_hash(c, hash);
 	}
 	qstr->hash = end_name_hash(hash);
 
@@ -360,10 +360,12 @@
 	popt->check = 'u';		/* unset */
 	popt->nocompress = 0;
 	popt->blocksize = 1024;
-	popt->mode = S_IRUGO | S_IXUGO; /* r-x for all.  The disc could
-					   be shared with DOS machines so
-					   virtually anything could be
-					   a valid executable. */
+	popt->mode = S_IRUGO | S_IXUGO; /*
+					 * r-x for all.  The disc could
+					 * be shared with DOS machines so
+					 * virtually anything could be
+					 * a valid executable.
+					 */
 	popt->gid = 0;
 	popt->uid = 0;
 	popt->iocharset = NULL;
@@ -503,30 +505,30 @@
 		Te.cdte_format=CDROM_LBA;
 		i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
 		if (!i) {
-			printk(KERN_DEBUG "Session %d start %d type %d\n",
-			       session, Te.cdte_addr.lba,
-			       Te.cdte_ctrl&CDROM_DATA_TRACK);
+			printk(KERN_DEBUG "ISOFS: Session %d start %d type %d\n",
+				session, Te.cdte_addr.lba,
+				Te.cdte_ctrl&CDROM_DATA_TRACK);
 			if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
 				return Te.cdte_addr.lba;
 		}
-			
-		printk(KERN_ERR "Invalid session number or type of track\n");
+
+		printk(KERN_ERR "ISOFS: Invalid session number or type of track\n");
 	}
 	i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
 	if (session > 0)
-		printk(KERN_ERR "Invalid session number\n");
+		printk(KERN_ERR "ISOFS: Invalid session number\n");
 #if 0
-	printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
+	printk(KERN_DEBUG "isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
 	if (i==0) {
-		printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
-		printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
+		printk(KERN_DEBUG "isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
+		printk(KERN_DEBUG "isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
 	}
 #endif
 	if (i==0)
 #if WE_OBEY_THE_WRITTEN_STANDARDS
-        if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
+		if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
 #endif
-		vol_desc_start=ms_info.addr.lba;
+			vol_desc_start=ms_info.addr.lba;
 	return vol_desc_start;
 }
 
@@ -538,20 +540,20 @@
  */
 static int isofs_fill_super(struct super_block *s, void *data, int silent)
 {
-	struct buffer_head	      * bh = NULL, *pri_bh = NULL;
-	struct hs_primary_descriptor  * h_pri = NULL;
-	struct iso_primary_descriptor * pri = NULL;
+	struct buffer_head *bh = NULL, *pri_bh = NULL;
+	struct hs_primary_descriptor *h_pri = NULL;
+	struct iso_primary_descriptor *pri = NULL;
 	struct iso_supplementary_descriptor *sec = NULL;
-	struct iso_directory_record   * rootp;
-	int				joliet_level = 0;
-	int				iso_blknum, block;
-	int				orig_zonesize;
-	int				table;
-	unsigned int			vol_desc_start;
-	unsigned long			first_data_zone;
-	struct inode		      * inode;
-	struct iso9660_options		opt;
-	struct isofs_sb_info	      * sbi;
+	struct iso_directory_record *rootp;
+	struct inode *inode;
+	struct iso9660_options opt;
+	struct isofs_sb_info *sbi;
+	unsigned long first_data_zone;
+	int joliet_level = 0;
+	int iso_blknum, block;
+	int orig_zonesize;
+	int table;
+	unsigned int vol_desc_start;
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -577,72 +579,73 @@
 	vol_desc_start = (opt.sbsector != -1) ?
 		opt.sbsector : isofs_get_last_session(s,opt.session);
 
-  	for (iso_blknum = vol_desc_start+16;
-             iso_blknum < vol_desc_start+100; iso_blknum++)
-	{
-	    struct hs_volume_descriptor   * hdp;
-	    struct iso_volume_descriptor  * vdp;
+	for (iso_blknum = vol_desc_start+16;
+		iso_blknum < vol_desc_start+100; iso_blknum++) {
+		struct hs_volume_descriptor *hdp;
+		struct iso_volume_descriptor  *vdp;
 
-	    block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
-	    if (!(bh = sb_bread(s, block)))
-		goto out_no_read;
+		block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
+		if (!(bh = sb_bread(s, block)))
+			goto out_no_read;
 
-	    vdp = (struct iso_volume_descriptor *)bh->b_data;
-	    hdp = (struct hs_volume_descriptor *)bh->b_data;
-	    
-	    /* Due to the overlapping physical location of the descriptors, 
-	     * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure 
-	     * proper identification in this case, we first check for ISO.
-	     */
-	    if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
-		if (isonum_711 (vdp->type) == ISO_VD_END)
-		    break;
-		if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
-		    if (pri == NULL) {
-			pri = (struct iso_primary_descriptor *)vdp;
-			/* Save the buffer in case we need it ... */
-			pri_bh = bh;
-			bh = NULL;
-		    }
-		}
-#ifdef CONFIG_JOLIET
-		else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
-		    sec = (struct iso_supplementary_descriptor *)vdp;
-		    if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
-			if (opt.joliet == 'y') {
-			    if (sec->escape[2] == 0x40) {
-				joliet_level = 1;
-			    } else if (sec->escape[2] == 0x43) {
-				joliet_level = 2;
-			    } else if (sec->escape[2] == 0x45) {
-				joliet_level = 3;
-			    }
-			    printk(KERN_DEBUG"ISO 9660 Extensions: Microsoft Joliet Level %d\n",
-				   joliet_level);
+		vdp = (struct iso_volume_descriptor *)bh->b_data;
+		hdp = (struct hs_volume_descriptor *)bh->b_data;
+
+		/*
+		 * Due to the overlapping physical location of the descriptors,
+		 * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure
+		 * proper identification in this case, we first check for ISO.
+		 */
+		if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
+			if (isonum_711(vdp->type) == ISO_VD_END)
+				break;
+			if (isonum_711(vdp->type) == ISO_VD_PRIMARY) {
+				if (pri == NULL) {
+					pri = (struct iso_primary_descriptor *)vdp;
+					/* Save the buffer in case we need it ... */
+					pri_bh = bh;
+					bh = NULL;
+				}
 			}
-			goto root_found;
-		    } else {
-			/* Unknown supplementary volume descriptor */
-			sec = NULL;
-		    }
-		}
+#ifdef CONFIG_JOLIET
+			else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) {
+				sec = (struct iso_supplementary_descriptor *)vdp;
+				if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
+					if (opt.joliet == 'y') {
+						if (sec->escape[2] == 0x40)
+							joliet_level = 1;
+						else if (sec->escape[2] == 0x43)
+							joliet_level = 2;
+						else if (sec->escape[2] == 0x45)
+							joliet_level = 3;
+
+						printk(KERN_DEBUG "ISO 9660 Extensions: "
+							"Microsoft Joliet Level %d\n",
+							joliet_level);
+					}
+					goto root_found;
+				} else {
+				/* Unknown supplementary volume descriptor */
+				sec = NULL;
+				}
+			}
 #endif
-	    } else {
-	        if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
-		    if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
-		        goto out_freebh;
-		
-		    sbi->s_high_sierra = 1;
-		    opt.rock = 'n';
-		    h_pri = (struct hs_primary_descriptor *)vdp;
-		    goto root_found;
+		} else {
+			if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
+				if (isonum_711(hdp->type) != ISO_VD_PRIMARY)
+					goto out_freebh;
+
+				sbi->s_high_sierra = 1;
+				opt.rock = 'n';
+				h_pri = (struct hs_primary_descriptor *)vdp;
+				goto root_found;
+			}
 		}
-	    }
 
-            /* Just skip any volume descriptors we don't recognize */
+		/* Just skip any volume descriptors we don't recognize */
 
-	    brelse(bh);
-	    bh = NULL;
+		brelse(bh);
+		bh = NULL;
 	}
 	/*
 	 * If we fall through, either no volume descriptor was found,
@@ -657,24 +660,24 @@
 root_found:
 
 	if (joliet_level && (pri == NULL || opt.rock == 'n')) {
-	    /* This is the case of Joliet with the norock mount flag.
-	     * A disc with both Joliet and Rock Ridge is handled later
-	     */
-	    pri = (struct iso_primary_descriptor *) sec;
+		/* This is the case of Joliet with the norock mount flag.
+		 * A disc with both Joliet and Rock Ridge is handled later
+		 */
+		pri = (struct iso_primary_descriptor *) sec;
 	}
 
 	if(sbi->s_high_sierra){
-	  rootp = (struct iso_directory_record *) h_pri->root_directory_record;
-	  sbi->s_nzones = isonum_733 (h_pri->volume_space_size);
-	  sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
-	  sbi->s_max_size = isonum_733(h_pri->volume_space_size);
+		rootp = (struct iso_directory_record *) h_pri->root_directory_record;
+		sbi->s_nzones = isonum_733(h_pri->volume_space_size);
+		sbi->s_log_zone_size = isonum_723(h_pri->logical_block_size);
+		sbi->s_max_size = isonum_733(h_pri->volume_space_size);
 	} else {
-	  if (!pri)
-	    goto out_freebh;
-	  rootp = (struct iso_directory_record *) pri->root_directory_record;
-	  sbi->s_nzones = isonum_733 (pri->volume_space_size);
-	  sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
-	  sbi->s_max_size = isonum_733(pri->volume_space_size);
+		if (!pri)
+			goto out_freebh;
+		rootp = (struct iso_directory_record *) pri->root_directory_record;
+		sbi->s_nzones = isonum_733(pri->volume_space_size);
+		sbi->s_log_zone_size = isonum_723(pri->logical_block_size);
+		sbi->s_max_size = isonum_733(pri->volume_space_size);
 	}
 
 	sbi->s_ninodes = 0; /* No way to figure this out easily */
@@ -687,42 +690,43 @@
 	 * blocks that were 512 bytes (which should only very rarely
 	 * happen.)
 	 */
-	if(orig_zonesize < opt.blocksize)
+	if (orig_zonesize < opt.blocksize)
 		goto out_bad_size;
 
 	/* RDE: convert log zone size to bit shift */
-	switch (sbi->s_log_zone_size)
-	  { case  512: sbi->s_log_zone_size =  9; break;
-	    case 1024: sbi->s_log_zone_size = 10; break;
-	    case 2048: sbi->s_log_zone_size = 11; break;
+	switch (sbi->s_log_zone_size) {
+	case  512: sbi->s_log_zone_size =  9; break;
+	case 1024: sbi->s_log_zone_size = 10; break;
+	case 2048: sbi->s_log_zone_size = 11; break;
 
-	    default:
+	default:
 		goto out_bad_zone_size;
-	  }
+	}
 
 	s->s_magic = ISOFS_SUPER_MAGIC;
 	s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */
 
-	/* The CDROM is read-only, has no nodes (devices) on it, and since
-	   all of the files appear to be owned by root, we really do not want
-	   to allow suid.  (suid or devices will not show up unless we have
-	   Rock Ridge extensions) */
+	/*
+	 * The CDROM is read-only, has no nodes (devices) on it, and since
+	 * all of the files appear to be owned by root, we really do not want
+	 * to allow suid.  (suid or devices will not show up unless we have
+	 * Rock Ridge extensions)
+	 */
 
 	s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
 
 	/* Set this for reference. Its not currently used except on write
 	   which we don't have .. */
-	   
-	first_data_zone = isonum_733 (rootp->extent) +
-			  isonum_711 (rootp->ext_attr_length);
+
+	first_data_zone = isonum_733(rootp->extent) +
+			  isonum_711(rootp->ext_attr_length);
 	sbi->s_firstdatazone = first_data_zone;
 #ifndef BEQUIET
-	printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
-	       sbi->s_max_size,
-	       1UL << sbi->s_log_zone_size);
-	printk(KERN_DEBUG "First datazone:%ld\n", sbi->s_firstdatazone);
+	printk(KERN_DEBUG "ISOFS: Max size:%ld   Log zone size:%ld\n",
+		sbi->s_max_size, 1UL << sbi->s_log_zone_size);
+	printk(KERN_DEBUG "ISOFS: First datazone:%ld\n", sbi->s_firstdatazone);
 	if(sbi->s_high_sierra)
-		printk(KERN_DEBUG "Disc in High Sierra format.\n");
+		printk(KERN_DEBUG "ISOFS: Disc in High Sierra format.\n");
 #endif
 
 	/*
@@ -737,8 +741,8 @@
 		pri = (struct iso_primary_descriptor *) sec;
 		rootp = (struct iso_directory_record *)
 			pri->root_directory_record;
-		first_data_zone = isonum_733 (rootp->extent) +
-			  	isonum_711 (rootp->ext_attr_length);
+		first_data_zone = isonum_733(rootp->extent) +
+				isonum_711(rootp->ext_attr_length);
 	}
 
 	/*
@@ -771,7 +775,7 @@
 
 #ifdef CONFIG_JOLIET
 	if (joliet_level && opt.utf8 == 0) {
-		char * p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
+		char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
 		sbi->s_nls_iocharset = load_nls(p);
 		if (! sbi->s_nls_iocharset) {
 			/* Fail only if explicit charset specified */
@@ -821,7 +825,7 @@
 		sbi->s_rock = 0;
 		if (sbi->s_firstdatazone != first_data_zone) {
 			sbi->s_firstdatazone = first_data_zone;
-			printk(KERN_DEBUG 
+			printk(KERN_DEBUG
 				"ISOFS: changing to secondary root\n");
 			iput(inode);
 			inode = isofs_iget(s, sbi->s_firstdatazone, 0);
@@ -830,8 +834,10 @@
 
 	if (opt.check == 'u') {
 		/* Only Joliet is case insensitive by default */
-		if (joliet_level) opt.check = 'r';
-		else opt.check = 's';
+		if (joliet_level)
+			opt.check = 'r';
+		else
+			opt.check = 's';
 	}
 	sbi->s_joliet_level = joliet_level;
 
@@ -846,8 +852,10 @@
 		goto out_no_root;
 
 	table = 0;
-	if (joliet_level) table += 2;
-	if (opt.check == 'r') table++;
+	if (joliet_level)
+		table += 2;
+	if (opt.check == 'r')
+		table++;
 	s->s_root->d_op = &isofs_dentry_ops[table];
 
 	kfree(opt.iocharset);
@@ -858,10 +866,10 @@
 	 * Display error messages and free resources.
 	 */
 out_bad_root:
-	printk(KERN_WARNING "isofs_fill_super: root inode not initialized\n");
+	printk(KERN_WARNING "%s: root inode not initialized\n", __func__);
 	goto out_iput;
 out_no_root:
-	printk(KERN_WARNING "isofs_fill_super: get root inode failed\n");
+	printk(KERN_WARNING "%s: get root inode failed\n", __func__);
 out_iput:
 	iput(inode);
 #ifdef CONFIG_JOLIET
@@ -870,21 +878,20 @@
 #endif
 	goto out_freesbi;
 out_no_read:
-	printk(KERN_WARNING "isofs_fill_super: "
-		"bread failed, dev=%s, iso_blknum=%d, block=%d\n",
-		s->s_id, iso_blknum, block);
+	printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n",
+		__func__, s->s_id, iso_blknum, block);
 	goto out_freesbi;
 out_bad_zone_size:
-	printk(KERN_WARNING "Bad logical zone size %ld\n",
+	printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n",
 		sbi->s_log_zone_size);
 	goto out_freebh;
 out_bad_size:
-	printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
+	printk(KERN_WARNING "ISOFS: Logical zone size(%d) < hardware blocksize(%u)\n",
 		orig_zonesize, opt.blocksize);
 	goto out_freebh;
 out_unknown_format:
 	if (!silent)
-		printk(KERN_WARNING "Unable to identify CD-ROM format.\n");
+		printk(KERN_WARNING "ISOFS: Unable to identify CD-ROM format.\n");
 
 out_freebh:
 	brelse(bh);
@@ -902,7 +909,7 @@
 	buf->f_type = ISOFS_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = (ISOFS_SB(sb)->s_nzones
-                  << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
+		<< (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
 	buf->f_bfree = 0;
 	buf->f_bavail = 0;
 	buf->f_files = ISOFS_SB(sb)->s_ninodes;
@@ -931,20 +938,20 @@
 
 	rv = 0;
 	if (iblock < 0 || iblock != iblock_s) {
-		printk("isofs_get_blocks: block number too large\n");
+		printk(KERN_DEBUG "%s: block number too large\n", __func__);
 		goto abort;
 	}
 
 	b_off = iblock;
-	
-	offset    = 0;
-	firstext  = ei->i_first_extent;
-	sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
-	nextblk   = ei->i_next_section_block;
-	nextoff   = ei->i_next_section_offset;
-	section   = 0;
 
-	while ( nblocks ) {
+	offset = 0;
+	firstext = ei->i_first_extent;
+	sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
+	nextblk = ei->i_next_section_block;
+	nextoff = ei->i_next_section_offset;
+	section = 0;
+
+	while (nblocks) {
 		/* If we are *way* beyond the end of the file, print a message.
 		 * Access beyond the end of the file up to the next page boundary
 		 * is normal, however because of the way the page cache works.
@@ -953,11 +960,11 @@
 		 * I/O errors.
 		 */
 		if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) {
-			printk("isofs_get_blocks: block >= EOF (%ld, %ld)\n",
-			       iblock, (unsigned long) inode->i_size);
+			printk(KERN_DEBUG "%s: block >= EOF (%ld, %ld)\n",
+				__func__, iblock, (unsigned long) inode->i_size);
 			goto abort;
 		}
-		
+
 		/* On the last section, nextblk == 0, section size is likely to
 		 * exceed sect_size by a partial block, and access beyond the
 		 * end of the file will reach beyond the section size, too.
@@ -976,20 +983,21 @@
 			iput(ninode);
 
 			if (++section > 100) {
-				printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
-				printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
-				       "nextblk=%lu nextoff=%lu\n",
-				       iblock, firstext, (unsigned) sect_size,
-				       nextblk, nextoff);
+				printk(KERN_DEBUG "%s: More than 100 file sections ?!?"
+					" aborting...\n", __func__);
+				printk(KERN_DEBUG "%s: block=%ld firstext=%u sect_size=%u "
+					"nextblk=%lu nextoff=%lu\n", __func__,
+					iblock, firstext, (unsigned) sect_size,
+					nextblk, nextoff);
 				goto abort;
 			}
 		}
-		
-		if ( *bh ) {
+
+		if (*bh) {
 			map_bh(*bh, inode->i_sb, firstext + b_off - offset);
 		} else {
 			*bh = sb_getblk(inode->i_sb, firstext+b_off-offset);
-			if ( !*bh )
+			if (!*bh)
 				goto abort;
 		}
 		bh++;	/* Next buffer head */
@@ -1010,7 +1018,7 @@
 		    struct buffer_head *bh_result, int create)
 {
 	if (create) {
-		printk("isofs_get_block: Kernel tries to allocate a block\n");
+		printk(KERN_DEBUG "%s: Kernel tries to allocate a block\n", __func__);
 		return -EROFS;
 	}
 
@@ -1070,11 +1078,11 @@
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
-	struct buffer_head * bh = NULL;
+	struct buffer_head *bh = NULL;
 	unsigned long block, offset, block_saved, offset_saved;
 	int i = 0;
 	int more_entries = 0;
-	struct iso_directory_record * tmpde = NULL;
+	struct iso_directory_record *tmpde = NULL;
 	struct iso_inode_info *ei = ISOFS_I(inode);
 
 	inode->i_size = 0;
@@ -1089,7 +1097,7 @@
 	offset = ei->i_iget5_offset;
 
 	do {
-		struct iso_directory_record * de;
+		struct iso_directory_record *de;
 		unsigned int de_len;
 
 		if (!bh) {
@@ -1163,10 +1171,9 @@
 	return -EIO;
 
 out_toomany:
-	printk(KERN_INFO "isofs_read_level3_size: "
-		"More than 100 file sections ?!?, aborting...\n"
-	  	"isofs_read_level3_size: inode=%lu\n",
-		inode->i_ino);
+	printk(KERN_INFO "%s: More than 100 file sections ?!?, aborting...\n"
+		"isofs_read_level3_size: inode=%lu\n",
+		__func__, inode->i_ino);
 	goto out;
 }
 
@@ -1177,9 +1184,9 @@
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	unsigned long block;
 	int high_sierra = sbi->s_high_sierra;
-	struct buffer_head * bh = NULL;
-	struct iso_directory_record * de;
-	struct iso_directory_record * tmpde = NULL;
+	struct buffer_head *bh = NULL;
+	struct iso_directory_record *de;
+	struct iso_directory_record *tmpde = NULL;
 	unsigned int de_len;
 	unsigned long offset;
 	struct iso_inode_info *ei = ISOFS_I(inode);
@@ -1199,7 +1206,7 @@
 
 		tmpde = kmalloc(de_len, GFP_KERNEL);
 		if (tmpde == NULL) {
-			printk(KERN_INFO "isofs_read_inode: out of memory\n");
+			printk(KERN_INFO "%s: out of memory\n", __func__);
 			goto fail;
 		}
 		memcpy(tmpde, bh->b_data + offset, frag1);
@@ -1212,24 +1219,26 @@
 	}
 
 	inode->i_ino = isofs_get_ino(ei->i_iget5_block,
-				     ei->i_iget5_offset,
-				     ISOFS_BUFFER_BITS(inode));
+					ei->i_iget5_offset,
+					ISOFS_BUFFER_BITS(inode));
 
 	/* Assume it is a normal-format file unless told otherwise */
 	ei->i_file_format = isofs_file_normal;
 
 	if (de->flags[-high_sierra] & 2) {
 		inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
-		inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
-				       the find utility tries to optimize
-				       if it is 2, and it screws up.  It is
-				       easier to give 1 which tells find to
-				       do it the hard way. */
+		inode->i_nlink = 1;	/*
+					 * Set to 1.  We know there are 2, but
+					 * the find utility tries to optimize
+					 * if it is 2, and it screws up.  It is
+					 * easier to give 1 which tells find to
+					 * do it the hard way.
+					 */
 	} else {
- 		/* Everybody gets to read the file. */
+		/* Everybody gets to read the file. */
 		inode->i_mode = sbi->s_mode;
 		inode->i_nlink = 1;
-	        inode->i_mode |= S_IFREG;
+		inode->i_mode |= S_IFREG;
 	}
 	inode->i_uid = sbi->s_uid;
 	inode->i_gid = sbi->s_gid;
@@ -1239,13 +1248,14 @@
 	ei->i_format_parm[1] = 0;
 	ei->i_format_parm[2] = 0;
 
-	ei->i_section_size = isonum_733 (de->size);
+	ei->i_section_size = isonum_733(de->size);
 	if (de->flags[-high_sierra] & 0x80) {
-		if(isofs_read_level3_size(inode)) goto fail;
+		if(isofs_read_level3_size(inode))
+			goto fail;
 	} else {
 		ei->i_next_section_block = 0;
 		ei->i_next_section_offset = 0;
-		inode->i_size = isonum_733 (de->size);
+		inode->i_size = isonum_733(de->size);
 	}
 
 	/*
@@ -1258,23 +1268,24 @@
 		inode->i_size &= 0x00ffffff;
 
 	if (de->interleave[0]) {
-		printk("Interleaved files not (yet) supported.\n");
+		printk(KERN_DEBUG "ISOFS: Interleaved files not (yet) supported.\n");
 		inode->i_size = 0;
 	}
 
 	/* I have no idea what file_unit_size is used for, so
 	   we will flag it for now */
 	if (de->file_unit_size[0] != 0) {
-		printk("File unit size != 0 for ISO file (%ld).\n",
-		       inode->i_ino);
+		printk(KERN_DEBUG "ISOFS: File unit size != 0 for ISO file (%ld).\n",
+			inode->i_ino);
 	}
 
 	/* I have no idea what other flag bits are used for, so
 	   we will flag it for now */
 #ifdef DEBUG
 	if((de->flags[-high_sierra] & ~2)!= 0){
-		printk("Unusual flag settings for ISO file (%ld %x).\n",
-		       inode->i_ino, de->flags[-high_sierra]);
+		printk(KERN_DEBUG "ISOFS: Unusual flag settings for ISO file "
+				"(%ld %x).\n",
+			inode->i_ino, de->flags[-high_sierra]);
 	}
 #endif
 
@@ -1285,11 +1296,11 @@
 	inode->i_atime.tv_nsec =
 	inode->i_ctime.tv_nsec = 0;
 
-	ei->i_first_extent = (isonum_733 (de->extent) +
-			      isonum_711 (de->ext_attr_length));
+	ei->i_first_extent = (isonum_733(de->extent) +
+			isonum_711(de->ext_attr_length));
 
 	/* Set the number of blocks for stat() - should be done before RR */
-	inode->i_blocks  = (inode->i_size + 511) >> 9;
+	inode->i_blocks = (inode->i_size + 511) >> 9;
 
 	/*
 	 * Now test for possible Rock Ridge extensions which will override
@@ -1306,7 +1317,7 @@
 	/* Install the inode operations vector */
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_fop = &generic_ro_fops;
-		switch ( ei->i_file_format ) {
+		switch (ei->i_file_format) {
 #ifdef CONFIG_ZISOFS
 		case isofs_file_compressed:
 			inode->i_data.a_ops = &zisofs_aops;
@@ -1350,7 +1361,7 @@
 	struct isofs_iget5_callback_data *d =
 		(struct isofs_iget5_callback_data*)data;
 	return (i->i_iget5_block == d->block)
-	       && (i->i_iget5_offset == d->offset);
+		&& (i->i_iget5_offset == d->offset);
 }
 
 static int isofs_iget5_set(struct inode *ino, void *data)
@@ -1384,7 +1395,7 @@
 	hashval = (block << sb->s_blocksize_bits) | offset;
 
 	inode = iget5_locked(sb, hashval, &isofs_iget5_test,
-			     &isofs_iget5_set, &data);
+				&isofs_iget5_set, &data);
 
 	if (inode && (inode->i_state & I_NEW)) {
 		sb->s_op->read_inode(inode);
@@ -1398,7 +1409,7 @@
 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super,
-			   mnt);
+				mnt);
 }
 
 static struct file_system_type iso9660_fs_type = {
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index efe2872..a07e67b 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -1,5 +1,6 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/iso_fs.h>
 #include <asm/unaligned.h>
 
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
index fb8fe7a..92c14b8 100644
--- a/fs/isofs/joliet.c
+++ b/fs/isofs/joliet.c
@@ -80,22 +80,20 @@
 
 	if (utf8) {
 		len = wcsntombs_be(outname, de->name,
-				   de->name_len[0] >> 1, PAGE_SIZE);
+				de->name_len[0] >> 1, PAGE_SIZE);
 	} else {
 		len = uni16_to_x8(outname, (__be16 *) de->name,
-				  de->name_len[0] >> 1, nls);
+				de->name_len[0] >> 1, nls);
 	}
-	if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) {
+	if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1'))
 		len -= 2;
-	}
 
 	/*
 	 * Windows doesn't like periods at the end of a name,
 	 * so neither do we
 	 */
-	while (len >= 2 && (outname[len-1] == '.')) {
+	while (len >= 2 && (outname[len-1] == '.'))
 		len--;
-	}
 
 	return len;
 }
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index c04b3a1..c8c7e51 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -15,7 +15,7 @@
  * some sanity tests.
  */
 static int
-isofs_cmp(struct dentry * dentry, const char * compare, int dlen)
+isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
 {
 	struct qstr qstr;
 
@@ -48,24 +48,24 @@
  */
 static unsigned long
 isofs_find_entry(struct inode *dir, struct dentry *dentry,
-	unsigned long *block_rv, unsigned long* offset_rv,
-	char * tmpname, struct iso_directory_record * tmpde)
+	unsigned long *block_rv, unsigned long *offset_rv,
+	char *tmpname, struct iso_directory_record *tmpde)
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
 	unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
 	unsigned long block, f_pos, offset, block_saved, offset_saved;
-	struct buffer_head * bh = NULL;
+	struct buffer_head *bh = NULL;
 	struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
 
 	if (!ISOFS_I(dir)->i_first_extent)
 		return 0;
-  
+
 	f_pos = 0;
 	offset = 0;
 	block = 0;
 
 	while (f_pos < dir->i_size) {
-		struct iso_directory_record * de;
+		struct iso_directory_record *de;
 		int de_len, match, i, dlen;
 		char *dpnt;
 
@@ -114,7 +114,7 @@
 
 		if (sbi->s_rock &&
 		    ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
-			dlen = i; 	/* possibly -1 */
+			dlen = i;	/* possibly -1 */
 			dpnt = tmpname;
 #ifdef CONFIG_JOLIET
 		} else if (sbi->s_joliet_level) {
@@ -145,8 +145,8 @@
 			isofs_normalize_block_and_offset(de,
 							 &block_saved,
 							 &offset_saved);
-                        *block_rv = block_saved;
-                        *offset_rv = offset_saved;
+			*block_rv = block_saved;
+			*offset_rv = offset_saved;
 			brelse(bh);
 			return 1;
 		}
@@ -155,7 +155,7 @@
 	return 0;
 }
 
-struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	int found;
 	unsigned long block, offset;
@@ -170,9 +170,9 @@
 
 	lock_kernel();
 	found = isofs_find_entry(dir, dentry,
-				 &block, &offset,
-				 page_address(page),
-				 1024 + page_address(page));
+				&block, &offset,
+				page_address(page),
+				1024 + page_address(page));
 	__free_page(page);
 
 	inode = NULL;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 1facfaf..a003d50 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -887,7 +887,8 @@
 	journal->j_committing_transaction = NULL;
 	spin_unlock(&journal->j_state_lock);
 
-	if (commit_transaction->t_checkpoint_list == NULL) {
+	if (commit_transaction->t_checkpoint_list == NULL &&
+	    commit_transaction->t_checkpoint_io_list == NULL) {
 		__journal_drop_transaction(journal, commit_transaction);
 	} else {
 		if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 824e3b7..8db2fa2 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -68,6 +68,7 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #endif
+#include <linux/log2.h>
 
 static struct kmem_cache *revoke_record_cache;
 static struct kmem_cache *revoke_table_cache;
@@ -211,7 +212,7 @@
 	journal->j_revoke = journal->j_revoke_table[0];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
@@ -238,7 +239,7 @@
 	journal->j_revoke = journal->j_revoke_table[1];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 2856e11..c0f59d1 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -896,7 +896,8 @@
 	journal->j_committing_transaction = NULL;
 	spin_unlock(&journal->j_state_lock);
 
-	if (commit_transaction->t_checkpoint_list == NULL) {
+	if (commit_transaction->t_checkpoint_list == NULL &&
+	    commit_transaction->t_checkpoint_io_list == NULL) {
 		__jbd2_journal_drop_transaction(journal, commit_transaction);
 	} else {
 		if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 9246e76..28cac04 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -68,6 +68,7 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #endif
+#include <linux/log2.h>
 
 static struct kmem_cache *jbd2_revoke_record_cache;
 static struct kmem_cache *jbd2_revoke_table_cache;
@@ -212,7 +213,7 @@
 	journal->j_revoke = journal->j_revoke_table[0];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
@@ -239,7 +240,7 @@
 	journal->j_revoke = journal->j_revoke_table[1];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 0c82dfc..143c553 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -81,6 +81,7 @@
 
 	set_user_nice(current, 10);
 
+	set_freezable();
 	for (;;) {
 		allow_signal(SIGHUP);
 
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 2374b59..f0ec72b 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -32,6 +32,7 @@
 extern void jfs_free_zero_link(struct inode *);
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
 extern void jfs_get_inode_flags(struct jfs_inode_info *);
+extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp);
 extern void jfs_set_inode_flags(struct inode *);
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 25161c4..932797b 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1477,6 +1477,38 @@
 	return dentry;
 }
 
+struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *jfs_get_parent(struct dentry *dentry)
 {
 	struct super_block *sb = dentry->d_inode->i_sb;
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 20e4ac1..929fcec 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -27,6 +27,7 @@
 #include <linux/kthread.h>
 #include <linux/posix_acl.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
 
@@ -737,6 +738,7 @@
 };
 
 static struct export_operations jfs_export_operations = {
+	.get_dentry	= jfs_get_dentry,
 	.get_parent	= jfs_get_parent,
 };
 
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 2680932..82e2192 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -25,6 +25,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/stats.h>
@@ -75,18 +76,31 @@
 
 static struct ctl_table_header * nlm_sysctl_table;
 
-static unsigned long set_grace_period(void)
+static unsigned long get_lockd_grace_period(void)
 {
-	unsigned long grace_period;
-
 	/* Note: nlm_timeout should always be nonzero */
 	if (nlm_grace_period)
-		grace_period = ((nlm_grace_period + nlm_timeout - 1)
-				/ nlm_timeout) * nlm_timeout * HZ;
+		return roundup(nlm_grace_period, nlm_timeout) * HZ;
 	else
-		grace_period = nlm_timeout * 5 * HZ;
+		return nlm_timeout * 5 * HZ;
+}
+
+unsigned long get_nfs_grace_period(void)
+{
+	unsigned long lockdgrace = get_lockd_grace_period();
+	unsigned long nfsdgrace = 0;
+
+	if (nlmsvc_ops)
+		nfsdgrace = nlmsvc_ops->get_grace_period();
+
+	return max(lockdgrace, nfsdgrace);
+}
+EXPORT_SYMBOL(get_nfs_grace_period);
+
+static unsigned long set_grace_period(void)
+{
 	nlmsvc_grace_period = 1;
-	return grace_period + jiffies;
+	return get_nfs_grace_period() + jiffies;
 }
 
 static inline void clear_grace_period(void)
@@ -119,6 +133,7 @@
 	complete(&lockd_start_done);
 
 	daemonize("lockd");
+	set_freezable();
 
 	/* Process request with signals blocked, but allow SIGKILL.  */
 	allow_signal(SIGKILL);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index deeb9dc..fbb1d02 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -100,7 +100,6 @@
 static LIST_HEAD(mb_cache_list);
 static LIST_HEAD(mb_cache_lru_list);
 static DEFINE_SPINLOCK(mb_cache_spinlock);
-static struct shrinker *mb_shrinker;
 
 static inline int
 mb_cache_indexes(struct mb_cache *cache)
@@ -118,6 +117,10 @@
 
 static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask);
 
+static struct shrinker mb_cache_shrinker = {
+	.shrink = mb_cache_shrink_fn,
+	.seeks = DEFAULT_SEEKS,
+};
 
 static inline int
 __mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
@@ -662,13 +665,13 @@
 
 static int __init init_mbcache(void)
 {
-	mb_shrinker = set_shrinker(DEFAULT_SEEKS, mb_cache_shrink_fn);
+	register_shrinker(&mb_cache_shrinker);
 	return 0;
 }
 
 static void __exit exit_mbcache(void)
 {
-	remove_shrinker(mb_shrinker);
+	unregister_shrinker(&mb_cache_shrinker);
 }
 
 module_init(init_mbcache)
diff --git a/fs/namespace.c b/fs/namespace.c
index b696e3a..4198003 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -28,6 +28,7 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include "pnode.h"
+#include "internal.h"
 
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
@@ -320,22 +321,16 @@
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
 	struct mnt_namespace *n = m->private;
-	struct list_head *p;
-	loff_t l = *pos;
 
 	down_read(&namespace_sem);
-	list_for_each(p, &n->list)
-		if (!l--)
-			return list_entry(p, struct vfsmount, mnt_list);
-	return NULL;
+	return seq_list_start(&n->list, *pos);
 }
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct mnt_namespace *n = m->private;
-	struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
-	(*pos)++;
-	return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
+
+	return seq_list_next(v, &n->list, pos);
 }
 
 static void m_stop(struct seq_file *m, void *v)
@@ -350,7 +345,7 @@
 
 static int show_vfsmnt(struct seq_file *m, void *v)
 {
-	struct vfsmount *mnt = v;
+	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
 	int err = 0;
 	static struct proc_fs_info {
 		int flag;
@@ -405,7 +400,7 @@
 
 static int show_vfsstat(struct seq_file *m, void *v)
 {
-	struct vfsmount *mnt = v;
+	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
 	int err = 0;
 
 	/* device */
@@ -1457,7 +1452,7 @@
 
 	new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
 	if (!new_ns)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	atomic_set(&new_ns->count, 1);
 	INIT_LIST_HEAD(&new_ns->list);
@@ -1471,7 +1466,7 @@
 	if (!new_ns->root) {
 		up_write(&namespace_sem);
 		kfree(new_ns);
-		return NULL;
+		return ERR_PTR(-ENOMEM);;
 	}
 	spin_lock(&vfsmount_lock);
 	list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
@@ -1515,7 +1510,7 @@
 	return new_ns;
 }
 
-struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns,
+struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 		struct fs_struct *new_fs)
 {
 	struct mnt_namespace *new_ns;
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index d3152f8..2b145de 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -203,7 +203,6 @@
 
 	if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
 		if (pos >= MAX_NON_LFS) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 		if (count > MAX_NON_LFS - (u32)pos) {
@@ -212,7 +211,6 @@
 	}
 	if (pos >= inode->i_sb->s_maxbytes) {
 		if (count || pos > inode->i_sb->s_maxbytes) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 	}
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 75f309c..a796be5 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,7 @@
 #include <linux/sunrpc/svcsock.h>
 #include <linux/nfs_fs.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 #include <net/inet_sock.h>
 
@@ -67,6 +68,7 @@
 	daemonize("nfsv4-svc");
 	/* Process request with signals blocked, but allow SIGKILL.  */
 	allow_signal(SIGKILL);
+	set_freezable();
 
 	complete(&nfs_callback_info.started);
 
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ccb4550..a49f9fe 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1206,23 +1206,9 @@
  */
 static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	/* lock the list against modification */
 	spin_lock(&nfs_client_lock);
-
-	/* allow for the header line */
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &nfs_client_list)
-		if (!pos--)
-			break;
-
-	return _p != &nfs_client_list ? _p : NULL;
+	return seq_list_start_head(&nfs_client_list, *_pos);
 }
 
 /*
@@ -1230,14 +1216,7 @@
  */
 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next;
-
-	return _p != &nfs_client_list ? _p : NULL;
+	return seq_list_next(v, &nfs_client_list, pos);
 }
 
 /*
@@ -1256,7 +1235,7 @@
 	struct nfs_client *clp;
 
 	/* display header on line 1 */
-	if (v == SEQ_START_TOKEN) {
+	if (v == &nfs_client_list) {
 		seq_puts(m, "NV SERVER   PORT USE HOSTNAME\n");
 		return 0;
 	}
@@ -1297,23 +1276,9 @@
  */
 static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	/* lock the list against modification */
 	spin_lock(&nfs_client_lock);
-
-	/* allow for the header line */
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &nfs_volume_list)
-		if (!pos--)
-			break;
-
-	return _p != &nfs_volume_list ? _p : NULL;
+	return seq_list_start_head(&nfs_volume_list, *_pos);
 }
 
 /*
@@ -1321,14 +1286,7 @@
  */
 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next;
-
-	return _p != &nfs_volume_list ? _p : NULL;
+	return seq_list_next(v, &nfs_volume_list, pos);
 }
 
 /*
@@ -1349,7 +1307,7 @@
 	char dev[8], fsid[17];
 
 	/* display header on line 1 */
-	if (v == SEQ_START_TOKEN) {
+	if (v == &nfs_volume_list) {
 		seq_puts(m, "NV SERVER   PORT DEV     FSID\n");
 		return 0;
 	}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a2b1af8..adffe16 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -300,7 +300,10 @@
 };
 #endif
 
-static struct shrinker *acl_shrinker;
+static struct shrinker acl_shrinker = {
+	.shrink		= nfs_access_cache_shrinker,
+	.seeks		= DEFAULT_SEEKS,
+};
 
 /*
  * Register the NFS filesystems
@@ -321,7 +324,7 @@
 	if (ret < 0)
 		goto error_2;
 #endif
-	acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
+	register_shrinker(&acl_shrinker);
 	return 0;
 
 #ifdef CONFIG_NFS_V4
@@ -339,8 +342,7 @@
  */
 void __exit unregister_nfs_fs(void)
 {
-	if (acl_shrinker != NULL)
-		remove_shrinker(acl_shrinker);
+	unregister_shrinker(&acl_shrinker);
 #ifdef CONFIG_NFS_V4
 	unregister_filesystem(&nfs4_fs_type);
 	nfs_unregister_sysctl();
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 6e92b0f..cf61dc8 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -12,17 +12,31 @@
 
 #define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
 
+static int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (f->pseudoflavor == rqstp->rq_flavor)
+			return f->flags;
+	}
+	return exp->ex_flags;
+
+}
+
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
 	struct svc_cred	cred = rqstp->rq_cred;
 	int i;
+	int flags = nfsexp_flags(rqstp, exp);
 	int ret;
 
-	if (exp->ex_flags & NFSEXP_ALLSQUASH) {
+	if (flags & NFSEXP_ALLSQUASH) {
 		cred.cr_uid = exp->ex_anon_uid;
 		cred.cr_gid = exp->ex_anon_gid;
 		cred.cr_group_info = groups_alloc(0);
-	} else if (exp->ex_flags & NFSEXP_ROOTSQUASH) {
+	} else if (flags & NFSEXP_ROOTSQUASH) {
 		struct group_info *gi;
 		if (!cred.cr_uid)
 			cred.cr_uid = exp->ex_anon_uid;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 79bd03b..c7bbf46 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -26,12 +26,15 @@
 #include <linux/mount.h>
 #include <linux/hash.h>
 #include <linux/module.h>
+#include <linux/exportfs.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/nfsfh.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/lockd/bind.h>
+#include <linux/sunrpc/msg_prot.h>
+#include <linux/sunrpc/gss_api.h>
 
 #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
 
@@ -451,8 +454,48 @@
 	return err;
 }
 
+static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
+{
+	int listsize, err;
+	struct exp_flavor_info *f;
+
+	err = get_int(mesg, &listsize);
+	if (err)
+		return err;
+	if (listsize < 0 || listsize > MAX_SECINFO_LIST)
+		return -EINVAL;
+
+	for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
+		err = get_int(mesg, &f->pseudoflavor);
+		if (err)
+			return err;
+		/*
+		 * Just a quick sanity check; we could also try to check
+		 * whether this pseudoflavor is supported, but at worst
+		 * an unsupported pseudoflavor on the export would just
+		 * be a pseudoflavor that won't match the flavor of any
+		 * authenticated request.  The administrator will
+		 * probably discover the problem when someone fails to
+		 * authenticate.
+		 */
+		if (f->pseudoflavor < 0)
+			return -EINVAL;
+		err = get_int(mesg, &f->flags);
+		if (err)
+			return err;
+		/* Only some flags are allowed to differ between flavors: */
+		if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
+			return -EINVAL;
+	}
+	exp->ex_nflavors = listsize;
+	return 0;
+}
+
 #else /* CONFIG_NFSD_V4 */
-static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
+static inline int
+fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
+static inline int
+secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
 #endif
 
 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
@@ -476,6 +519,9 @@
 
 	exp.ex_uuid = NULL;
 
+	/* secinfo */
+	exp.ex_nflavors = 0;
+
 	if (mesg[mlen-1] != '\n')
 		return -EINVAL;
 	mesg[mlen-1] = 0;
@@ -553,7 +599,9 @@
 					if (exp.ex_uuid == NULL)
 						err = -ENOMEM;
 				}
-			} else
+			} else if (strcmp(buf, "secinfo") == 0)
+				err = secinfo_parse(&mesg, buf, &exp);
+			else
 				/* quietly ignore unknown words and anything
 				 * following. Newer user-space can try to set
 				 * new values, then see what the result was.
@@ -593,6 +641,7 @@
 
 static void exp_flags(struct seq_file *m, int flag, int fsid,
 		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs);
+static void show_secinfo(struct seq_file *m, struct svc_export *exp);
 
 static int svc_export_show(struct seq_file *m,
 			   struct cache_detail *cd,
@@ -622,6 +671,7 @@
 				seq_printf(m, "%02x", exp->ex_uuid[i]);
 			}
 		}
+		show_secinfo(m, exp);
 	}
 	seq_puts(m, ")\n");
 	return 0;
@@ -654,6 +704,7 @@
 {
 	struct svc_export *new = container_of(cnew, struct svc_export, h);
 	struct svc_export *item = container_of(citem, struct svc_export, h);
+	int i;
 
 	new->ex_flags = item->ex_flags;
 	new->ex_anon_uid = item->ex_anon_uid;
@@ -669,6 +720,10 @@
 	item->ex_fslocs.locations_count = 0;
 	new->ex_fslocs.migrated = item->ex_fslocs.migrated;
 	item->ex_fslocs.migrated = 0;
+	new->ex_nflavors = item->ex_nflavors;
+	for (i = 0; i < MAX_SECINFO_LIST; i++) {
+		new->ex_flavors[i] = item->ex_flavors[i];
+	}
 }
 
 static struct cache_head *svc_export_alloc(void)
@@ -738,16 +793,18 @@
 	int err;
 	
 	if (!clp)
-		return NULL;
+		return ERR_PTR(-ENOENT);
 
 	key.ek_client = clp;
 	key.ek_fsidtype = fsid_type;
 	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
 
 	ek = svc_expkey_lookup(&key);
-	if (ek != NULL)
-		if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
-			ek = ERR_PTR(err);
+	if (ek == NULL)
+		return ERR_PTR(-ENOMEM);
+	err = cache_check(&svc_expkey_cache, &ek->h, reqp);
+	if (err)
+		return ERR_PTR(err);
 	return ek;
 }
 
@@ -808,30 +865,21 @@
 		struct cache_req *reqp)
 {
 	struct svc_export *exp, key;
+	int err;
 	
 	if (!clp)
-		return NULL;
+		return ERR_PTR(-ENOENT);
 
 	key.ex_client = clp;
 	key.ex_mnt = mnt;
 	key.ex_dentry = dentry;
 
 	exp = svc_export_lookup(&key);
-	if (exp != NULL)  {
-		int err;
-
-		err = cache_check(&svc_export_cache, &exp->h, reqp);
-		switch (err) {
-		case 0: break;
-		case -EAGAIN:
-		case -ETIMEDOUT:
-			exp = ERR_PTR(err);
-			break;
-		default:
-			exp = NULL;
-		}
-	}
-
+	if (exp == NULL)
+		return ERR_PTR(-ENOMEM);
+	err = cache_check(&svc_export_cache, &exp->h, reqp);
+	if (err)
+		return ERR_PTR(err);
 	return exp;
 }
 
@@ -847,7 +895,7 @@
 	dget(dentry);
 	exp = exp_get_by_name(clp, mnt, dentry, reqp);
 
-	while (exp == NULL && !IS_ROOT(dentry)) {
+	while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
 		struct dentry *parent;
 
 		parent = dget_parent(dentry);
@@ -900,7 +948,7 @@
 		return;
 
 	ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
-	if (ek && !IS_ERR(ek)) {
+	if (!IS_ERR(ek)) {
 		ek->h.expiry_time = get_seconds()-1;
 		cache_put(&ek->h, &svc_expkey_cache);
 	}
@@ -938,7 +986,7 @@
 	struct inode *inode = exp->ex_dentry->d_inode;
 
 	ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
-	if (ek && !IS_ERR(ek)) {
+	if (!IS_ERR(ek)) {
 		ek->h.expiry_time = get_seconds()-1;
 		cache_put(&ek->h, &svc_expkey_cache);
 	}
@@ -989,13 +1037,12 @@
 
 	/* must make sure there won't be an ex_fsid clash */
 	if ((nxp->ex_flags & NFSEXP_FSID) &&
-	    (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
-	    !IS_ERR(fsid_key) &&
+	    (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
 	    fsid_key->ek_mnt &&
 	    (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
 		goto finish;
 
-	if (exp) {
+	if (!IS_ERR(exp)) {
 		/* just a flags/id/fsid update */
 
 		exp_fsid_unhash(exp);
@@ -1104,7 +1151,7 @@
 	err = -EINVAL;
 	exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
 	path_release(&nd);
-	if (!exp)
+	if (IS_ERR(exp))
 		goto out_domain;
 
 	exp_do_unexport(exp);
@@ -1149,10 +1196,6 @@
 		err = PTR_ERR(exp);
 		goto out;
 	}
-	if (!exp) {
-		dprintk("nfsd: exp_rootfh export not found.\n");
-		goto out;
-	}
 
 	/*
 	 * fh must be initialized before calling fh_compose
@@ -1176,17 +1219,130 @@
 {
 	struct svc_export *exp;
 	struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
-	if (!ek || IS_ERR(ek))
+	if (IS_ERR(ek))
 		return ERR_PTR(PTR_ERR(ek));
 
 	exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
 	cache_put(&ek->h, &svc_expkey_cache);
 
-	if (!exp || IS_ERR(exp))
+	if (IS_ERR(exp))
 		return ERR_PTR(PTR_ERR(exp));
 	return exp;
 }
 
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+	/* legacy gss-only clients are always OK: */
+	if (exp->ex_client == rqstp->rq_gssclient)
+		return 0;
+	/* ip-address based client; check sec= export option: */
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (f->pseudoflavor == rqstp->rq_flavor)
+			return 0;
+	}
+	/* defaults in absence of sec= options: */
+	if (exp->ex_nflavors == 0) {
+		if (rqstp->rq_flavor == RPC_AUTH_NULL ||
+		    rqstp->rq_flavor == RPC_AUTH_UNIX)
+			return 0;
+	}
+	return nfserr_wrongsec;
+}
+
+/*
+ * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
+ * auth_unix client) if it's available and has secinfo information;
+ * otherwise, will try to use rq_gssclient.
+ *
+ * Called from functions that handle requests; functions that do work on
+ * behalf of mountd are passed a single client name to use, and should
+ * use exp_get_by_name() or exp_find().
+ */
+struct svc_export *
+rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+		struct dentry *dentry)
+{
+	struct svc_export *gssexp, *exp = NULL;
+
+	if (rqstp->rq_client == NULL)
+		goto gss;
+
+	/* First try the auth_unix client: */
+	exp = exp_get_by_name(rqstp->rq_client, mnt, dentry,
+						&rqstp->rq_chandle);
+	if (PTR_ERR(exp) == -ENOENT)
+		goto gss;
+	if (IS_ERR(exp))
+		return exp;
+	/* If it has secinfo, assume there are no gss/... clients */
+	if (exp->ex_nflavors > 0)
+		return exp;
+gss:
+	/* Otherwise, try falling back on gss client */
+	if (rqstp->rq_gssclient == NULL)
+		return exp;
+	gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry,
+						&rqstp->rq_chandle);
+	if (PTR_ERR(gssexp) == -ENOENT)
+		return exp;
+	if (exp && !IS_ERR(exp))
+		exp_put(exp);
+	return gssexp;
+}
+
+struct svc_export *
+rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+{
+	struct svc_export *gssexp, *exp = NULL;
+
+	if (rqstp->rq_client == NULL)
+		goto gss;
+
+	/* First try the auth_unix client: */
+	exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle);
+	if (PTR_ERR(exp) == -ENOENT)
+		goto gss;
+	if (IS_ERR(exp))
+		return exp;
+	/* If it has secinfo, assume there are no gss/... clients */
+	if (exp->ex_nflavors > 0)
+		return exp;
+gss:
+	/* Otherwise, try falling back on gss client */
+	if (rqstp->rq_gssclient == NULL)
+		return exp;
+	gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv,
+						&rqstp->rq_chandle);
+	if (PTR_ERR(gssexp) == -ENOENT)
+		return exp;
+	if (exp && !IS_ERR(exp))
+		exp_put(exp);
+	return gssexp;
+}
+
+struct svc_export *
+rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
+		struct dentry *dentry)
+{
+	struct svc_export *exp;
+
+	dget(dentry);
+	exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
+
+	while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
+		struct dentry *parent;
+
+		parent = dget_parent(dentry);
+		dput(dentry);
+		dentry = parent;
+		exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
+	}
+	dput(dentry);
+	return exp;
+}
 
 /*
  * Called when we need the filehandle for the root of the pseudofs,
@@ -1194,8 +1350,7 @@
  * export point with fsid==0
  */
 __be32
-exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
-	       struct cache_req *creq)
+exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
 {
 	struct svc_export *exp;
 	__be32 rv;
@@ -1203,12 +1358,16 @@
 
 	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
 
-	exp = exp_find(clp, FSID_NUM, fsidv, creq);
+	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+	if (PTR_ERR(exp) == -ENOENT)
+		return nfserr_perm;
 	if (IS_ERR(exp))
 		return nfserrno(PTR_ERR(exp));
-	if (exp == NULL)
-		return nfserr_perm;
 	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
+	if (rv)
+		goto out;
+	rv = check_nfsd_access(exp, rqstp);
+out:
 	exp_put(exp);
 	return rv;
 }
@@ -1296,28 +1455,62 @@
 	{ 0, {"", ""}}
 };
 
-static void exp_flags(struct seq_file *m, int flag, int fsid,
-		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
+static void show_expflags(struct seq_file *m, int flags, int mask)
 {
-	int first = 0;
 	struct flags *flg;
+	int state, first = 0;
 
 	for (flg = expflags; flg->flag; flg++) {
-		int state = (flg->flag & flag)?0:1;
+		if (flg->flag & ~mask)
+			continue;
+		state = (flg->flag & flags) ? 0 : 1;
 		if (*flg->name[state])
 			seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
 	}
+}
+
+static void show_secinfo_flags(struct seq_file *m, int flags)
+{
+	seq_printf(m, ",");
+	show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
+}
+
+static void show_secinfo(struct seq_file *m, struct svc_export *exp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+	int lastflags = 0, first = 0;
+
+	if (exp->ex_nflavors == 0)
+		return;
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (first || f->flags != lastflags) {
+			if (!first)
+				show_secinfo_flags(m, lastflags);
+			seq_printf(m, ",sec=%d", f->pseudoflavor);
+			lastflags = f->flags;
+		} else {
+			seq_printf(m, ":%d", f->pseudoflavor);
+		}
+	}
+	show_secinfo_flags(m, lastflags);
+}
+
+static void exp_flags(struct seq_file *m, int flag, int fsid,
+		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
+{
+	show_expflags(m, flag, NFSEXP_ALLFLAGS);
 	if (flag & NFSEXP_FSID)
-		seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
+		seq_printf(m, ",fsid=%d", fsid);
 	if (anonu != (uid_t)-2 && anonu != (0x10000-2))
-		seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
+		seq_printf(m, ",sanonuid=%d", anonu);
 	if (anong != (gid_t)-2 && anong != (0x10000-2))
-		seq_printf(m, "%sanongid=%d", first++?",":"", anong);
+		seq_printf(m, ",sanongid=%d", anong);
 	if (fsloc && fsloc->locations_count > 0) {
 		char *loctype = (fsloc->migrated) ? "refer" : "replicas";
 		int i;
 
-		seq_printf(m, "%s%s=", first++?",":"", loctype);
+		seq_printf(m, ",%s=", loctype);
 		seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
 		seq_putc(m, '@');
 		seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 221acd1..9e4a568 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -65,6 +65,7 @@
 static struct nlmsvc_binding	nfsd_nlm_ops = {
 	.fopen		= nlm_fopen,		/* open file for locking */
 	.fclose		= nlm_fclose,		/* close file */
+	.get_grace_period = get_nfs4_grace_period,
 };
 
 void
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index cc3b7ba..b6ed383 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -183,8 +183,13 @@
 summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
 {
 	struct posix_acl_entry *pa, *pe;
-	pas->users = 0;
-	pas->groups = 0;
+
+	/*
+	 * Only pas.users and pas.groups need initialization; previous
+	 * posix_acl_valid() calls ensure that the other fields will be
+	 * initialized in the following loop.  But, just to placate gcc:
+	 */
+	memset(pas, 0, sizeof(*pas));
 	pas->mask = 07;
 
 	pe = acl->a_entries + acl->a_count;
@@ -732,13 +737,16 @@
 	*pacl = posix_state_to_acl(&effective_acl_state, flags);
 	if (IS_ERR(*pacl)) {
 		ret = PTR_ERR(*pacl);
+		*pacl = NULL;
 		goto out_dstate;
 	}
 	*dpacl = posix_state_to_acl(&default_acl_state,
 						flags | NFS4_ACL_TYPE_DEFAULT);
 	if (IS_ERR(*dpacl)) {
 		ret = PTR_ERR(*dpacl);
+		*dpacl = NULL;
 		posix_acl_release(*pacl);
+		*pacl = NULL;
 		goto out_dstate;
 	}
 	sort_pacl(*pacl);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 5443c52..31d6633 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -75,7 +75,7 @@
 #define op_enc_sz			1
 #define op_dec_sz			2
 #define enc_nfs4_fh_sz			(1 + (NFS4_FHSIZE >> 2))
-#define enc_stateid_sz			16
+#define enc_stateid_sz			(NFS4_STATEID_SIZE >> 2)
 #define NFS4_enc_cb_recall_sz		(cb_compound_enc_hdr_sz +       \
 					1 + enc_stateid_sz +            \
 					enc_nfs4_fh_sz)
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 45aa21c..2cf9a9a 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -587,6 +587,15 @@
 	return ret;
 }
 
+static char *
+rqst_authname(struct svc_rqst *rqstp)
+{
+	struct auth_domain *clp;
+
+	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+	return clp->name;
+}
+
 static int
 idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
 		uid_t *id)
@@ -600,7 +609,7 @@
 		return -EINVAL;
 	memcpy(key.name, name, namelen);
 	key.name[namelen] = '\0';
-	strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
 	ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
 	if (ret == -ENOENT)
 		ret = -ESRCH; /* nfserr_badname */
@@ -620,7 +629,7 @@
 	};
 	int ret;
 
-	strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
 	ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
 	if (ret == -ENOENT)
 		return sprintf(name, "%u", id);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 8522729..3c62712 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -47,6 +47,7 @@
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 #include <linux/nfs4_acl.h>
+#include <linux/sunrpc/gss_api.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
@@ -286,8 +287,7 @@
 	__be32 status;
 
 	fh_put(&cstate->current_fh);
-	status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
-			      &rqstp->rq_chandle);
+	status = exp_pseudoroot(rqstp, &cstate->current_fh);
 	return status;
 }
 
@@ -474,8 +474,8 @@
 	__be32 ret;
 
 	fh_init(&tmp_fh, NFS4_FHSIZE);
-	if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
-			      &rqstp->rq_chandle)) != 0)
+	ret = exp_pseudoroot(rqstp, &tmp_fh);
+	if (ret)
 		return ret;
 	if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
 		fh_put(&tmp_fh);
@@ -611,6 +611,30 @@
 }
 
 static __be32
+nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_secinfo *secinfo)
+{
+	struct svc_fh resfh;
+	struct svc_export *exp;
+	struct dentry *dentry;
+	__be32 err;
+
+	fh_init(&resfh, NFS4_FHSIZE);
+	err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
+				    secinfo->si_name, secinfo->si_namelen,
+				    &exp, &dentry);
+	if (err)
+		return err;
+	if (dentry->d_inode == NULL) {
+		exp_put(exp);
+		err = nfserr_noent;
+	} else
+		secinfo->si_exp = exp;
+	dput(dentry);
+	return err;
+}
+
+static __be32
 nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	      struct nfsd4_setattr *setattr)
 {
@@ -1009,6 +1033,9 @@
 	[OP_SAVEFH] = {
 		.op_func = (nfsd4op_func)nfsd4_savefh,
 	},
+	[OP_SECINFO] = {
+		.op_func = (nfsd4op_func)nfsd4_secinfo,
+	},
 	[OP_SETATTR] = {
 		.op_func = (nfsd4op_func)nfsd4_setattr,
 	},
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 8c52913..e4a4c87 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -49,8 +49,10 @@
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 #include <linux/namei.h>
+#include <linux/swap.h>
 #include <linux/mutex.h>
 #include <linux/lockd/bind.h>
+#include <linux/module.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -149,6 +151,7 @@
 }
 
 static int num_delegations;
+unsigned int max_delegations;
 
 /*
  * Open owner state (share locks)
@@ -192,7 +195,9 @@
 	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
 
 	dprintk("NFSD alloc_init_deleg\n");
-	if (num_delegations > STATEID_HASH_SIZE * 4)
+	if (fp->fi_had_conflict)
+		return NULL;
+	if (num_delegations > max_delegations)
 		return NULL;
 	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
 	if (dp == NULL)
@@ -999,6 +1004,7 @@
 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
 		fp->fi_inode = igrab(ino);
 		fp->fi_id = current_fileid++;
+		fp->fi_had_conflict = false;
 		return fp;
 	}
 	return NULL;
@@ -1325,6 +1331,7 @@
 {
 	struct nfs4_delegation *dp = __dp;
 
+	dp->dl_file->fi_had_conflict = true;
 	nfsd4_cb_recall(dp);
 	return 0;
 }
@@ -3190,20 +3197,49 @@
 		printk("NFSD: Failure reading reboot recovery data\n");
 }
 
+unsigned long
+get_nfs4_grace_period(void)
+{
+	return max(user_lease_time, lease_time) * HZ;
+}
+
+/*
+ * Since the lifetime of a delegation isn't limited to that of an open, a
+ * client may quite reasonably hang on to a delegation as long as it has
+ * the inode cached.  This becomes an obvious problem the first time a
+ * client's inode cache approaches the size of the server's total memory.
+ *
+ * For now we avoid this problem by imposing a hard limit on the number
+ * of delegations, which varies according to the server's memory size.
+ */
+static void
+set_max_delegations(void)
+{
+	/*
+	 * Allow at most 4 delegations per megabyte of RAM.  Quick
+	 * estimates suggest that in the worst case (where every delegation
+	 * is for a different inode), a delegation could take about 1.5K,
+	 * giving a worst case usage of about 6% of memory.
+	 */
+	max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
+}
+
 /* initialization to perform when the nfsd service is started: */
 
 static void
 __nfs4_state_start(void)
 {
-	time_t grace_time;
+	unsigned long grace_time;
 
 	boot_time = get_seconds();
-	grace_time = max(user_lease_time, lease_time);
+	grace_time = get_nfs_grace_period();
 	lease_time = user_lease_time;
 	in_grace = 1;
-	printk("NFSD: starting %ld-second grace period\n", grace_time);
+	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+	       grace_time/HZ);
 	laundry_wq = create_singlethread_workqueue("nfsd4");
-	queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
+	queue_delayed_work(laundry_wq, &laundromat_work, grace_time);
+	set_max_delegations();
 }
 
 int
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 15809df..b3d55c6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -56,6 +56,8 @@
 #include <linux/nfsd_idmap.h>
 #include <linux/nfs4.h>
 #include <linux/nfs4_acl.h>
+#include <linux/sunrpc/gss_api.h>
+#include <linux/sunrpc/svcauth_gss.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
@@ -819,6 +821,23 @@
 }
 
 static __be32
+nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
+		     struct nfsd4_secinfo *secinfo)
+{
+	DECODE_HEAD;
+
+	READ_BUF(4);
+	READ32(secinfo->si_namelen);
+	READ_BUF(secinfo->si_namelen);
+	SAVEMEM(secinfo->si_name, secinfo->si_namelen);
+	status = check_filename(secinfo->si_name, secinfo->si_namelen,
+								nfserr_noent);
+	if (status)
+		return status;
+	DECODE_TAIL;
+}
+
+static __be32
 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
 {
 	DECODE_HEAD;
@@ -1131,6 +1150,9 @@
 		case OP_SAVEFH:
 			op->status = nfs_ok;
 			break;
+		case OP_SECINFO:
+			op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
+			break;
 		case OP_SETATTR:
 			op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
 			break;
@@ -1296,7 +1318,7 @@
 	char *path, *rootpath;
 
 	fh_init(&tmp_fh, NFS4_FHSIZE);
-	*stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
+	*stat = exp_pseudoroot(rqstp, &tmp_fh);
 	if (*stat)
 		return NULL;
 	rootpath = tmp_fh.fh_export->ex_path;
@@ -1847,11 +1869,19 @@
 	if (d_mountpoint(dentry)) {
 		int err;
 
+		/*
+		 * Why the heck aren't we just using nfsd_lookup??
+		 * Different "."/".." handling?  Something else?
+		 * At least, add a comment here to explain....
+		 */
 		err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
 		if (err) {
 			nfserr = nfserrno(err);
 			goto out_put;
 		}
+		nfserr = check_nfsd_access(exp, cd->rd_rqstp);
+		if (nfserr)
+			goto out_put;
 
 	}
 	nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
@@ -2419,6 +2449,72 @@
 	}
 }
 
+static void
+nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr,
+		     struct nfsd4_secinfo *secinfo)
+{
+	int i = 0;
+	struct svc_export *exp = secinfo->si_exp;
+	u32 nflavs;
+	struct exp_flavor_info *flavs;
+	struct exp_flavor_info def_flavs[2];
+	ENCODE_HEAD;
+
+	if (nfserr)
+		goto out;
+	if (exp->ex_nflavors) {
+		flavs = exp->ex_flavors;
+		nflavs = exp->ex_nflavors;
+	} else { /* Handling of some defaults in absence of real secinfo: */
+		flavs = def_flavs;
+		if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
+			nflavs = 2;
+			flavs[0].pseudoflavor = RPC_AUTH_UNIX;
+			flavs[1].pseudoflavor = RPC_AUTH_NULL;
+		} else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
+			nflavs = 1;
+			flavs[0].pseudoflavor
+					= svcauth_gss_flavor(exp->ex_client);
+		} else {
+			nflavs = 1;
+			flavs[0].pseudoflavor
+					= exp->ex_client->flavour->flavour;
+		}
+	}
+
+	RESERVE_SPACE(4);
+	WRITE32(nflavs);
+	ADJUST_ARGS();
+	for (i = 0; i < nflavs; i++) {
+		u32 flav = flavs[i].pseudoflavor;
+		struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
+
+		if (gm) {
+			RESERVE_SPACE(4);
+			WRITE32(RPC_AUTH_GSS);
+			ADJUST_ARGS();
+			RESERVE_SPACE(4 + gm->gm_oid.len);
+			WRITE32(gm->gm_oid.len);
+			WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
+			ADJUST_ARGS();
+			RESERVE_SPACE(4);
+			WRITE32(0); /* qop */
+			ADJUST_ARGS();
+			RESERVE_SPACE(4);
+			WRITE32(gss_pseudoflavor_to_service(gm, flav));
+			ADJUST_ARGS();
+			gss_mech_put(gm);
+		} else {
+			RESERVE_SPACE(4);
+			WRITE32(flav);
+			ADJUST_ARGS();
+		}
+	}
+out:
+	if (exp)
+		exp_put(exp);
+}
+
 /*
  * The SETATTR encode routine is special -- it always encodes a bitmap,
  * regardless of the error status.
@@ -2559,6 +2655,9 @@
 		break;
 	case OP_SAVEFH:
 		break;
+	case OP_SECINFO:
+		nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo);
+		break;
 	case OP_SETATTR:
 		nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
 		break;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 71c686d..baac89d 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -35,7 +35,6 @@
 #include <linux/nfsd/cache.h>
 #include <linux/nfsd/xdr.h>
 #include <linux/nfsd/syscall.h>
-#include <linux/nfsd/interface.h>
 
 #include <asm/uaccess.h>
 
@@ -245,7 +244,7 @@
 	}
 	exp_readunlock();
 	if (err == 0)
-		err = res->fh_size + (int)&((struct knfsd_fh*)0)->fh_base;
+		err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
  out:
 	return err;
 }
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 6ca2d24..0eb464a 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -15,10 +15,12 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/dcache.h>
+#include <linux/exportfs.h>
 #include <linux/mount.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
+#include <linux/sunrpc/svcauth_gss.h>
 #include <linux/nfsd/nfsd.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_FH
@@ -27,10 +29,6 @@
 static int nfsd_nr_verified;
 static int nfsd_nr_put;
 
-extern struct export_operations export_op_default;
-
-#define	CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-
 /*
  * our acceptability function.
  * if NOSUBTREECHECK, accept anything
@@ -123,8 +121,6 @@
 		int data_left = fh->fh_size/4;
 
 		error = nfserr_stale;
-		if (rqstp->rq_client == NULL)
-			goto out;
 		if (rqstp->rq_vers > 2)
 			error = nfserr_badhandle;
 		if (rqstp->rq_vers == 4 && fh->fh_size == 0)
@@ -148,7 +144,7 @@
 				fh->fh_fsid[1] = fh->fh_fsid[2];
 			}
 			if ((data_left -= len)<0) goto out;
-			exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap, &rqstp->rq_chandle);
+			exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap);
 			datap += len;
 		} else {
 			dev_t xdev;
@@ -159,20 +155,18 @@
 			xdev = old_decode_dev(fh->ofh_xdev);
 			xino = u32_to_ino_t(fh->ofh_xino);
 			mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
-			exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
-				       &rqstp->rq_chandle);
+			exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
 		}
 
-		if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
-				|| PTR_ERR(exp) == -ETIMEDOUT)) {
+		error = nfserr_stale;
+		if (PTR_ERR(exp) == -ENOENT)
+			goto out;
+
+		if (IS_ERR(exp)) {
 			error = nfserrno(PTR_ERR(exp));
 			goto out;
 		}
 
-		error = nfserr_stale; 
-		if (!exp || IS_ERR(exp))
-			goto out;
-
 		/* Check if the request originated from a secure port. */
 		error = nfserr_perm;
 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
@@ -211,11 +205,9 @@
 		if (fileid_type == 0)
 			dentry = dget(exp->ex_dentry);
 		else {
-			struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-			dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
-						     datap, data_left,
-						     fileid_type,
-						     nfsd_acceptable, exp);
+			dentry = exportfs_decode_fh(exp->ex_mnt, datap,
+					data_left, fileid_type,
+					nfsd_acceptable, exp);
 		}
 		if (dentry == NULL)
 			goto out;
@@ -257,8 +249,19 @@
 	if (error)
 		goto out;
 
+	if (!(access & MAY_LOCK)) {
+		/*
+		 * pseudoflavor restrictions are not enforced on NLM,
+		 * which clients virtually always use auth_sys for,
+		 * even while using RPCSEC_GSS for NFS.
+		 */
+		error = check_nfsd_access(exp, rqstp);
+		if (error)
+			goto out;
+	}
+
 	/* Finally, check access permissions. */
-	error = nfsd_permission(exp, dentry, access);
+	error = nfsd_permission(rqstp, exp, dentry, access);
 
 	if (error) {
 		dprintk("fh_verify: %s/%s permission failure, "
@@ -286,15 +289,13 @@
 static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
 			     __u32 *datap, int *maxsize)
 {
-	struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-
 	if (dentry == exp->ex_dentry) {
 		*maxsize = 0;
 		return 0;
 	}
 
-	return CALL(nop,encode_fh)(dentry, datap, maxsize,
-			  !(exp->ex_flags&NFSEXP_NOSUBTREECHECK));
+	return exportfs_encode_fh(dentry, datap, maxsize,
+			  !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
 }
 
 /*
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index b2c7147..977a71f 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -278,7 +278,8 @@
 					 *   echo thing > device-special-file-or-pipe
 					 * by doing a CREATE with type==0
 					 */
-					nfserr = nfsd_permission(newfhp->fh_export,
+					nfserr = nfsd_permission(rqstp,
+								 newfhp->fh_export,
 								 newfhp->fh_dentry,
 								 MAY_WRITE|MAY_LOCAL_ACCESS);
 					if (nfserr && nfserr != nfserr_rofs)
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ff55950..a8c89ae 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/freezer.h>
 #include <linux/fs_struct.h>
 
 #include <linux/sunrpc/types.h>
@@ -432,6 +433,7 @@
 	 * dirty pages.
 	 */
 	current->flags |= PF_LESS_THROTTLE;
+	set_freezable();
 
 	/*
 	 * The main request loop
@@ -492,6 +494,15 @@
 	module_put_and_exit(0);
 }
 
+static __be32 map_new_errors(u32 vers, __be32 nfserr)
+{
+	if (nfserr == nfserr_jukebox && vers == 2)
+		return nfserr_dropit;
+	if (nfserr == nfserr_wrongsec && vers < 4)
+		return nfserr_acces;
+	return nfserr;
+}
+
 int
 nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
@@ -534,6 +545,7 @@
 
 	/* Now call the procedure handler, and encode NFS status. */
 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
+	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
 	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
 		nfserr = nfserr_dropit;
 	if (nfserr == nfserr_dropit) {
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 945b1ce..e90f4a8 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -113,7 +113,7 @@
 
 	while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
 
-	exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle);
+	exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts);
 	if (IS_ERR(exp2)) {
 		err = PTR_ERR(exp2);
 		dput(mounts);
@@ -135,21 +135,10 @@
 	return err;
 }
 
-/*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
- *
- * If the lookup would cross a mountpoint, and the mounted filesystem
- * is exported to the client with NFSEXP_NOHIDE, then the lookup is
- * accepted as it stands and the mounted directory is
- * returned. Otherwise the covered directory is returned.
- * NOTE: this mountpoint crossing is not supported properly by all
- *   clients and is explicitly disallowed for NFSv3
- *      NeilBrown <neilb@cse.unsw.edu.au>
- */
 __be32
-nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
-					int len, struct svc_fh *resfh)
+nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+		   const char *name, int len,
+		   struct svc_export **exp_ret, struct dentry **dentry_ret)
 {
 	struct svc_export	*exp;
 	struct dentry		*dparent;
@@ -168,8 +157,6 @@
 	exp  = fhp->fh_export;
 	exp_get(exp);
 
-	err = nfserr_acces;
-
 	/* Lookup the name, but don't follow links */
 	if (isdotent(name, len)) {
 		if (len==1)
@@ -190,17 +177,15 @@
 			dput(dentry);
 			dentry = dp;
 
-			exp2 = exp_parent(exp->ex_client, mnt, dentry,
-					  &rqstp->rq_chandle);
-			if (IS_ERR(exp2)) {
+			exp2 = rqst_exp_parent(rqstp, mnt, dentry);
+			if (PTR_ERR(exp2) == -ENOENT) {
+				dput(dentry);
+				dentry = dget(dparent);
+			} else if (IS_ERR(exp2)) {
 				host_err = PTR_ERR(exp2);
 				dput(dentry);
 				mntput(mnt);
 				goto out_nfserr;
-			}
-			if (!exp2) {
-				dput(dentry);
-				dentry = dget(dparent);
 			} else {
 				exp_put(exp);
 				exp = exp2;
@@ -223,6 +208,41 @@
 			}
 		}
 	}
+	*dentry_ret = dentry;
+	*exp_ret = exp;
+	return 0;
+
+out_nfserr:
+	exp_put(exp);
+	return nfserrno(host_err);
+}
+
+/*
+ * Look up one component of a pathname.
+ * N.B. After this call _both_ fhp and resfh need an fh_put
+ *
+ * If the lookup would cross a mountpoint, and the mounted filesystem
+ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
+ * accepted as it stands and the mounted directory is
+ * returned. Otherwise the covered directory is returned.
+ * NOTE: this mountpoint crossing is not supported properly by all
+ *   clients and is explicitly disallowed for NFSv3
+ *      NeilBrown <neilb@cse.unsw.edu.au>
+ */
+__be32
+nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+					int len, struct svc_fh *resfh)
+{
+	struct svc_export	*exp;
+	struct dentry		*dentry;
+	__be32 err;
+
+	err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
+	if (err)
+		return err;
+	err = check_nfsd_access(exp, rqstp);
+	if (err)
+		goto out;
 	/*
 	 * Note: we compose the file handle now, but as the
 	 * dentry may be negative, it may need to be updated.
@@ -230,16 +250,13 @@
 	err = fh_compose(resfh, exp, dentry, fhp);
 	if (!err && !dentry->d_inode)
 		err = nfserr_noent;
-	dput(dentry);
 out:
+	dput(dentry);
 	exp_put(exp);
 	return err;
-
-out_nfserr:
-	err = nfserrno(host_err);
-	goto out;
 }
 
+
 /*
  * Set various file attributes.
  * N.B. After this call fhp needs an fh_put
@@ -311,7 +328,7 @@
 	/* The size case is special. It changes the file as well as the attributes.  */
 	if (iap->ia_valid & ATTR_SIZE) {
 		if (iap->ia_size < inode->i_size) {
-			err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
+			err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
 			if (err)
 				goto out;
 		}
@@ -435,7 +452,7 @@
 	/* Get inode */
 	error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR);
 	if (error)
-		goto out;
+		return error;
 
 	dentry = fhp->fh_dentry;
 	inode = dentry->d_inode;
@@ -444,33 +461,25 @@
 
 	host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
 	if (host_error == -EINVAL) {
-		error = nfserr_attrnotsupp;
-		goto out;
+		return nfserr_attrnotsupp;
 	} else if (host_error < 0)
 		goto out_nfserr;
 
 	host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
 	if (host_error < 0)
-		goto out_nfserr;
+		goto out_release;
 
-	if (S_ISDIR(inode->i_mode)) {
+	if (S_ISDIR(inode->i_mode))
 		host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
-		if (host_error < 0)
-			goto out_nfserr;
-	}
 
-	error = nfs_ok;
-
-out:
+out_release:
 	posix_acl_release(pacl);
 	posix_acl_release(dpacl);
-	return (error);
 out_nfserr:
 	if (host_error == -EOPNOTSUPP)
-		error = nfserr_attrnotsupp;
+		return nfserr_attrnotsupp;
 	else
-		error = nfserrno(host_error);
-	goto out;
+		return nfserrno(host_error);
 }
 
 static struct posix_acl *
@@ -607,7 +616,7 @@
 
 			sresult |= map->access;
 
-			err2 = nfsd_permission(export, dentry, map->how);
+			err2 = nfsd_permission(rqstp, export, dentry, map->how);
 			switch (err2) {
 			case nfs_ok:
 				result |= map->access;
@@ -1034,7 +1043,7 @@
 	__be32		err;
 
 	if (file) {
-		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+		err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
 				MAY_READ|MAY_OWNER_OVERRIDE);
 		if (err)
 			goto out;
@@ -1063,7 +1072,7 @@
 	__be32			err = 0;
 
 	if (file) {
-		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+		err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
 				MAY_WRITE|MAY_OWNER_OVERRIDE);
 		if (err)
 			goto out;
@@ -1792,7 +1801,8 @@
  * Check for a user's access permissions to this inode.
  */
 __be32
-nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
+nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+					struct dentry *dentry, int acc)
 {
 	struct inode	*inode = dentry->d_inode;
 	int		err;
@@ -1823,7 +1833,7 @@
 	 */
 	if (!(acc & MAY_LOCAL_ACCESS))
 		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
-			if (EX_RDONLY(exp) || IS_RDONLY(inode))
+			if (EX_RDONLY(exp, rqstp) || IS_RDONLY(inode))
 				return nfserr_rofs;
 			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
 				return nfserr_perm;
diff --git a/fs/nls/Makefile b/fs/nls/Makefile
index a7ade13..f499dd7 100644
--- a/fs/nls/Makefile
+++ b/fs/nls/Makefile
@@ -36,11 +36,9 @@
 obj-$(CONFIG_NLS_ISO8859_7)	+= nls_iso8859-7.o
 obj-$(CONFIG_NLS_ISO8859_8)	+= nls_cp1255.o
 obj-$(CONFIG_NLS_ISO8859_9)	+= nls_iso8859-9.o
-obj-$(CONFIG_NLS_ISO8859_10)	+= nls_iso8859-10.o
 obj-$(CONFIG_NLS_ISO8859_13)	+= nls_iso8859-13.o
 obj-$(CONFIG_NLS_ISO8859_14)	+= nls_iso8859-14.o
 obj-$(CONFIG_NLS_ISO8859_15)	+= nls_iso8859-15.o
 obj-$(CONFIG_NLS_KOI8_R)	+= nls_koi8-r.o
 obj-$(CONFIG_NLS_KOI8_U)	+= nls_koi8-u.o nls_koi8-ru.o
-obj-$(CONFIG_NLS_ABC)		+= nls_abc.o
 obj-$(CONFIG_NLS_UTF8)		+= nls_utf8.o
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index bff01a5..e93c614 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/dcache.h>
+#include <linux/exportfs.h>
 #include <linux/security.h>
 
 #include "attrib.h"
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 19712a7..f5e11f4 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -50,6 +50,8 @@
 #include "buffer_head_io.h"
 
 static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+					 struct ocfs2_extent_block *eb);
 
 /*
  * Structures which describe a path through a btree, and functions to
@@ -117,6 +119,31 @@
 }
 
 /*
+ * All the elements of src into dest. After this call, src could be freed
+ * without affecting dest.
+ *
+ * Both paths should have the same root. Any non-root elements of dest
+ * will be freed.
+ */
+static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
+{
+	int i;
+
+	BUG_ON(path_root_bh(dest) != path_root_bh(src));
+	BUG_ON(path_root_el(dest) != path_root_el(src));
+
+	ocfs2_reinit_path(dest, 1);
+
+	for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
+		dest->p_node[i].bh = src->p_node[i].bh;
+		dest->p_node[i].el = src->p_node[i].el;
+
+		if (dest->p_node[i].bh)
+			get_bh(dest->p_node[i].bh);
+	}
+}
+
+/*
  * Make the *dest path the same as src and re-initialize src path to
  * have a root only.
  */
@@ -212,10 +239,41 @@
 	return ret;
 }
 
+/*
+ * Return the index of the extent record which contains cluster #v_cluster.
+ * -1 is returned if it was not found.
+ *
+ * Should work fine on interior and exterior nodes.
+ */
+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster)
+{
+	int ret = -1;
+	int i;
+	struct ocfs2_extent_rec *rec;
+	u32 rec_end, rec_start, clusters;
+
+	for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
+		rec = &el->l_recs[i];
+
+		rec_start = le32_to_cpu(rec->e_cpos);
+		clusters = ocfs2_rec_clusters(el, rec);
+
+		rec_end = rec_start + clusters;
+
+		if (v_cluster >= rec_start && v_cluster < rec_end) {
+			ret = i;
+			break;
+		}
+	}
+
+	return ret;
+}
+
 enum ocfs2_contig_type {
 	CONTIG_NONE = 0,
 	CONTIG_LEFT,
-	CONTIG_RIGHT
+	CONTIG_RIGHT,
+	CONTIG_LEFTRIGHT,
 };
 
 
@@ -253,6 +311,14 @@
 {
 	u64 blkno = le64_to_cpu(insert_rec->e_blkno);
 
+	/*
+	 * Refuse to coalesce extent records with different flag
+	 * fields - we don't want to mix unwritten extents with user
+	 * data.
+	 */
+	if (ext->e_flags != insert_rec->e_flags)
+		return CONTIG_NONE;
+
 	if (ocfs2_extents_adjacent(ext, insert_rec) &&
 	    ocfs2_block_extent_contig(inode->i_sb, ext, blkno))
 			return CONTIG_RIGHT;
@@ -277,7 +343,14 @@
 	APPEND_TAIL,
 };
 
+enum ocfs2_split_type {
+	SPLIT_NONE = 0,
+	SPLIT_LEFT,
+	SPLIT_RIGHT,
+};
+
 struct ocfs2_insert_type {
+	enum ocfs2_split_type	ins_split;
 	enum ocfs2_append_type	ins_appending;
 	enum ocfs2_contig_type	ins_contig;
 	int			ins_contig_index;
@@ -285,6 +358,13 @@
 	int			ins_tree_depth;
 };
 
+struct ocfs2_merge_ctxt {
+	enum ocfs2_contig_type	c_contig_type;
+	int			c_has_empty_extent;
+	int			c_split_covers_rec;
+	int			c_used_tail_recs;
+};
+
 /*
  * How many free extents have we got before we need more meta data?
  */
@@ -384,13 +464,7 @@
 			strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
 			eb->h_blkno = cpu_to_le64(first_blkno);
 			eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
-
-#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
-			/* we always use slot zero's suballocator */
-			eb->h_suballoc_slot = 0;
-#else
 			eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);
-#endif
 			eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 			eb->h_list.l_count =
 				cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
@@ -461,7 +535,7 @@
 			    struct inode *inode,
 			    struct buffer_head *fe_bh,
 			    struct buffer_head *eb_bh,
-			    struct buffer_head *last_eb_bh,
+			    struct buffer_head **last_eb_bh,
 			    struct ocfs2_alloc_context *meta_ac)
 {
 	int status, new_blocks, i;
@@ -476,7 +550,7 @@
 
 	mlog_entry_void();
 
-	BUG_ON(!last_eb_bh);
+	BUG_ON(!last_eb_bh || !*last_eb_bh);
 
 	fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
@@ -507,7 +581,7 @@
 		goto bail;
 	}
 
-	eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
+	eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
 	new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
 
 	/* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
@@ -568,7 +642,7 @@
 	 * journal_dirty erroring as it won't unless we've aborted the
 	 * handle (in which case we would never be here) so reserving
 	 * the write with journal_access is all we need to do. */
-	status = ocfs2_journal_access(handle, inode, last_eb_bh,
+	status = ocfs2_journal_access(handle, inode, *last_eb_bh,
 				      OCFS2_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
 		mlog_errno(status);
@@ -601,10 +675,10 @@
 	 * next_leaf on the previously last-extent-block. */
 	fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);
 
-	eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+	eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
 	eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);
 
-	status = ocfs2_journal_dirty(handle, last_eb_bh);
+	status = ocfs2_journal_dirty(handle, *last_eb_bh);
 	if (status < 0)
 		mlog_errno(status);
 	status = ocfs2_journal_dirty(handle, fe_bh);
@@ -616,6 +690,14 @@
 			mlog_errno(status);
 	}
 
+	/*
+	 * Some callers want to track the rightmost leaf so pass it
+	 * back here.
+	 */
+	brelse(*last_eb_bh);
+	get_bh(new_eb_bhs[0]);
+	*last_eb_bh = new_eb_bhs[0];
+
 	status = 0;
 bail:
 	if (new_eb_bhs) {
@@ -829,6 +911,87 @@
 }
 
 /*
+ * Grow a b-tree so that it has more records.
+ *
+ * We might shift the tree depth in which case existing paths should
+ * be considered invalid.
+ *
+ * Tree depth after the grow is returned via *final_depth.
+ *
+ * *last_eb_bh will be updated by ocfs2_add_branch().
+ */
+static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
+			   struct buffer_head *di_bh, int *final_depth,
+			   struct buffer_head **last_eb_bh,
+			   struct ocfs2_alloc_context *meta_ac)
+{
+	int ret, shift;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+	int depth = le16_to_cpu(di->id2.i_list.l_tree_depth);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct buffer_head *bh = NULL;
+
+	BUG_ON(meta_ac == NULL);
+
+	shift = ocfs2_find_branch_target(osb, inode, di_bh, &bh);
+	if (shift < 0) {
+		ret = shift;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/* We traveled all the way to the bottom of the allocation tree
+	 * and didn't find room for any more extents - we need to add
+	 * another tree level */
+	if (shift) {
+		BUG_ON(bh);
+		mlog(0, "need to shift tree depth (current = %d)\n", depth);
+
+		/* ocfs2_shift_tree_depth will return us a buffer with
+		 * the new extent block (so we can pass that to
+		 * ocfs2_add_branch). */
+		ret = ocfs2_shift_tree_depth(osb, handle, inode, di_bh,
+					     meta_ac, &bh);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+		depth++;
+		if (depth == 1) {
+			/*
+			 * Special case: we have room now if we shifted from
+			 * tree_depth 0, so no more work needs to be done.
+			 *
+			 * We won't be calling add_branch, so pass
+			 * back *last_eb_bh as the new leaf. At depth
+			 * zero, it should always be null so there's
+			 * no reason to brelse.
+			 */
+			BUG_ON(*last_eb_bh);
+			get_bh(bh);
+			*last_eb_bh = bh;
+			goto out;
+		}
+	}
+
+	/* call ocfs2_add_branch to add the final part of the tree with
+	 * the new data. */
+	mlog(0, "add branch. bh = %p\n", bh);
+	ret = ocfs2_add_branch(osb, handle, inode, di_bh, bh, last_eb_bh,
+			       meta_ac);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+out:
+	if (final_depth)
+		*final_depth = depth;
+	brelse(bh);
+	return ret;
+}
+
+/*
  * This is only valid for leaf nodes, which are the only ones that can
  * have empty extents anyway.
  */
@@ -934,6 +1097,22 @@
 
 }
 
+static void ocfs2_remove_empty_extent(struct ocfs2_extent_list *el)
+{
+	int size, num_recs = le16_to_cpu(el->l_next_free_rec);
+
+	BUG_ON(num_recs == 0);
+
+	if (ocfs2_is_empty_extent(&el->l_recs[0])) {
+		num_recs--;
+		size = num_recs * sizeof(struct ocfs2_extent_rec);
+		memmove(&el->l_recs[0], &el->l_recs[1], size);
+		memset(&el->l_recs[num_recs], 0,
+		       sizeof(struct ocfs2_extent_rec));
+		el->l_next_free_rec = cpu_to_le16(num_recs);
+	}
+}
+
 /*
  * Create an empty extent record .
  *
@@ -1211,6 +1390,10 @@
 	 * immediately to their right.
 	 */
 	left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
+	if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
+		BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
+		left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
+	}
 	left_clusters -= le32_to_cpu(left_rec->e_cpos);
 	left_rec->e_int_clusters = cpu_to_le32(left_clusters);
 
@@ -1531,10 +1714,16 @@
 	return ret;
 }
 
+/*
+ * Extend the transaction by enough credits to complete the rotation,
+ * and still leave at least the original number of credits allocated
+ * to this transaction.
+ */
 static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth,
+					   int op_credits,
 					   struct ocfs2_path *path)
 {
-	int credits = (path->p_tree_depth - subtree_depth) * 2 + 1;
+	int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits;
 
 	if (handle->h_buffer_credits < credits)
 		return ocfs2_extend_trans(handle, credits);
@@ -1568,6 +1757,29 @@
 	return 0;
 }
 
+static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
+{
+	int next_free = le16_to_cpu(el->l_next_free_rec);
+	unsigned int range;
+	struct ocfs2_extent_rec *rec;
+
+	if (next_free == 0)
+		return 0;
+
+	rec = &el->l_recs[0];
+	if (ocfs2_is_empty_extent(rec)) {
+		/* Empty list. */
+		if (next_free == 1)
+			return 0;
+		rec = &el->l_recs[1];
+	}
+
+	range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+	if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
+		return 1;
+	return 0;
+}
+
 /*
  * Rotate all the records in a btree right one record, starting at insert_cpos.
  *
@@ -1586,11 +1798,12 @@
  */
 static int ocfs2_rotate_tree_right(struct inode *inode,
 				   handle_t *handle,
+				   enum ocfs2_split_type split,
 				   u32 insert_cpos,
 				   struct ocfs2_path *right_path,
 				   struct ocfs2_path **ret_left_path)
 {
-	int ret, start;
+	int ret, start, orig_credits = handle->h_buffer_credits;
 	u32 cpos;
 	struct ocfs2_path *left_path = NULL;
 
@@ -1657,9 +1870,9 @@
 				(unsigned long long)
 				path_leaf_bh(left_path)->b_blocknr);
 
-		if (ocfs2_rotate_requires_path_adjustment(left_path,
+		if (split == SPLIT_NONE &&
+		    ocfs2_rotate_requires_path_adjustment(left_path,
 							  insert_cpos)) {
-			mlog(0, "Path adjustment required\n");
 
 			/*
 			 * We've rotated the tree as much as we
@@ -1687,7 +1900,7 @@
 		     right_path->p_tree_depth);
 
 		ret = ocfs2_extend_rotate_transaction(handle, start,
-						      right_path);
+						      orig_credits, right_path);
 		if (ret) {
 			mlog_errno(ret);
 			goto out;
@@ -1700,6 +1913,24 @@
 			goto out;
 		}
 
+		if (split != SPLIT_NONE &&
+		    ocfs2_leftmost_rec_contains(path_leaf_el(right_path),
+						insert_cpos)) {
+			/*
+			 * A rotate moves the rightmost left leaf
+			 * record over to the leftmost right leaf
+			 * slot. If we're doing an extent split
+			 * instead of a real insert, then we have to
+			 * check that the extent to be split wasn't
+			 * just moved over. If it was, then we can
+			 * exit here, passing left_path back -
+			 * ocfs2_split_extent() is smart enough to
+			 * search both leaves.
+			 */
+			*ret_left_path = left_path;
+			goto out_ret_path;
+		}
+
 		/*
 		 * There is no need to re-read the next right path
 		 * as we know that it'll be our current left
@@ -1722,6 +1953,1031 @@
 	return ret;
 }
 
+static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
+				      struct ocfs2_path *path)
+{
+	int i, idx;
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_extent_block *eb;
+	u32 range;
+
+	/* Path should always be rightmost. */
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+	BUG_ON(eb->h_next_leaf_blk != 0ULL);
+
+	el = &eb->h_list;
+	BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);
+	idx = le16_to_cpu(el->l_next_free_rec) - 1;
+	rec = &el->l_recs[idx];
+	range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+
+	for (i = 0; i < path->p_tree_depth; i++) {
+		el = path->p_node[i].el;
+		idx = le16_to_cpu(el->l_next_free_rec) - 1;
+		rec = &el->l_recs[idx];
+
+		rec->e_int_clusters = cpu_to_le32(range);
+		le32_add_cpu(&rec->e_int_clusters, -le32_to_cpu(rec->e_cpos));
+
+		ocfs2_journal_dirty(handle, path->p_node[i].bh);
+	}
+}
+
+static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc,
+			      struct ocfs2_path *path, int unlink_start)
+{
+	int ret, i;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *el;
+	struct buffer_head *bh;
+
+	for(i = unlink_start; i < path_num_items(path); i++) {
+		bh = path->p_node[i].bh;
+
+		eb = (struct ocfs2_extent_block *)bh->b_data;
+		/*
+		 * Not all nodes might have had their final count
+		 * decremented by the caller - handle this here.
+		 */
+		el = &eb->h_list;
+		if (le16_to_cpu(el->l_next_free_rec) > 1) {
+			mlog(ML_ERROR,
+			     "Inode %llu, attempted to remove extent block "
+			     "%llu with %u records\n",
+			     (unsigned long long)OCFS2_I(inode)->ip_blkno,
+			     (unsigned long long)le64_to_cpu(eb->h_blkno),
+			     le16_to_cpu(el->l_next_free_rec));
+
+			ocfs2_journal_dirty(handle, bh);
+			ocfs2_remove_from_cache(inode, bh);
+			continue;
+		}
+
+		el->l_next_free_rec = 0;
+		memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+
+		ocfs2_journal_dirty(handle, bh);
+
+		ret = ocfs2_cache_extent_block_free(dealloc, eb);
+		if (ret)
+			mlog_errno(ret);
+
+		ocfs2_remove_from_cache(inode, bh);
+	}
+}
+
+static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,
+				 struct ocfs2_path *left_path,
+				 struct ocfs2_path *right_path,
+				 int subtree_index,
+				 struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int i;
+	struct buffer_head *root_bh = left_path->p_node[subtree_index].bh;
+	struct ocfs2_extent_list *root_el = left_path->p_node[subtree_index].el;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_extent_block *eb;
+
+	el = path_leaf_el(left_path);
+
+	eb = (struct ocfs2_extent_block *)right_path->p_node[subtree_index + 1].bh->b_data;
+
+	for(i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)
+		if (root_el->l_recs[i].e_blkno == eb->h_blkno)
+			break;
+
+	BUG_ON(i >= le16_to_cpu(root_el->l_next_free_rec));
+
+	memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
+	le16_add_cpu(&root_el->l_next_free_rec, -1);
+
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+	eb->h_next_leaf_blk = 0;
+
+	ocfs2_journal_dirty(handle, root_bh);
+	ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+
+	ocfs2_unlink_path(inode, handle, dealloc, right_path,
+			  subtree_index + 1);
+}
+
+static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
+				     struct ocfs2_path *left_path,
+				     struct ocfs2_path *right_path,
+				     int subtree_index,
+				     struct ocfs2_cached_dealloc_ctxt *dealloc,
+				     int *deleted)
+{
+	int ret, i, del_right_subtree = 0, right_has_empty = 0;
+	struct buffer_head *root_bh, *di_bh = path_root_bh(right_path);
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+	struct ocfs2_extent_list *right_leaf_el, *left_leaf_el;
+	struct ocfs2_extent_block *eb;
+
+	*deleted = 0;
+
+	right_leaf_el = path_leaf_el(right_path);
+	left_leaf_el = path_leaf_el(left_path);
+	root_bh = left_path->p_node[subtree_index].bh;
+	BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
+
+	if (!ocfs2_is_empty_extent(&left_leaf_el->l_recs[0]))
+		return 0;
+
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(right_path)->b_data;
+	if (ocfs2_is_empty_extent(&right_leaf_el->l_recs[0])) {
+		/*
+		 * It's legal for us to proceed if the right leaf is
+		 * the rightmost one and it has an empty extent. There
+		 * are two cases to handle - whether the leaf will be
+		 * empty after removal or not. If the leaf isn't empty
+		 * then just remove the empty extent up front. The
+		 * next block will handle empty leaves by flagging
+		 * them for unlink.
+		 *
+		 * Non rightmost leaves will throw -EAGAIN and the
+		 * caller can manually move the subtree and retry.
+		 */
+
+		if (eb->h_next_leaf_blk != 0ULL)
+			return -EAGAIN;
+
+		if (le16_to_cpu(right_leaf_el->l_next_free_rec) > 1) {
+			ret = ocfs2_journal_access(handle, inode,
+						   path_leaf_bh(right_path),
+						   OCFS2_JOURNAL_ACCESS_WRITE);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+
+			ocfs2_remove_empty_extent(right_leaf_el);
+		} else
+			right_has_empty = 1;
+	}
+
+	if (eb->h_next_leaf_blk == 0ULL &&
+	    le16_to_cpu(right_leaf_el->l_next_free_rec) == 1) {
+		/*
+		 * We have to update i_last_eb_blk during the meta
+		 * data delete.
+		 */
+		ret = ocfs2_journal_access(handle, inode, di_bh,
+					   OCFS2_JOURNAL_ACCESS_WRITE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		del_right_subtree = 1;
+	}
+
+	/*
+	 * Getting here with an empty extent in the right path implies
+	 * that it's the rightmost path and will be deleted.
+	 */
+	BUG_ON(right_has_empty && !del_right_subtree);
+
+	ret = ocfs2_journal_access(handle, inode, root_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
+		ret = ocfs2_journal_access(handle, inode,
+					   right_path->p_node[i].bh,
+					   OCFS2_JOURNAL_ACCESS_WRITE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_journal_access(handle, inode,
+					   left_path->p_node[i].bh,
+					   OCFS2_JOURNAL_ACCESS_WRITE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+	if (!right_has_empty) {
+		/*
+		 * Only do this if we're moving a real
+		 * record. Otherwise, the action is delayed until
+		 * after removal of the right path in which case we
+		 * can do a simple shift to remove the empty extent.
+		 */
+		ocfs2_rotate_leaf(left_leaf_el, &right_leaf_el->l_recs[0]);
+		memset(&right_leaf_el->l_recs[0], 0,
+		       sizeof(struct ocfs2_extent_rec));
+	}
+	if (eb->h_next_leaf_blk == 0ULL) {
+		/*
+		 * Move recs over to get rid of empty extent, decrease
+		 * next_free. This is allowed to remove the last
+		 * extent in our leaf (setting l_next_free_rec to
+		 * zero) - the delete code below won't care.
+		 */
+		ocfs2_remove_empty_extent(right_leaf_el);
+	}
+
+	ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+	if (ret)
+		mlog_errno(ret);
+	ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));
+	if (ret)
+		mlog_errno(ret);
+
+	if (del_right_subtree) {
+		ocfs2_unlink_subtree(inode, handle, left_path, right_path,
+				     subtree_index, dealloc);
+		ocfs2_update_edge_lengths(inode, handle, left_path);
+
+		eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+		di->i_last_eb_blk = eb->h_blkno;
+
+		/*
+		 * Removal of the extent in the left leaf was skipped
+		 * above so we could delete the right path
+		 * 1st.
+		 */
+		if (right_has_empty)
+			ocfs2_remove_empty_extent(left_leaf_el);
+
+		ret = ocfs2_journal_dirty(handle, di_bh);
+		if (ret)
+			mlog_errno(ret);
+
+		*deleted = 1;
+	} else
+		ocfs2_complete_edge_insert(inode, handle, left_path, right_path,
+					   subtree_index);
+
+out:
+	return ret;
+}
+
+/*
+ * Given a full path, determine what cpos value would return us a path
+ * containing the leaf immediately to the right of the current one.
+ *
+ * Will return zero if the path passed in is already the rightmost path.
+ *
+ * This looks similar, but is subtly different to
+ * ocfs2_find_cpos_for_left_leaf().
+ */
+static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+					  struct ocfs2_path *path, u32 *cpos)
+{
+	int i, j, ret = 0;
+	u64 blkno;
+	struct ocfs2_extent_list *el;
+
+	*cpos = 0;
+
+	if (path->p_tree_depth == 0)
+		return 0;
+
+	blkno = path_leaf_bh(path)->b_blocknr;
+
+	/* Start at the tree node just above the leaf and work our way up. */
+	i = path->p_tree_depth - 1;
+	while (i >= 0) {
+		int next_free;
+
+		el = path->p_node[i].el;
+
+		/*
+		 * Find the extent record just after the one in our
+		 * path.
+		 */
+		next_free = le16_to_cpu(el->l_next_free_rec);
+		for(j = 0; j < le16_to_cpu(el->l_next_free_rec); j++) {
+			if (le64_to_cpu(el->l_recs[j].e_blkno) == blkno) {
+				if (j == (next_free - 1)) {
+					if (i == 0) {
+						/*
+						 * We've determined that the
+						 * path specified is already
+						 * the rightmost one - return a
+						 * cpos of zero.
+						 */
+						goto out;
+					}
+					/*
+					 * The rightmost record points to our
+					 * leaf - we need to travel up the
+					 * tree one level.
+					 */
+					goto next_node;
+				}
+
+				*cpos = le32_to_cpu(el->l_recs[j + 1].e_cpos);
+				goto out;
+			}
+		}
+
+		/*
+		 * If we got here, we never found a valid node where
+		 * the tree indicated one should be.
+		 */
+		ocfs2_error(sb,
+			    "Invalid extent tree at extent block %llu\n",
+			    (unsigned long long)blkno);
+		ret = -EROFS;
+		goto out;
+
+next_node:
+		blkno = path->p_node[i].bh->b_blocknr;
+		i--;
+	}
+
+out:
+	return ret;
+}
+
+static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
+					    handle_t *handle,
+					    struct buffer_head *bh,
+					    struct ocfs2_extent_list *el)
+{
+	int ret;
+
+	if (!ocfs2_is_empty_extent(&el->l_recs[0]))
+		return 0;
+
+	ret = ocfs2_journal_access(handle, inode, bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ocfs2_remove_empty_extent(el);
+
+	ret = ocfs2_journal_dirty(handle, bh);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
+static int __ocfs2_rotate_tree_left(struct inode *inode,
+				    handle_t *handle, int orig_credits,
+				    struct ocfs2_path *path,
+				    struct ocfs2_cached_dealloc_ctxt *dealloc,
+				    struct ocfs2_path **empty_extent_path)
+{
+	int ret, subtree_root, deleted;
+	u32 right_cpos;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_path *right_path = NULL;
+
+	BUG_ON(!ocfs2_is_empty_extent(&(path_leaf_el(path)->l_recs[0])));
+
+	*empty_extent_path = NULL;
+
+	ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, path,
+					     &right_cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	left_path = ocfs2_new_path(path_root_bh(path),
+				   path_root_el(path));
+	if (!left_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ocfs2_cp_path(left_path, path);
+
+	right_path = ocfs2_new_path(path_root_bh(path),
+				    path_root_el(path));
+	if (!right_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	while (right_cpos) {
+		ret = ocfs2_find_path(inode, right_path, right_cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		subtree_root = ocfs2_find_subtree_root(inode, left_path,
+						       right_path);
+
+		mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
+		     subtree_root,
+		     (unsigned long long)
+		     right_path->p_node[subtree_root].bh->b_blocknr,
+		     right_path->p_tree_depth);
+
+		ret = ocfs2_extend_rotate_transaction(handle, subtree_root,
+						      orig_credits, left_path);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_rotate_subtree_left(inode, handle, left_path,
+						right_path, subtree_root,
+						dealloc, &deleted);
+		if (ret == -EAGAIN) {
+			/*
+			 * The rotation has to temporarily stop due to
+			 * the right subtree having an empty
+			 * extent. Pass it back to the caller for a
+			 * fixup.
+			 */
+			*empty_extent_path = right_path;
+			right_path = NULL;
+			goto out;
+		}
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * The subtree rotate might have removed records on
+		 * the rightmost edge. If so, then rotation is
+		 * complete.
+		 */
+		if (deleted)
+			break;
+
+		ocfs2_mv_path(left_path, right_path);
+
+		ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
+						     &right_cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+out:
+	ocfs2_free_path(right_path);
+	ocfs2_free_path(left_path);
+
+	return ret;
+}
+
+static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
+				       struct ocfs2_path *path,
+				       struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, subtree_index;
+	u32 cpos;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_dinode *di;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *el;
+
+	/*
+	 * XXX: This code assumes that the root is an inode, which is
+	 * true for now but may change as tree code gets generic.
+	 */
+	di = (struct ocfs2_dinode *)path_root_bh(path)->b_data;
+	if (!OCFS2_IS_VALID_DINODE(di)) {
+		ret = -EIO;
+		ocfs2_error(inode->i_sb,
+			    "Inode %llu has invalid path root",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+		goto out;
+	}
+
+	/*
+	 * There's two ways we handle this depending on
+	 * whether path is the only existing one.
+	 */
+	ret = ocfs2_extend_rotate_transaction(handle, 0,
+					      handle->h_buffer_credits,
+					      path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_path(inode, handle, path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path, &cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (cpos) {
+		/*
+		 * We have a path to the left of this one - it needs
+		 * an update too.
+		 */
+		left_path = ocfs2_new_path(path_root_bh(path),
+					   path_root_el(path));
+		if (!left_path) {
+			ret = -ENOMEM;
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_find_path(inode, left_path, cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_journal_access_path(inode, handle, left_path);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
+
+		ocfs2_unlink_subtree(inode, handle, left_path, path,
+				     subtree_index, dealloc);
+		ocfs2_update_edge_lengths(inode, handle, left_path);
+
+		eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+		di->i_last_eb_blk = eb->h_blkno;
+	} else {
+		/*
+		 * 'path' is also the leftmost path which
+		 * means it must be the only one. This gets
+		 * handled differently because we want to
+		 * revert the inode back to having extents
+		 * in-line.
+		 */
+		ocfs2_unlink_path(inode, handle, dealloc, path, 1);
+
+		el = &di->id2.i_list;
+		el->l_tree_depth = 0;
+		el->l_next_free_rec = 0;
+		memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+
+		di->i_last_eb_blk = 0;
+	}
+
+	ocfs2_journal_dirty(handle, path_root_bh(path));
+
+out:
+	ocfs2_free_path(left_path);
+	return ret;
+}
+
+/*
+ * Left rotation of btree records.
+ *
+ * In many ways, this is (unsurprisingly) the opposite of right
+ * rotation. We start at some non-rightmost path containing an empty
+ * extent in the leaf block. The code works its way to the rightmost
+ * path by rotating records to the left in every subtree.
+ *
+ * This is used by any code which reduces the number of extent records
+ * in a leaf. After removal, an empty record should be placed in the
+ * leftmost list position.
+ *
+ * This won't handle a length update of the rightmost path records if
+ * the rightmost tree leaf record is removed so the caller is
+ * responsible for detecting and correcting that.
+ */
+static int ocfs2_rotate_tree_left(struct inode *inode, handle_t *handle,
+				  struct ocfs2_path *path,
+				  struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, orig_credits = handle->h_buffer_credits;
+	struct ocfs2_path *tmp_path = NULL, *restart_path = NULL;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *el;
+
+	el = path_leaf_el(path);
+	if (!ocfs2_is_empty_extent(&el->l_recs[0]))
+		return 0;
+
+	if (path->p_tree_depth == 0) {
+rightmost_no_delete:
+		/*
+		 * In-inode extents. This is trivially handled, so do
+		 * it up front.
+		 */
+		ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
+						       path_leaf_bh(path),
+						       path_leaf_el(path));
+		if (ret)
+			mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * Handle rightmost branch now. There's several cases:
+	 *  1) simple rotation leaving records in there. That's trivial.
+	 *  2) rotation requiring a branch delete - there's no more
+	 *     records left. Two cases of this:
+	 *     a) There are branches to the left.
+	 *     b) This is also the leftmost (the only) branch.
+	 *
+	 *  1) is handled via ocfs2_rotate_rightmost_leaf_left()
+	 *  2a) we need the left branch so that we can update it with the unlink
+	 *  2b) we need to bring the inode back to inline extents.
+	 */
+
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+	el = &eb->h_list;
+	if (eb->h_next_leaf_blk == 0) {
+		/*
+		 * This gets a bit tricky if we're going to delete the
+		 * rightmost path. Get the other cases out of the way
+		 * 1st.
+		 */
+		if (le16_to_cpu(el->l_next_free_rec) > 1)
+			goto rightmost_no_delete;
+
+		if (le16_to_cpu(el->l_next_free_rec) == 0) {
+			ret = -EIO;
+			ocfs2_error(inode->i_sb,
+				    "Inode %llu has empty extent block at %llu",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+				    (unsigned long long)le64_to_cpu(eb->h_blkno));
+			goto out;
+		}
+
+		/*
+		 * XXX: The caller can not trust "path" any more after
+		 * this as it will have been deleted. What do we do?
+		 *
+		 * In theory the rotate-for-merge code will never get
+		 * here because it'll always ask for a rotate in a
+		 * nonempty list.
+		 */
+
+		ret = ocfs2_remove_rightmost_path(inode, handle, path,
+						  dealloc);
+		if (ret)
+			mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * Now we can loop, remembering the path we get from -EAGAIN
+	 * and restarting from there.
+	 */
+try_rotate:
+	ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits, path,
+				       dealloc, &restart_path);
+	if (ret && ret != -EAGAIN) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	while (ret == -EAGAIN) {
+		tmp_path = restart_path;
+		restart_path = NULL;
+
+		ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits,
+					       tmp_path, dealloc,
+					       &restart_path);
+		if (ret && ret != -EAGAIN) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ocfs2_free_path(tmp_path);
+		tmp_path = NULL;
+
+		if (ret == 0)
+			goto try_rotate;
+	}
+
+out:
+	ocfs2_free_path(tmp_path);
+	ocfs2_free_path(restart_path);
+	return ret;
+}
+
+static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
+				int index)
+{
+	struct ocfs2_extent_rec *rec = &el->l_recs[index];
+	unsigned int size;
+
+	if (rec->e_leaf_clusters == 0) {
+		/*
+		 * We consumed all of the merged-from record. An empty
+		 * extent cannot exist anywhere but the 1st array
+		 * position, so move things over if the merged-from
+		 * record doesn't occupy that position.
+		 *
+		 * This creates a new empty extent so the caller
+		 * should be smart enough to have removed any existing
+		 * ones.
+		 */
+		if (index > 0) {
+			BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+			size = index * sizeof(struct ocfs2_extent_rec);
+			memmove(&el->l_recs[1], &el->l_recs[0], size);
+		}
+
+		/*
+		 * Always memset - the caller doesn't check whether it
+		 * created an empty extent, so there could be junk in
+		 * the other fields.
+		 */
+		memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+	}
+}
+
+/*
+ * Remove split_rec clusters from the record at index and merge them
+ * onto the beginning of the record at index + 1.
+ */
+static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+				handle_t *handle,
+				struct ocfs2_extent_rec *split_rec,
+				struct ocfs2_extent_list *el, int index)
+{
+	int ret;
+	unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+	struct ocfs2_extent_rec *left_rec;
+	struct ocfs2_extent_rec *right_rec;
+
+	BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
+
+	left_rec = &el->l_recs[index];
+	right_rec = &el->l_recs[index + 1];
+
+	ret = ocfs2_journal_access(handle, inode, bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	le16_add_cpu(&left_rec->e_leaf_clusters, -split_clusters);
+
+	le32_add_cpu(&right_rec->e_cpos, -split_clusters);
+	le64_add_cpu(&right_rec->e_blkno,
+		     -ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+	le16_add_cpu(&right_rec->e_leaf_clusters, split_clusters);
+
+	ocfs2_cleanup_merge(el, index);
+
+	ret = ocfs2_journal_dirty(handle, bh);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
+/*
+ * Remove split_rec clusters from the record at index and merge them
+ * onto the tail of the record at index - 1.
+ */
+static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+				handle_t *handle,
+				struct ocfs2_extent_rec *split_rec,
+				struct ocfs2_extent_list *el, int index)
+{
+	int ret, has_empty_extent = 0;
+	unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+	struct ocfs2_extent_rec *left_rec;
+	struct ocfs2_extent_rec *right_rec;
+
+	BUG_ON(index <= 0);
+
+	left_rec = &el->l_recs[index - 1];
+	right_rec = &el->l_recs[index];
+	if (ocfs2_is_empty_extent(&el->l_recs[0]))
+		has_empty_extent = 1;
+
+	ret = ocfs2_journal_access(handle, inode, bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (has_empty_extent && index == 1) {
+		/*
+		 * The easy case - we can just plop the record right in.
+		 */
+		*left_rec = *split_rec;
+
+		has_empty_extent = 0;
+	} else {
+		le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
+	}
+
+	le32_add_cpu(&right_rec->e_cpos, split_clusters);
+	le64_add_cpu(&right_rec->e_blkno,
+		     ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+	le16_add_cpu(&right_rec->e_leaf_clusters, -split_clusters);
+
+	ocfs2_cleanup_merge(el, index);
+
+	ret = ocfs2_journal_dirty(handle, bh);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
+static int ocfs2_try_to_merge_extent(struct inode *inode,
+				     handle_t *handle,
+				     struct ocfs2_path *left_path,
+				     int split_index,
+				     struct ocfs2_extent_rec *split_rec,
+				     struct ocfs2_cached_dealloc_ctxt *dealloc,
+				     struct ocfs2_merge_ctxt *ctxt)
+
+{
+	int ret = 0, delete_tail_recs = 0;
+	struct ocfs2_extent_list *el = path_leaf_el(left_path);
+	struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+
+	BUG_ON(ctxt->c_contig_type == CONTIG_NONE);
+
+	if (ctxt->c_split_covers_rec) {
+		delete_tail_recs++;
+
+		if (ctxt->c_contig_type == CONTIG_LEFTRIGHT ||
+		    ctxt->c_has_empty_extent)
+			delete_tail_recs++;
+
+		if (ctxt->c_has_empty_extent) {
+			/*
+			 * The merge code will need to create an empty
+			 * extent to take the place of the newly
+			 * emptied slot. Remove any pre-existing empty
+			 * extents - having more than one in a leaf is
+			 * illegal.
+			 */
+			ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+						     dealloc);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+			split_index--;
+			rec = &el->l_recs[split_index];
+		}
+	}
+
+	if (ctxt->c_contig_type == CONTIG_LEFTRIGHT) {
+		/*
+		 * Left-right contig implies this.
+		 */
+		BUG_ON(!ctxt->c_split_covers_rec);
+		BUG_ON(split_index == 0);
+
+		/*
+		 * Since the leftright insert always covers the entire
+		 * extent, this call will delete the insert record
+		 * entirely, resulting in an empty extent record added to
+		 * the extent block.
+		 *
+		 * Since the adding of an empty extent shifts
+		 * everything back to the right, there's no need to
+		 * update split_index here.
+		 */
+		ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path),
+					   handle, split_rec, el, split_index);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * We can only get this from logic error above.
+		 */
+		BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+
+		/*
+		 * The left merge left us with an empty extent, remove
+		 * it.
+		 */
+		ret = ocfs2_rotate_tree_left(inode, handle, left_path, dealloc);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+		split_index--;
+		rec = &el->l_recs[split_index];
+
+		/*
+		 * Note that we don't pass split_rec here on purpose -
+		 * we've merged it into the left side.
+		 */
+		ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path),
+					    handle, rec, el, split_index);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+
+		ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+					     dealloc);
+		/*
+		 * Error from this last rotate is not critical, so
+		 * print but don't bubble it up.
+		 */
+		if (ret)
+			mlog_errno(ret);
+		ret = 0;
+	} else {
+		/*
+		 * Merge a record to the left or right.
+		 *
+		 * 'contig_type' is relative to the existing record,
+		 * so for example, if we're "right contig", it's to
+		 * the record on the left (hence the left merge).
+		 */
+		if (ctxt->c_contig_type == CONTIG_RIGHT) {
+			ret = ocfs2_merge_rec_left(inode,
+						   path_leaf_bh(left_path),
+						   handle, split_rec, el,
+						   split_index);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		} else {
+			ret = ocfs2_merge_rec_right(inode,
+						    path_leaf_bh(left_path),
+						    handle, split_rec, el,
+						    split_index);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		}
+
+		if (ctxt->c_split_covers_rec) {
+			/*
+			 * The merge may have left an empty extent in
+			 * our leaf. Try to rotate it away.
+			 */
+			ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+						     dealloc);
+			if (ret)
+				mlog_errno(ret);
+			ret = 0;
+		}
+	}
+
+out:
+	return ret;
+}
+
+static void ocfs2_subtract_from_rec(struct super_block *sb,
+				    enum ocfs2_split_type split,
+				    struct ocfs2_extent_rec *rec,
+				    struct ocfs2_extent_rec *split_rec)
+{
+	u64 len_blocks;
+
+	len_blocks = ocfs2_clusters_to_blocks(sb,
+				le16_to_cpu(split_rec->e_leaf_clusters));
+
+	if (split == SPLIT_LEFT) {
+		/*
+		 * Region is on the left edge of the existing
+		 * record.
+		 */
+		le32_add_cpu(&rec->e_cpos,
+			     le16_to_cpu(split_rec->e_leaf_clusters));
+		le64_add_cpu(&rec->e_blkno, len_blocks);
+		le16_add_cpu(&rec->e_leaf_clusters,
+			     -le16_to_cpu(split_rec->e_leaf_clusters));
+	} else {
+		/*
+		 * Region is on the right edge of the existing
+		 * record.
+		 */
+		le16_add_cpu(&rec->e_leaf_clusters,
+			     -le16_to_cpu(split_rec->e_leaf_clusters));
+	}
+}
+
 /*
  * Do the final bits of extent record insertion at the target leaf
  * list. If this leaf is part of an allocation tree, it is assumed
@@ -1738,6 +2994,15 @@
 
 	BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
 
+	if (insert->ins_split != SPLIT_NONE) {
+		i = ocfs2_search_extent_list(el, le32_to_cpu(insert_rec->e_cpos));
+		BUG_ON(i == -1);
+		rec = &el->l_recs[i];
+		ocfs2_subtract_from_rec(inode->i_sb, insert->ins_split, rec,
+					insert_rec);
+		goto rotate;
+	}
+
 	/*
 	 * Contiguous insert - either left or right.
 	 */
@@ -1792,6 +3057,7 @@
 		return;
 	}
 
+rotate:
 	/*
 	 * Ok, we have to rotate.
 	 *
@@ -1815,13 +3081,53 @@
 	spin_unlock(&OCFS2_I(inode)->ip_lock);
 }
 
+static void ocfs2_adjust_rightmost_records(struct inode *inode,
+					   handle_t *handle,
+					   struct ocfs2_path *path,
+					   struct ocfs2_extent_rec *insert_rec)
+{
+	int ret, i, next_free;
+	struct buffer_head *bh;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_extent_rec *rec;
+
+	/*
+	 * Update everything except the leaf block.
+	 */
+	for (i = 0; i < path->p_tree_depth; i++) {
+		bh = path->p_node[i].bh;
+		el = path->p_node[i].el;
+
+		next_free = le16_to_cpu(el->l_next_free_rec);
+		if (next_free == 0) {
+			ocfs2_error(inode->i_sb,
+				    "Dinode %llu has a bad extent list",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+			ret = -EIO;
+			return;
+		}
+
+		rec = &el->l_recs[next_free - 1];
+
+		rec->e_int_clusters = insert_rec->e_cpos;
+		le32_add_cpu(&rec->e_int_clusters,
+			     le16_to_cpu(insert_rec->e_leaf_clusters));
+		le32_add_cpu(&rec->e_int_clusters,
+			     -le32_to_cpu(rec->e_cpos));
+
+		ret = ocfs2_journal_dirty(handle, bh);
+		if (ret)
+			mlog_errno(ret);
+
+	}
+}
+
 static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
 				    struct ocfs2_extent_rec *insert_rec,
 				    struct ocfs2_path *right_path,
 				    struct ocfs2_path **ret_left_path)
 {
-	int ret, i, next_free;
-	struct buffer_head *bh;
+	int ret, next_free;
 	struct ocfs2_extent_list *el;
 	struct ocfs2_path *left_path = NULL;
 
@@ -1887,40 +3193,7 @@
 		goto out;
 	}
 
-	el = path_root_el(right_path);
-	bh = path_root_bh(right_path);
-	i = 0;
-	while (1) {
-		struct ocfs2_extent_rec *rec;
-
-		next_free = le16_to_cpu(el->l_next_free_rec);
-		if (next_free == 0) {
-			ocfs2_error(inode->i_sb,
-				    "Dinode %llu has a bad extent list",
-				    (unsigned long long)OCFS2_I(inode)->ip_blkno);
-			ret = -EIO;
-			goto out;
-		}
-
-		rec = &el->l_recs[next_free - 1];
-
-		rec->e_int_clusters = insert_rec->e_cpos;
-		le32_add_cpu(&rec->e_int_clusters,
-			     le16_to_cpu(insert_rec->e_leaf_clusters));
-		le32_add_cpu(&rec->e_int_clusters,
-			     -le32_to_cpu(rec->e_cpos));
-
-		ret = ocfs2_journal_dirty(handle, bh);
-		if (ret)
-			mlog_errno(ret);
-
-		/* Don't touch the leaf node */
-		if (++i >= right_path->p_tree_depth)
-			break;
-
-		bh = right_path->p_node[i].bh;
-		el = right_path->p_node[i].el;
-	}
+	ocfs2_adjust_rightmost_records(inode, handle, right_path, insert_rec);
 
 	*ret_left_path = left_path;
 	ret = 0;
@@ -1931,6 +3204,83 @@
 	return ret;
 }
 
+static void ocfs2_split_record(struct inode *inode,
+			       struct ocfs2_path *left_path,
+			       struct ocfs2_path *right_path,
+			       struct ocfs2_extent_rec *split_rec,
+			       enum ocfs2_split_type split)
+{
+	int index;
+	u32 cpos = le32_to_cpu(split_rec->e_cpos);
+	struct ocfs2_extent_list *left_el = NULL, *right_el, *insert_el, *el;
+	struct ocfs2_extent_rec *rec, *tmprec;
+
+	right_el = path_leaf_el(right_path);;
+	if (left_path)
+		left_el = path_leaf_el(left_path);
+
+	el = right_el;
+	insert_el = right_el;
+	index = ocfs2_search_extent_list(el, cpos);
+	if (index != -1) {
+		if (index == 0 && left_path) {
+			BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+
+			/*
+			 * This typically means that the record
+			 * started in the left path but moved to the
+			 * right as a result of rotation. We either
+			 * move the existing record to the left, or we
+			 * do the later insert there.
+			 *
+			 * In this case, the left path should always
+			 * exist as the rotate code will have passed
+			 * it back for a post-insert update.
+			 */
+
+			if (split == SPLIT_LEFT) {
+				/*
+				 * It's a left split. Since we know
+				 * that the rotate code gave us an
+				 * empty extent in the left path, we
+				 * can just do the insert there.
+				 */
+				insert_el = left_el;
+			} else {
+				/*
+				 * Right split - we have to move the
+				 * existing record over to the left
+				 * leaf. The insert will be into the
+				 * newly created empty extent in the
+				 * right leaf.
+				 */
+				tmprec = &right_el->l_recs[index];
+				ocfs2_rotate_leaf(left_el, tmprec);
+				el = left_el;
+
+				memset(tmprec, 0, sizeof(*tmprec));
+				index = ocfs2_search_extent_list(left_el, cpos);
+				BUG_ON(index == -1);
+			}
+		}
+	} else {
+		BUG_ON(!left_path);
+		BUG_ON(!ocfs2_is_empty_extent(&left_el->l_recs[0]));
+		/*
+		 * Left path is easy - we can just allow the insert to
+		 * happen.
+		 */
+		el = left_el;
+		insert_el = left_el;
+		index = ocfs2_search_extent_list(el, cpos);
+		BUG_ON(index == -1);
+	}
+
+	rec = &el->l_recs[index];
+	ocfs2_subtract_from_rec(inode->i_sb, split, rec, split_rec);
+	ocfs2_rotate_leaf(insert_el, split_rec);
+}
+
 /*
  * This function only does inserts on an allocation b-tree. For dinode
  * lists, ocfs2_insert_at_leaf() is called directly.
@@ -1948,7 +3298,6 @@
 {
 	int ret, subtree_index;
 	struct buffer_head *leaf_bh = path_leaf_bh(right_path);
-	struct ocfs2_extent_list *el;
 
 	/*
 	 * Pass both paths to the journal. The majority of inserts
@@ -1984,9 +3333,18 @@
 		}
 	}
 
-	el = path_leaf_el(right_path);
+	if (insert->ins_split != SPLIT_NONE) {
+		/*
+		 * We could call ocfs2_insert_at_leaf() for some types
+		 * of splits, but it's easier to just let one seperate
+		 * function sort it all out.
+		 */
+		ocfs2_split_record(inode, left_path, right_path,
+				   insert_rec, insert->ins_split);
+	} else
+		ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path),
+				     insert, inode);
 
-	ocfs2_insert_at_leaf(insert_rec, el, insert, inode);
 	ret = ocfs2_journal_dirty(handle, leaf_bh);
 	if (ret)
 		mlog_errno(ret);
@@ -2075,7 +3433,7 @@
 	 * can wind up skipping both of these two special cases...
 	 */
 	if (rotate) {
-		ret = ocfs2_rotate_tree_right(inode, handle,
+		ret = ocfs2_rotate_tree_right(inode, handle, type->ins_split,
 					      le32_to_cpu(insert_rec->e_cpos),
 					      right_path, &left_path);
 		if (ret) {
@@ -2100,8 +3458,9 @@
 	}
 
 out_update_clusters:
-	ocfs2_update_dinode_clusters(inode, di,
-				     le16_to_cpu(insert_rec->e_leaf_clusters));
+	if (type->ins_split == SPLIT_NONE)
+		ocfs2_update_dinode_clusters(inode, di,
+					     le16_to_cpu(insert_rec->e_leaf_clusters));
 
 	ret = ocfs2_journal_dirty(handle, di_bh);
 	if (ret)
@@ -2114,6 +3473,44 @@
 	return ret;
 }
 
+static enum ocfs2_contig_type
+ocfs2_figure_merge_contig_type(struct inode *inode,
+			       struct ocfs2_extent_list *el, int index,
+			       struct ocfs2_extent_rec *split_rec)
+{
+	struct ocfs2_extent_rec *rec;
+	enum ocfs2_contig_type ret = CONTIG_NONE;
+
+	/*
+	 * We're careful to check for an empty extent record here -
+	 * the merge code will know what to do if it sees one.
+	 */
+
+	if (index > 0) {
+		rec = &el->l_recs[index - 1];
+		if (index == 1 && ocfs2_is_empty_extent(rec)) {
+			if (split_rec->e_cpos == el->l_recs[index].e_cpos)
+				ret = CONTIG_RIGHT;
+		} else {
+			ret = ocfs2_extent_contig(inode, rec, split_rec);
+		}
+	}
+
+	if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
+		enum ocfs2_contig_type contig_type;
+
+		rec = &el->l_recs[index + 1];
+		contig_type = ocfs2_extent_contig(inode, rec, split_rec);
+
+		if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
+			ret = CONTIG_LEFTRIGHT;
+		else if (ret == CONTIG_NONE)
+			ret = contig_type;
+	}
+
+	return ret;
+}
+
 static void ocfs2_figure_contig_type(struct inode *inode,
 				     struct ocfs2_insert_type *insert,
 				     struct ocfs2_extent_list *el,
@@ -2205,6 +3602,8 @@
 	struct ocfs2_path *path = NULL;
 	struct buffer_head *bh = NULL;
 
+	insert->ins_split = SPLIT_NONE;
+
 	el = &di->id2.i_list;
 	insert->ins_tree_depth = le16_to_cpu(el->l_tree_depth);
 
@@ -2327,9 +3726,10 @@
 			u32 cpos,
 			u64 start_blk,
 			u32 new_clusters,
+			u8 flags,
 			struct ocfs2_alloc_context *meta_ac)
 {
-	int status, shift;
+	int status;
 	struct buffer_head *last_eb_bh = NULL;
 	struct buffer_head *bh = NULL;
 	struct ocfs2_insert_type insert = {0, };
@@ -2350,6 +3750,7 @@
 	rec.e_cpos = cpu_to_le32(cpos);
 	rec.e_blkno = cpu_to_le64(start_blk);
 	rec.e_leaf_clusters = cpu_to_le16(new_clusters);
+	rec.e_flags = flags;
 
 	status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
 					  &insert);
@@ -2364,55 +3765,16 @@
 	     insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
 	     insert.ins_free_records, insert.ins_tree_depth);
 
-	/*
-	 * Avoid growing the tree unless we're out of records and the
-	 * insert type requres one.
-	 */
-	if (insert.ins_contig != CONTIG_NONE || insert.ins_free_records)
-		goto out_add;
-
-	shift = ocfs2_find_branch_target(osb, inode, fe_bh, &bh);
-	if (shift < 0) {
-		status = shift;
-		mlog_errno(status);
-		goto bail;
-	}
-
-	/* We traveled all the way to the bottom of the allocation tree
-	 * and didn't find room for any more extents - we need to add
-	 * another tree level */
-	if (shift) {
-		BUG_ON(bh);
-		mlog(0, "need to shift tree depth "
-		     "(current = %d)\n", insert.ins_tree_depth);
-
-		/* ocfs2_shift_tree_depth will return us a buffer with
-		 * the new extent block (so we can pass that to
-		 * ocfs2_add_branch). */
-		status = ocfs2_shift_tree_depth(osb, handle, inode, fe_bh,
-						meta_ac, &bh);
-		if (status < 0) {
+	if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
+		status = ocfs2_grow_tree(inode, handle, fe_bh,
+					 &insert.ins_tree_depth, &last_eb_bh,
+					 meta_ac);
+		if (status) {
 			mlog_errno(status);
 			goto bail;
 		}
-		insert.ins_tree_depth++;
-		/* Special case: we have room now if we shifted from
-		 * tree_depth 0 */
-		if (insert.ins_tree_depth == 1)
-			goto out_add;
 	}
 
-	/* call ocfs2_add_branch to add the final part of the tree with
-	 * the new data. */
-	mlog(0, "add branch. bh = %p\n", bh);
-	status = ocfs2_add_branch(osb, handle, inode, fe_bh, bh, last_eb_bh,
-				  meta_ac);
-	if (status < 0) {
-		mlog_errno(status);
-		goto bail;
-	}
-
-out_add:
 	/* Finally, we can add clusters. This might rotate the tree for us. */
 	status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
 	if (status < 0)
@@ -2431,7 +3793,720 @@
 	return status;
 }
 
-static inline int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
+static void ocfs2_make_right_split_rec(struct super_block *sb,
+				       struct ocfs2_extent_rec *split_rec,
+				       u32 cpos,
+				       struct ocfs2_extent_rec *rec)
+{
+	u32 rec_cpos = le32_to_cpu(rec->e_cpos);
+	u32 rec_range = rec_cpos + le16_to_cpu(rec->e_leaf_clusters);
+
+	memset(split_rec, 0, sizeof(struct ocfs2_extent_rec));
+
+	split_rec->e_cpos = cpu_to_le32(cpos);
+	split_rec->e_leaf_clusters = cpu_to_le16(rec_range - cpos);
+
+	split_rec->e_blkno = rec->e_blkno;
+	le64_add_cpu(&split_rec->e_blkno,
+		     ocfs2_clusters_to_blocks(sb, cpos - rec_cpos));
+
+	split_rec->e_flags = rec->e_flags;
+}
+
+static int ocfs2_split_and_insert(struct inode *inode,
+				  handle_t *handle,
+				  struct ocfs2_path *path,
+				  struct buffer_head *di_bh,
+				  struct buffer_head **last_eb_bh,
+				  int split_index,
+				  struct ocfs2_extent_rec *orig_split_rec,
+				  struct ocfs2_alloc_context *meta_ac)
+{
+	int ret = 0, depth;
+	unsigned int insert_range, rec_range, do_leftright = 0;
+	struct ocfs2_extent_rec tmprec;
+	struct ocfs2_extent_list *rightmost_el;
+	struct ocfs2_extent_rec rec;
+	struct ocfs2_extent_rec split_rec = *orig_split_rec;
+	struct ocfs2_insert_type insert;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_dinode *di;
+
+leftright:
+	/*
+	 * Store a copy of the record on the stack - it might move
+	 * around as the tree is manipulated below.
+	 */
+	rec = path_leaf_el(path)->l_recs[split_index];
+
+	di = (struct ocfs2_dinode *)di_bh->b_data;
+	rightmost_el = &di->id2.i_list;
+
+	depth = le16_to_cpu(rightmost_el->l_tree_depth);
+	if (depth) {
+		BUG_ON(!(*last_eb_bh));
+		eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
+		rightmost_el = &eb->h_list;
+	}
+
+	if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
+	    le16_to_cpu(rightmost_el->l_count)) {
+		int old_depth = depth;
+
+		ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh,
+				      meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (old_depth != depth) {
+			eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
+			rightmost_el = &eb->h_list;
+		}
+	}
+
+	memset(&insert, 0, sizeof(struct ocfs2_insert_type));
+	insert.ins_appending = APPEND_NONE;
+	insert.ins_contig = CONTIG_NONE;
+	insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
+		- le16_to_cpu(rightmost_el->l_next_free_rec);
+	insert.ins_tree_depth = depth;
+
+	insert_range = le32_to_cpu(split_rec.e_cpos) +
+		le16_to_cpu(split_rec.e_leaf_clusters);
+	rec_range = le32_to_cpu(rec.e_cpos) +
+		le16_to_cpu(rec.e_leaf_clusters);
+
+	if (split_rec.e_cpos == rec.e_cpos) {
+		insert.ins_split = SPLIT_LEFT;
+	} else if (insert_range == rec_range) {
+		insert.ins_split = SPLIT_RIGHT;
+	} else {
+		/*
+		 * Left/right split. We fake this as a right split
+		 * first and then make a second pass as a left split.
+		 */
+		insert.ins_split = SPLIT_RIGHT;
+
+		ocfs2_make_right_split_rec(inode->i_sb, &tmprec, insert_range,
+					   &rec);
+
+		split_rec = tmprec;
+
+		BUG_ON(do_leftright);
+		do_leftright = 1;
+	}
+
+	ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec,
+				     &insert);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (do_leftright == 1) {
+		u32 cpos;
+		struct ocfs2_extent_list *el;
+
+		do_leftright++;
+		split_rec = *orig_split_rec;
+
+		ocfs2_reinit_path(path, 1);
+
+		cpos = le32_to_cpu(split_rec.e_cpos);
+		ret = ocfs2_find_path(inode, path, cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		el = path_leaf_el(path);
+		split_index = ocfs2_search_extent_list(el, cpos);
+		goto leftright;
+	}
+out:
+
+	return ret;
+}
+
+/*
+ * Mark part or all of the extent record at split_index in the leaf
+ * pointed to by path as written. This removes the unwritten
+ * extent flag.
+ *
+ * Care is taken to handle contiguousness so as to not grow the tree.
+ *
+ * meta_ac is not strictly necessary - we only truly need it if growth
+ * of the tree is required. All other cases will degrade into a less
+ * optimal tree layout.
+ *
+ * last_eb_bh should be the rightmost leaf block for any inode with a
+ * btree. Since a split may grow the tree or a merge might shrink it, the caller cannot trust the contents of that buffer after this call.
+ *
+ * This code is optimized for readability - several passes might be
+ * made over certain portions of the tree. All of those blocks will
+ * have been brought into cache (and pinned via the journal), so the
+ * extra overhead is not expressed in terms of disk reads.
+ */
+static int __ocfs2_mark_extent_written(struct inode *inode,
+				       struct buffer_head *di_bh,
+				       handle_t *handle,
+				       struct ocfs2_path *path,
+				       int split_index,
+				       struct ocfs2_extent_rec *split_rec,
+				       struct ocfs2_alloc_context *meta_ac,
+				       struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret = 0;
+	struct ocfs2_extent_list *el = path_leaf_el(path);
+	struct buffer_head *eb_bh, *last_eb_bh = NULL;
+	struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+	struct ocfs2_merge_ctxt ctxt;
+	struct ocfs2_extent_list *rightmost_el;
+
+	if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) {
+		ret = -EIO;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
+	    ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
+	     (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
+		ret = -EIO;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	eb_bh = path_leaf_bh(path);
+	ret = ocfs2_journal_access(handle, inode, eb_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
+							    split_index,
+							    split_rec);
+
+	/*
+	 * The core merge / split code wants to know how much room is
+	 * left in this inodes allocation tree, so we pass the
+	 * rightmost extent list.
+	 */
+	if (path->p_tree_depth) {
+		struct ocfs2_extent_block *eb;
+		struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+
+		ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+				       le64_to_cpu(di->i_last_eb_blk),
+				       &last_eb_bh, OCFS2_BH_CACHED, inode);
+		if (ret) {
+			mlog_exit(ret);
+			goto out;
+		}
+
+		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+		if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+			OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+			ret = -EROFS;
+			goto out;
+		}
+
+		rightmost_el = &eb->h_list;
+	} else
+		rightmost_el = path_root_el(path);
+
+	ctxt.c_used_tail_recs = le16_to_cpu(rightmost_el->l_next_free_rec);
+	if (ctxt.c_used_tail_recs > 0 &&
+	    ocfs2_is_empty_extent(&rightmost_el->l_recs[0]))
+		ctxt.c_used_tail_recs--;
+
+	if (rec->e_cpos == split_rec->e_cpos &&
+	    rec->e_leaf_clusters == split_rec->e_leaf_clusters)
+		ctxt.c_split_covers_rec = 1;
+	else
+		ctxt.c_split_covers_rec = 0;
+
+	ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]);
+
+	mlog(0, "index: %d, contig: %u, used_tail_recs: %u, "
+	     "has_empty: %u, split_covers: %u\n", split_index,
+	     ctxt.c_contig_type, ctxt.c_used_tail_recs,
+	     ctxt.c_has_empty_extent, ctxt.c_split_covers_rec);
+
+	if (ctxt.c_contig_type == CONTIG_NONE) {
+		if (ctxt.c_split_covers_rec)
+			el->l_recs[split_index] = *split_rec;
+		else
+			ret = ocfs2_split_and_insert(inode, handle, path, di_bh,
+						     &last_eb_bh, split_index,
+						     split_rec, meta_ac);
+		if (ret)
+			mlog_errno(ret);
+	} else {
+		ret = ocfs2_try_to_merge_extent(inode, handle, path,
+						split_index, split_rec,
+						dealloc, &ctxt);
+		if (ret)
+			mlog_errno(ret);
+	}
+
+	ocfs2_journal_dirty(handle, eb_bh);
+
+out:
+	brelse(last_eb_bh);
+	return ret;
+}
+
+/*
+ * Mark the already-existing extent at cpos as written for len clusters.
+ *
+ * If the existing extent is larger than the request, initiate a
+ * split. An attempt will be made at merging with adjacent extents.
+ *
+ * The caller is responsible for passing down meta_ac if we'll need it.
+ */
+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+			      handle_t *handle, u32 cpos, u32 len, u32 phys,
+			      struct ocfs2_alloc_context *meta_ac,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, index;
+	u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
+	struct ocfs2_extent_rec split_rec;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_extent_list *el;
+
+	mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
+	     inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
+
+	if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
+		ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
+			    "that are being written to, but the feature bit "
+			    "is not set in the super block.",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+		ret = -EROFS;
+		goto out;
+	}
+
+	/*
+	 * XXX: This should be fixed up so that we just re-insert the
+	 * next extent records.
+	 */
+	ocfs2_extent_map_trunc(inode, 0);
+
+	left_path = ocfs2_new_inode_path(di_bh);
+	if (!left_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_path(inode, left_path, cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+	el = path_leaf_el(left_path);
+
+	index = ocfs2_search_extent_list(el, cpos);
+	if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+		ocfs2_error(inode->i_sb,
+			    "Inode %llu has an extent at cpos %u which can no "
+			    "longer be found.\n",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+		ret = -EROFS;
+		goto out;
+	}
+
+	memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
+	split_rec.e_cpos = cpu_to_le32(cpos);
+	split_rec.e_leaf_clusters = cpu_to_le16(len);
+	split_rec.e_blkno = cpu_to_le64(start_blkno);
+	split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
+	split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
+
+	ret = __ocfs2_mark_extent_written(inode, di_bh, handle, left_path,
+					  index, &split_rec, meta_ac, dealloc);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	ocfs2_free_path(left_path);
+	return ret;
+}
+
+static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
+			    handle_t *handle, struct ocfs2_path *path,
+			    int index, u32 new_range,
+			    struct ocfs2_alloc_context *meta_ac)
+{
+	int ret, depth, credits = handle->h_buffer_credits;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+	struct buffer_head *last_eb_bh = NULL;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *rightmost_el, *el;
+	struct ocfs2_extent_rec split_rec;
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_insert_type insert;
+
+	/*
+	 * Setup the record to split before we grow the tree.
+	 */
+	el = path_leaf_el(path);
+	rec = &el->l_recs[index];
+	ocfs2_make_right_split_rec(inode->i_sb, &split_rec, new_range, rec);
+
+	depth = path->p_tree_depth;
+	if (depth > 0) {
+		ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+				       le64_to_cpu(di->i_last_eb_blk),
+				       &last_eb_bh, OCFS2_BH_CACHED, inode);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+		rightmost_el = &eb->h_list;
+	} else
+		rightmost_el = path_leaf_el(path);
+
+	credits += path->p_tree_depth + ocfs2_extend_meta_needed(di);
+	ret = ocfs2_extend_trans(handle, credits);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
+	    le16_to_cpu(rightmost_el->l_count)) {
+		int old_depth = depth;
+
+		ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, &last_eb_bh,
+				      meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (old_depth != depth) {
+			eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
+			rightmost_el = &eb->h_list;
+		}
+	}
+
+	memset(&insert, 0, sizeof(struct ocfs2_insert_type));
+	insert.ins_appending = APPEND_NONE;
+	insert.ins_contig = CONTIG_NONE;
+	insert.ins_split = SPLIT_RIGHT;
+	insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
+		- le16_to_cpu(rightmost_el->l_next_free_rec);
+	insert.ins_tree_depth = depth;
+
+	ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec, &insert);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	brelse(last_eb_bh);
+	return ret;
+}
+
+static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
+			      struct ocfs2_path *path, int index,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc,
+			      u32 cpos, u32 len)
+{
+	int ret;
+	u32 left_cpos, rec_range, trunc_range;
+	int wants_rotate = 0, is_rightmost_tree_rec = 0;
+	struct super_block *sb = inode->i_sb;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_extent_list *el = path_leaf_el(path);
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_extent_block *eb;
+
+	if (ocfs2_is_empty_extent(&el->l_recs[0]) && index > 0) {
+		ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		index--;
+	}
+
+	if (index == (le16_to_cpu(el->l_next_free_rec) - 1) &&
+	    path->p_tree_depth) {
+		/*
+		 * Check whether this is the rightmost tree record. If
+		 * we remove all of this record or part of its right
+		 * edge then an update of the record lengths above it
+		 * will be required.
+		 */
+		eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+		if (eb->h_next_leaf_blk == 0)
+			is_rightmost_tree_rec = 1;
+	}
+
+	rec = &el->l_recs[index];
+	if (index == 0 && path->p_tree_depth &&
+	    le32_to_cpu(rec->e_cpos) == cpos) {
+		/*
+		 * Changing the leftmost offset (via partial or whole
+		 * record truncate) of an interior (or rightmost) path
+		 * means we have to update the subtree that is formed
+		 * by this leaf and the one to it's left.
+		 *
+		 * There are two cases we can skip:
+		 *   1) Path is the leftmost one in our inode tree.
+		 *   2) The leaf is rightmost and will be empty after
+		 *      we remove the extent record - the rotate code
+		 *      knows how to update the newly formed edge.
+		 */
+
+		ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path,
+						    &left_cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (left_cpos && le16_to_cpu(el->l_next_free_rec) > 1) {
+			left_path = ocfs2_new_path(path_root_bh(path),
+						   path_root_el(path));
+			if (!left_path) {
+				ret = -ENOMEM;
+				mlog_errno(ret);
+				goto out;
+			}
+
+			ret = ocfs2_find_path(inode, left_path, left_cpos);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		}
+	}
+
+	ret = ocfs2_extend_rotate_transaction(handle, 0,
+					      handle->h_buffer_credits,
+					      path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_path(inode, handle, path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_path(inode, handle, left_path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	rec_range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+	trunc_range = cpos + len;
+
+	if (le32_to_cpu(rec->e_cpos) == cpos && rec_range == trunc_range) {
+		int next_free;
+
+		memset(rec, 0, sizeof(*rec));
+		ocfs2_cleanup_merge(el, index);
+		wants_rotate = 1;
+
+		next_free = le16_to_cpu(el->l_next_free_rec);
+		if (is_rightmost_tree_rec && next_free > 1) {
+			/*
+			 * We skip the edge update if this path will
+			 * be deleted by the rotate code.
+			 */
+			rec = &el->l_recs[next_free - 1];
+			ocfs2_adjust_rightmost_records(inode, handle, path,
+						       rec);
+		}
+	} else if (le32_to_cpu(rec->e_cpos) == cpos) {
+		/* Remove leftmost portion of the record. */
+		le32_add_cpu(&rec->e_cpos, len);
+		le64_add_cpu(&rec->e_blkno, ocfs2_clusters_to_blocks(sb, len));
+		le16_add_cpu(&rec->e_leaf_clusters, -len);
+	} else if (rec_range == trunc_range) {
+		/* Remove rightmost portion of the record */
+		le16_add_cpu(&rec->e_leaf_clusters, -len);
+		if (is_rightmost_tree_rec)
+			ocfs2_adjust_rightmost_records(inode, handle, path, rec);
+	} else {
+		/* Caller should have trapped this. */
+		mlog(ML_ERROR, "Inode %llu: Invalid record truncate: (%u, %u) "
+		     "(%u, %u)\n", (unsigned long long)OCFS2_I(inode)->ip_blkno,
+		     le32_to_cpu(rec->e_cpos),
+		     le16_to_cpu(rec->e_leaf_clusters), cpos, len);
+		BUG();
+	}
+
+	if (left_path) {
+		int subtree_index;
+
+		subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
+		ocfs2_complete_edge_insert(inode, handle, left_path, path,
+					   subtree_index);
+	}
+
+	ocfs2_journal_dirty(handle, path_leaf_bh(path));
+
+	ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+out:
+	ocfs2_free_path(left_path);
+	return ret;
+}
+
+int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+			u32 cpos, u32 len, handle_t *handle,
+			struct ocfs2_alloc_context *meta_ac,
+			struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, index;
+	u32 rec_range, trunc_range;
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_path *path;
+
+	ocfs2_extent_map_trunc(inode, 0);
+
+	path = ocfs2_new_inode_path(di_bh);
+	if (!path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_path(inode, path, cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	el = path_leaf_el(path);
+	index = ocfs2_search_extent_list(el, cpos);
+	if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+		ocfs2_error(inode->i_sb,
+			    "Inode %llu has an extent at cpos %u which can no "
+			    "longer be found.\n",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+		ret = -EROFS;
+		goto out;
+	}
+
+	/*
+	 * We have 3 cases of extent removal:
+	 *   1) Range covers the entire extent rec
+	 *   2) Range begins or ends on one edge of the extent rec
+	 *   3) Range is in the middle of the extent rec (no shared edges)
+	 *
+	 * For case 1 we remove the extent rec and left rotate to
+	 * fill the hole.
+	 *
+	 * For case 2 we just shrink the existing extent rec, with a
+	 * tree update if the shrinking edge is also the edge of an
+	 * extent block.
+	 *
+	 * For case 3 we do a right split to turn the extent rec into
+	 * something case 2 can handle.
+	 */
+	rec = &el->l_recs[index];
+	rec_range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+	trunc_range = cpos + len;
+
+	BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range);
+
+	mlog(0, "Inode %llu, remove (cpos %u, len %u). Existing index %d "
+	     "(cpos %u, len %u)\n",
+	     (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos, len, index,
+	     le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec));
+
+	if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) {
+		ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
+					 cpos, len);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	} else {
+		ret = ocfs2_split_tree(inode, di_bh, handle, path, index,
+				       trunc_range, meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * The split could have manipulated the tree enough to
+		 * move the record location, so we have to look for it again.
+		 */
+		ocfs2_reinit_path(path, 1);
+
+		ret = ocfs2_find_path(inode, path, cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		el = path_leaf_el(path);
+		index = ocfs2_search_extent_list(el, cpos);
+		if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+			ocfs2_error(inode->i_sb,
+				    "Inode %llu: split at cpos %u lost record.",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+				    cpos);
+			ret = -EROFS;
+			goto out;
+		}
+
+		/*
+		 * Double check our values here. If anything is fishy,
+		 * it's easier to catch it at the top level.
+		 */
+		rec = &el->l_recs[index];
+		rec_range = le32_to_cpu(rec->e_cpos) +
+			ocfs2_rec_clusters(el, rec);
+		if (rec_range != trunc_range) {
+			ocfs2_error(inode->i_sb,
+				    "Inode %llu: error after split at cpos %u"
+				    "trunc len %u, existing record is (%u,%u)",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+				    cpos, len, le32_to_cpu(rec->e_cpos),
+				    ocfs2_rec_clusters(el, rec));
+			ret = -EROFS;
+			goto out;
+		}
+
+		ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
+					 cpos, len);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+out:
+	ocfs2_free_path(path);
+	return ret;
+}
+
+int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
 {
 	struct buffer_head *tl_bh = osb->osb_tl_bh;
 	struct ocfs2_dinode *di;
@@ -2464,10 +4539,10 @@
 	return current_tail == new_start;
 }
 
-static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
-				     handle_t *handle,
-				     u64 start_blk,
-				     unsigned int num_clusters)
+int ocfs2_truncate_log_append(struct ocfs2_super *osb,
+			      handle_t *handle,
+			      u64 start_blk,
+			      unsigned int num_clusters)
 {
 	int status, index;
 	unsigned int start_cluster, tl_count;
@@ -2623,7 +4698,7 @@
 }
 
 /* Expects you to already be holding tl_inode->i_mutex */
-static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
+int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
 {
 	int status;
 	unsigned int num_to_flush;
@@ -2957,6 +5032,219 @@
 	return status;
 }
 
+/*
+ * Delayed de-allocation of suballocator blocks.
+ *
+ * Some sets of block de-allocations might involve multiple suballocator inodes.
+ *
+ * The locking for this can get extremely complicated, especially when
+ * the suballocator inodes to delete from aren't known until deep
+ * within an unrelated codepath.
+ *
+ * ocfs2_extent_block structures are a good example of this - an inode
+ * btree could have been grown by any number of nodes each allocating
+ * out of their own suballoc inode.
+ *
+ * These structures allow the delay of block de-allocation until a
+ * later time, when locking of multiple cluster inodes won't cause
+ * deadlock.
+ */
+
+/*
+ * Describes a single block free from a suballocator
+ */
+struct ocfs2_cached_block_free {
+	struct ocfs2_cached_block_free		*free_next;
+	u64					free_blk;
+	unsigned int				free_bit;
+};
+
+struct ocfs2_per_slot_free_list {
+	struct ocfs2_per_slot_free_list		*f_next_suballocator;
+	int					f_inode_type;
+	int					f_slot;
+	struct ocfs2_cached_block_free		*f_first;
+};
+
+static int ocfs2_free_cached_items(struct ocfs2_super *osb,
+				   int sysfile_type,
+				   int slot,
+				   struct ocfs2_cached_block_free *head)
+{
+	int ret;
+	u64 bg_blkno;
+	handle_t *handle;
+	struct inode *inode;
+	struct buffer_head *di_bh = NULL;
+	struct ocfs2_cached_block_free *tmp;
+
+	inode = ocfs2_get_system_file_inode(osb, sysfile_type, slot);
+	if (!inode) {
+		ret = -EINVAL;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	mutex_lock(&inode->i_mutex);
+
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_mutex;
+	}
+
+	handle = ocfs2_start_trans(osb, OCFS2_SUBALLOC_FREE);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		mlog_errno(ret);
+		goto out_unlock;
+	}
+
+	while (head) {
+		bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
+						      head->free_bit);
+		mlog(0, "Free bit: (bit %u, blkno %llu)\n",
+		     head->free_bit, (unsigned long long)head->free_blk);
+
+		ret = ocfs2_free_suballoc_bits(handle, inode, di_bh,
+					       head->free_bit, bg_blkno, 1);
+		if (ret) {
+			mlog_errno(ret);
+			goto out_journal;
+		}
+
+		ret = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_FREE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out_journal;
+		}
+
+		tmp = head;
+		head = head->free_next;
+		kfree(tmp);
+	}
+
+out_journal:
+	ocfs2_commit_trans(osb, handle);
+
+out_unlock:
+	ocfs2_meta_unlock(inode, 1);
+	brelse(di_bh);
+out_mutex:
+	mutex_unlock(&inode->i_mutex);
+	iput(inode);
+out:
+	while(head) {
+		/* Premature exit may have left some dangling items. */
+		tmp = head;
+		head = head->free_next;
+		kfree(tmp);
+	}
+
+	return ret;
+}
+
+int ocfs2_run_deallocs(struct ocfs2_super *osb,
+		       struct ocfs2_cached_dealloc_ctxt *ctxt)
+{
+	int ret = 0, ret2;
+	struct ocfs2_per_slot_free_list *fl;
+
+	if (!ctxt)
+		return 0;
+
+	while (ctxt->c_first_suballocator) {
+		fl = ctxt->c_first_suballocator;
+
+		if (fl->f_first) {
+			mlog(0, "Free items: (type %u, slot %d)\n",
+			     fl->f_inode_type, fl->f_slot);
+			ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
+						       fl->f_slot, fl->f_first);
+			if (ret2)
+				mlog_errno(ret2);
+			if (!ret)
+				ret = ret2;
+		}
+
+		ctxt->c_first_suballocator = fl->f_next_suballocator;
+		kfree(fl);
+	}
+
+	return ret;
+}
+
+static struct ocfs2_per_slot_free_list *
+ocfs2_find_per_slot_free_list(int type,
+			      int slot,
+			      struct ocfs2_cached_dealloc_ctxt *ctxt)
+{
+	struct ocfs2_per_slot_free_list *fl = ctxt->c_first_suballocator;
+
+	while (fl) {
+		if (fl->f_inode_type == type && fl->f_slot == slot)
+			return fl;
+
+		fl = fl->f_next_suballocator;
+	}
+
+	fl = kmalloc(sizeof(*fl), GFP_NOFS);
+	if (fl) {
+		fl->f_inode_type = type;
+		fl->f_slot = slot;
+		fl->f_first = NULL;
+		fl->f_next_suballocator = ctxt->c_first_suballocator;
+
+		ctxt->c_first_suballocator = fl;
+	}
+	return fl;
+}
+
+static int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+				     int type, int slot, u64 blkno,
+				     unsigned int bit)
+{
+	int ret;
+	struct ocfs2_per_slot_free_list *fl;
+	struct ocfs2_cached_block_free *item;
+
+	fl = ocfs2_find_per_slot_free_list(type, slot, ctxt);
+	if (fl == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	item = kmalloc(sizeof(*item), GFP_NOFS);
+	if (item == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
+	     type, slot, bit, (unsigned long long)blkno);
+
+	item->free_blk = blkno;
+	item->free_bit = bit;
+	item->free_next = fl->f_first;
+
+	fl->f_first = item;
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+					 struct ocfs2_extent_block *eb)
+{
+	return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
+					 le16_to_cpu(eb->h_suballoc_slot),
+					 le64_to_cpu(eb->h_blkno),
+					 le16_to_cpu(eb->h_suballoc_bit));
+}
+
 /* This function will figure out whether the currently last extent
  * block will be deleted, and if it will, what the new last extent
  * block will be so we can update his h_next_leaf_blk field, as well
@@ -3238,27 +5526,10 @@
 			BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
 			BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
 
-			if (le16_to_cpu(eb->h_suballoc_slot) == 0) {
-				/*
-				 * This code only understands how to
-				 * lock the suballocator in slot 0,
-				 * which is fine because allocation is
-				 * only ever done out of that
-				 * suballocator too. A future version
-				 * might change that however, so avoid
-				 * a free if we don't know how to
-				 * handle it. This way an fs incompat
-				 * bit will not be necessary.
-				 */
-				ret = ocfs2_free_extent_block(handle,
-							      tc->tc_ext_alloc_inode,
-							      tc->tc_ext_alloc_bh,
-							      eb);
-
-				/* An error here is not fatal. */
-				if (ret < 0)
-					mlog_errno(ret);
-			}
+			ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
+			/* An error here is not fatal. */
+			if (ret < 0)
+				mlog_errno(ret);
 		} else {
 			deleted_eb = 0;
 		}
@@ -3397,9 +5668,9 @@
 	return ocfs2_journal_dirty_data(handle, bh);
 }
 
-static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize,
-				     struct page **pages, int numpages,
-				     u64 phys, handle_t *handle)
+static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start,
+				     loff_t end, struct page **pages,
+				     int numpages, u64 phys, handle_t *handle)
 {
 	int i, ret, partial = 0;
 	void *kaddr;
@@ -3412,26 +5683,14 @@
 	if (numpages == 0)
 		goto out;
 
-	from = isize & (PAGE_CACHE_SIZE - 1); /* 1st page offset */
-	if (PAGE_CACHE_SHIFT > OCFS2_SB(sb)->s_clustersize_bits) {
-		/*
-		 * Since 'from' has been capped to a value below page
-		 * size, this calculation won't be able to overflow
-		 * 'to'
-		 */
-		to = ocfs2_align_bytes_to_clusters(sb, from);
-
-		/*
-		 * The truncate tail in this case should never contain
-		 * more than one page at maximum. The loop below also
-		 * assumes this.
-		 */
-		BUG_ON(numpages != 1);
-	}
-
+	to = PAGE_CACHE_SIZE;
 	for(i = 0; i < numpages; i++) {
 		page = pages[i];
 
+		from = start & (PAGE_CACHE_SIZE - 1);
+		if ((end >> PAGE_CACHE_SHIFT) == page->index)
+			to = end & (PAGE_CACHE_SIZE - 1);
+
 		BUG_ON(from > PAGE_CACHE_SIZE);
 		BUG_ON(to > PAGE_CACHE_SIZE);
 
@@ -3468,10 +5727,7 @@
 
 		flush_dcache_page(page);
 
-		/*
-		 * Every page after the 1st one should be completely zero'd.
-		 */
-		from = 0;
+		start = (page->index + 1) << PAGE_CACHE_SHIFT;
 	}
 out:
 	if (pages) {
@@ -3484,24 +5740,26 @@
 	}
 }
 
-static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page **pages,
-				int *num, u64 *phys)
+static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
+				struct page **pages, int *num, u64 *phys)
 {
 	int i, numpages = 0, ret = 0;
-	unsigned int csize = OCFS2_SB(inode->i_sb)->s_clustersize;
 	unsigned int ext_flags;
 	struct super_block *sb = inode->i_sb;
 	struct address_space *mapping = inode->i_mapping;
 	unsigned long index;
-	u64 next_cluster_bytes;
+	loff_t last_page_bytes;
 
 	BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb)));
+	BUG_ON(start > end);
 
-	/* Cluster boundary, so we don't need to grab any pages. */
-	if ((isize & (csize - 1)) == 0)
+	if (start == end)
 		goto out;
 
-	ret = ocfs2_extent_map_get_blocks(inode, isize >> sb->s_blocksize_bits,
+	BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
+	       (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
+
+	ret = ocfs2_extent_map_get_blocks(inode, start >> sb->s_blocksize_bits,
 					  phys, NULL, &ext_flags);
 	if (ret) {
 		mlog_errno(ret);
@@ -3517,8 +5775,8 @@
 	if (ext_flags & OCFS2_EXT_UNWRITTEN)
 		goto out;
 
-	next_cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, isize);
-	index = isize >> PAGE_CACHE_SHIFT;
+	last_page_bytes = PAGE_ALIGN(end);
+	index = start >> PAGE_CACHE_SHIFT;
 	do {
 		pages[numpages] = grab_cache_page(mapping, index);
 		if (!pages[numpages]) {
@@ -3529,7 +5787,7 @@
 
 		numpages++;
 		index++;
-	} while (index < (next_cluster_bytes >> PAGE_CACHE_SHIFT));
+	} while (index < (last_page_bytes >> PAGE_CACHE_SHIFT));
 
 out:
 	if (ret != 0) {
@@ -3558,11 +5816,10 @@
  * otherwise block_write_full_page() will skip writeout of pages past
  * i_size. The new_i_size parameter is passed for this reason.
  */
-int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
-				 u64 new_i_size)
+int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
+				  u64 range_start, u64 range_end)
 {
 	int ret, numpages;
-	loff_t endbyte;
 	struct page **pages = NULL;
 	u64 phys;
 
@@ -3581,7 +5838,8 @@
 		goto out;
 	}
 
-	ret = ocfs2_grab_eof_pages(inode, new_i_size, pages, &numpages, &phys);
+	ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages,
+				   &numpages, &phys);
 	if (ret) {
 		mlog_errno(ret);
 		goto out;
@@ -3590,17 +5848,16 @@
 	if (numpages == 0)
 		goto out;
 
-	ocfs2_zero_cluster_pages(inode, new_i_size, pages, numpages, phys,
-				 handle);
+	ocfs2_zero_cluster_pages(inode, range_start, range_end, pages,
+				 numpages, phys, handle);
 
 	/*
 	 * Initiate writeout of the pages we zero'd here. We don't
 	 * wait on them - the truncate_inode_pages() call later will
 	 * do that for us.
 	 */
-	endbyte = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size);
-	ret = do_sync_mapping_range(inode->i_mapping, new_i_size,
-				    endbyte - 1, SYNC_FILE_RANGE_WRITE);
+	ret = do_sync_mapping_range(inode->i_mapping, range_start,
+				    range_end - 1, SYNC_FILE_RANGE_WRITE);
 	if (ret)
 		mlog_errno(ret);
 
@@ -3631,8 +5888,6 @@
 
 	mlog_entry_void();
 
-	down_write(&OCFS2_I(inode)->ip_alloc_sem);
-
 	new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
 						     i_size_read(inode));
 
@@ -3754,7 +6009,6 @@
 	goto start;
 
 bail:
-	up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
 	ocfs2_schedule_truncate_log_flush(osb, 1);
 
@@ -3764,6 +6018,8 @@
 	if (handle)
 		ocfs2_commit_trans(osb, handle);
 
+	ocfs2_run_deallocs(osb, &tc->tc_dealloc);
+
 	ocfs2_free_path(path);
 
 	/* This will drop the ext_alloc cluster lock for us */
@@ -3774,23 +6030,18 @@
 }
 
 /*
- * Expects the inode to already be locked. This will figure out which
- * inodes need to be locked and will put them on the returned truncate
- * context.
+ * Expects the inode to already be locked.
  */
 int ocfs2_prepare_truncate(struct ocfs2_super *osb,
 			   struct inode *inode,
 			   struct buffer_head *fe_bh,
 			   struct ocfs2_truncate_context **tc)
 {
-	int status, metadata_delete, i;
+	int status;
 	unsigned int new_i_clusters;
 	struct ocfs2_dinode *fe;
 	struct ocfs2_extent_block *eb;
-	struct ocfs2_extent_list *el;
 	struct buffer_head *last_eb_bh = NULL;
-	struct inode *ext_alloc_inode = NULL;
-	struct buffer_head *ext_alloc_bh = NULL;
 
 	mlog_entry_void();
 
@@ -3810,12 +6061,9 @@
 		mlog_errno(status);
 		goto bail;
 	}
+	ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
 
-	metadata_delete = 0;
 	if (fe->id2.i_list.l_tree_depth) {
-		/* If we have a tree, then the truncate may result in
-		 * metadata deletes. Figure this out from the
-		 * rightmost leaf block.*/
 		status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
 					  &last_eb_bh, OCFS2_BH_CACHED, inode);
 		if (status < 0) {
@@ -3830,43 +6078,10 @@
 			status = -EIO;
 			goto bail;
 		}
-		el = &(eb->h_list);
-
-		i = 0;
-		if (ocfs2_is_empty_extent(&el->l_recs[0]))
-			i = 1;
-		/*
-		 * XXX: Should we check that next_free_rec contains
-		 * the extent?
-		 */
-		if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_i_clusters)
-			metadata_delete = 1;
 	}
 
 	(*tc)->tc_last_eb_bh = last_eb_bh;
 
-	if (metadata_delete) {
-		mlog(0, "Will have to delete metadata for this trunc. "
-		     "locking allocator.\n");
-		ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
-		if (!ext_alloc_inode) {
-			status = -ENOMEM;
-			mlog_errno(status);
-			goto bail;
-		}
-
-		mutex_lock(&ext_alloc_inode->i_mutex);
-		(*tc)->tc_ext_alloc_inode = ext_alloc_inode;
-
-		status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
-		if (status < 0) {
-			mlog_errno(status);
-			goto bail;
-		}
-		(*tc)->tc_ext_alloc_bh = ext_alloc_bh;
-		(*tc)->tc_ext_alloc_locked = 1;
-	}
-
 	status = 0;
 bail:
 	if (status < 0) {
@@ -3880,16 +6095,13 @@
 
 static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
 {
-	if (tc->tc_ext_alloc_inode) {
-		if (tc->tc_ext_alloc_locked)
-			ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);
-
-		mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);
-		iput(tc->tc_ext_alloc_inode);
-	}
-
-	if (tc->tc_ext_alloc_bh)
-		brelse(tc->tc_ext_alloc_bh);
+	/*
+	 * The caller is responsible for completing deallocation
+	 * before freeing the context.
+	 */
+	if (tc->tc_dealloc.c_first_suballocator != NULL)
+		mlog(ML_NOTICE,
+		     "Truncate completion has non-empty dealloc context\n");
 
 	if (tc->tc_last_eb_bh)
 		brelse(tc->tc_last_eb_bh);
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index fbcb593..990df48 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -34,7 +34,17 @@
 			u32 cpos,
 			u64 start_blk,
 			u32 new_clusters,
+			u8 flags,
 			struct ocfs2_alloc_context *meta_ac);
+struct ocfs2_cached_dealloc_ctxt;
+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+			      handle_t *handle, u32 cpos, u32 len, u32 phys,
+			      struct ocfs2_alloc_context *meta_ac,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc);
+int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+			u32 cpos, u32 len, handle_t *handle,
+			struct ocfs2_alloc_context *meta_ac,
+			struct ocfs2_cached_dealloc_ctxt *dealloc);
 int ocfs2_num_free_extents(struct ocfs2_super *osb,
 			   struct inode *inode,
 			   struct ocfs2_dinode *fe);
@@ -62,17 +72,41 @@
 				      struct ocfs2_dinode **tl_copy);
 int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
 					 struct ocfs2_dinode *tl_copy);
+int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb);
+int ocfs2_truncate_log_append(struct ocfs2_super *osb,
+			      handle_t *handle,
+			      u64 start_blk,
+			      unsigned int num_clusters);
+int __ocfs2_flush_truncate_log(struct ocfs2_super *osb);
+
+/*
+ * Process local structure which describes the block unlinks done
+ * during an operation. This is populated via
+ * ocfs2_cache_block_dealloc().
+ *
+ * ocfs2_run_deallocs() should be called after the potentially
+ * de-allocating routines. No journal handles should be open, and most
+ * locks should have been dropped.
+ */
+struct ocfs2_cached_dealloc_ctxt {
+	struct ocfs2_per_slot_free_list		*c_first_suballocator;
+};
+static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
+{
+	c->c_first_suballocator = NULL;
+}
+int ocfs2_run_deallocs(struct ocfs2_super *osb,
+		       struct ocfs2_cached_dealloc_ctxt *ctxt);
 
 struct ocfs2_truncate_context {
-	struct inode *tc_ext_alloc_inode;
-	struct buffer_head *tc_ext_alloc_bh;
+	struct ocfs2_cached_dealloc_ctxt tc_dealloc;
 	int tc_ext_alloc_locked; /* is it cluster locked? */
 	/* these get destroyed once it's passed to ocfs2_commit_truncate. */
 	struct buffer_head *tc_last_eb_bh;
 };
 
-int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
-				 u64 new_i_size);
+int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
+				  u64 range_start, u64 range_end);
 int ocfs2_prepare_truncate(struct ocfs2_super *osb,
 			   struct inode *inode,
 			   struct buffer_head *fe_bh,
@@ -84,6 +118,7 @@
 
 int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
 		    u32 cpos, struct buffer_head **leaf_bh);
+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster);
 
 /*
  * Helper function to look at the # of clusters in an extent record.
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index a480b09..84bf6e7 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -684,6 +684,8 @@
 	     bh = bh->b_this_page, block_start += bsize) {
 		block_end = block_start + bsize;
 
+		clear_buffer_new(bh);
+
 		/*
 		 * Ignore blocks outside of our i/o range -
 		 * they may belong to unallocated clusters.
@@ -698,9 +700,8 @@
 		 * For an allocating write with cluster size >= page
 		 * size, we always write the entire page.
 		 */
-
-		if (buffer_new(bh))
-			clear_buffer_new(bh);
+		if (new)
+			set_buffer_new(bh);
 
 		if (!buffer_mapped(bh)) {
 			map_bh(bh, inode->i_sb, *p_blkno);
@@ -711,7 +712,8 @@
 			if (!buffer_uptodate(bh))
 				set_buffer_uptodate(bh);
 		} else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
-		     (block_start < from || block_end > to)) {
+			   !buffer_new(bh) &&
+			   (block_start < from || block_end > to)) {
 			ll_rw_block(READ, 1, &bh);
 			*wait_bh++=bh;
 		}
@@ -738,18 +740,13 @@
 	bh = head;
 	block_start = 0;
 	do {
-		void *kaddr;
-
 		block_end = block_start + bsize;
 		if (block_end <= from)
 			goto next_bh;
 		if (block_start >= to)
 			break;
 
-		kaddr = kmap_atomic(page, KM_USER0);
-		memset(kaddr+block_start, 0, bh->b_size);
-		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
+		zero_user_page(page, block_start, bh->b_size, KM_USER0);
 		set_buffer_uptodate(bh);
 		mark_buffer_dirty(bh);
 
@@ -761,217 +758,240 @@
 	return ret;
 }
 
+#if (PAGE_CACHE_SIZE >= OCFS2_MAX_CLUSTERSIZE)
+#define OCFS2_MAX_CTXT_PAGES	1
+#else
+#define OCFS2_MAX_CTXT_PAGES	(OCFS2_MAX_CLUSTERSIZE / PAGE_CACHE_SIZE)
+#endif
+
+#define OCFS2_MAX_CLUSTERS_PER_PAGE	(PAGE_CACHE_SIZE / OCFS2_MIN_CLUSTERSIZE)
+
 /*
- * This will copy user data from the buffer page in the splice
- * context.
- *
- * For now, we ignore SPLICE_F_MOVE as that would require some extra
- * communication out all the way to ocfs2_write().
+ * Describe the state of a single cluster to be written to.
  */
-int ocfs2_map_and_write_splice_data(struct inode *inode,
-				  struct ocfs2_write_ctxt *wc, u64 *p_blkno,
-				  unsigned int *ret_from, unsigned int *ret_to)
+struct ocfs2_write_cluster_desc {
+	u32		c_cpos;
+	u32		c_phys;
+	/*
+	 * Give this a unique field because c_phys eventually gets
+	 * filled.
+	 */
+	unsigned	c_new;
+	unsigned	c_unwritten;
+};
+
+static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
 {
-	int ret;
-	unsigned int to, from, cluster_start, cluster_end;
-	char *src, *dst;
-	struct ocfs2_splice_write_priv *sp = wc->w_private;
-	struct pipe_buffer *buf = sp->s_buf;
-	unsigned long bytes, src_from;
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-
-	ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
-					&cluster_end);
-
-	from = sp->s_offset;
-	src_from = sp->s_buf_offset;
-	bytes = wc->w_count;
-
-	if (wc->w_large_pages) {
-		/*
-		 * For cluster size < page size, we have to
-		 * calculate pos within the cluster and obey
-		 * the rightmost boundary.
-		 */
-		bytes = min(bytes, (unsigned long)(osb->s_clustersize
-				   - (wc->w_pos & (osb->s_clustersize - 1))));
-	}
-	to = from + bytes;
-
-	BUG_ON(from > PAGE_CACHE_SIZE);
-	BUG_ON(to > PAGE_CACHE_SIZE);
-	BUG_ON(from < cluster_start);
-	BUG_ON(to > cluster_end);
-
-	if (wc->w_this_page_new)
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    cluster_start, cluster_end, 1);
-	else
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    from, to, 0);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	src = buf->ops->map(sp->s_pipe, buf, 1);
-	dst = kmap_atomic(wc->w_this_page, KM_USER1);
-	memcpy(dst + from, src + src_from, bytes);
-	kunmap_atomic(wc->w_this_page, KM_USER1);
-	buf->ops->unmap(sp->s_pipe, buf, src);
-
-	wc->w_finished_copy = 1;
-
-	*ret_from = from;
-	*ret_to = to;
-out:
-
-	return bytes ? (unsigned int)bytes : ret;
+	return d->c_new || d->c_unwritten;
 }
 
-/*
- * This will copy user data from the iovec in the buffered write
- * context.
- */
-int ocfs2_map_and_write_user_data(struct inode *inode,
-				  struct ocfs2_write_ctxt *wc, u64 *p_blkno,
-				  unsigned int *ret_from, unsigned int *ret_to)
-{
-	int ret;
-	unsigned int to, from, cluster_start, cluster_end;
-	unsigned long bytes, src_from;
-	char *dst;
-	struct ocfs2_buffered_write_priv *bp = wc->w_private;
-	const struct iovec *cur_iov = bp->b_cur_iov;
-	char __user *buf;
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+struct ocfs2_write_ctxt {
+	/* Logical cluster position / len of write */
+	u32				w_cpos;
+	u32				w_clen;
 
-	ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
-					&cluster_end);
-
-	buf = cur_iov->iov_base + bp->b_cur_off;
-	src_from = (unsigned long)buf & ~PAGE_CACHE_MASK;
-
-	from = wc->w_pos & (PAGE_CACHE_SIZE - 1);
+	struct ocfs2_write_cluster_desc	w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
 
 	/*
-	 * This is a lot of comparisons, but it reads quite
-	 * easily, which is important here.
-	 */
-	/* Stay within the src page */
-	bytes = PAGE_SIZE - src_from;
-	/* Stay within the vector */
-	bytes = min(bytes,
-		    (unsigned long)(cur_iov->iov_len - bp->b_cur_off));
-	/* Stay within count */
-	bytes = min(bytes, (unsigned long)wc->w_count);
-	/*
-	 * For clustersize > page size, just stay within
-	 * target page, otherwise we have to calculate pos
-	 * within the cluster and obey the rightmost
-	 * boundary.
-	 */
-	if (wc->w_large_pages) {
-		/*
-		 * For cluster size < page size, we have to
-		 * calculate pos within the cluster and obey
-		 * the rightmost boundary.
-		 */
-		bytes = min(bytes, (unsigned long)(osb->s_clustersize
-				   - (wc->w_pos & (osb->s_clustersize - 1))));
-	} else {
-		/*
-		 * cluster size > page size is the most common
-		 * case - we just stay within the target page
-		 * boundary.
-		 */
-		bytes = min(bytes, PAGE_CACHE_SIZE - from);
-	}
-
-	to = from + bytes;
-
-	BUG_ON(from > PAGE_CACHE_SIZE);
-	BUG_ON(to > PAGE_CACHE_SIZE);
-	BUG_ON(from < cluster_start);
-	BUG_ON(to > cluster_end);
-
-	if (wc->w_this_page_new)
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    cluster_start, cluster_end, 1);
-	else
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    from, to, 0);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	dst = kmap(wc->w_this_page);
-	memcpy(dst + from, bp->b_src_buf + src_from, bytes);
-	kunmap(wc->w_this_page);
-
-	/*
-	 * XXX: This is slow, but simple. The caller of
-	 * ocfs2_buffered_write_cluster() is responsible for
-	 * passing through the iovecs, so it's difficult to
-	 * predict what our next step is in here after our
-	 * initial write. A future version should be pushing
-	 * that iovec manipulation further down.
+	 * This is true if page_size > cluster_size.
 	 *
-	 * By setting this, we indicate that a copy from user
-	 * data was done, and subsequent calls for this
-	 * cluster will skip copying more data.
+	 * It triggers a set of special cases during write which might
+	 * have to deal with allocating writes to partial pages.
 	 */
-	wc->w_finished_copy = 1;
+	unsigned int			w_large_pages;
 
-	*ret_from = from;
-	*ret_to = to;
-out:
+	/*
+	 * Pages involved in this write.
+	 *
+	 * w_target_page is the page being written to by the user.
+	 *
+	 * w_pages is an array of pages which always contains
+	 * w_target_page, and in the case of an allocating write with
+	 * page_size < cluster size, it will contain zero'd and mapped
+	 * pages adjacent to w_target_page which need to be written
+	 * out in so that future reads from that region will get
+	 * zero's.
+	 */
+	struct page			*w_pages[OCFS2_MAX_CTXT_PAGES];
+	unsigned int			w_num_pages;
+	struct page			*w_target_page;
 
-	return bytes ? (unsigned int)bytes : ret;
+	/*
+	 * ocfs2_write_end() uses this to know what the real range to
+	 * write in the target should be.
+	 */
+	unsigned int			w_target_from;
+	unsigned int			w_target_to;
+
+	/*
+	 * We could use journal_current_handle() but this is cleaner,
+	 * IMHO -Mark
+	 */
+	handle_t			*w_handle;
+
+	struct buffer_head		*w_di_bh;
+
+	struct ocfs2_cached_dealloc_ctxt w_dealloc;
+};
+
+static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
+{
+	int i;
+
+	for(i = 0; i < wc->w_num_pages; i++) {
+		if (wc->w_pages[i] == NULL)
+			continue;
+
+		unlock_page(wc->w_pages[i]);
+		mark_page_accessed(wc->w_pages[i]);
+		page_cache_release(wc->w_pages[i]);
+	}
+
+	brelse(wc->w_di_bh);
+	kfree(wc);
+}
+
+static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
+				  struct ocfs2_super *osb, loff_t pos,
+				  unsigned len, struct buffer_head *di_bh)
+{
+	struct ocfs2_write_ctxt *wc;
+
+	wc = kzalloc(sizeof(struct ocfs2_write_ctxt), GFP_NOFS);
+	if (!wc)
+		return -ENOMEM;
+
+	wc->w_cpos = pos >> osb->s_clustersize_bits;
+	wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
+	get_bh(di_bh);
+	wc->w_di_bh = di_bh;
+
+	if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
+		wc->w_large_pages = 1;
+	else
+		wc->w_large_pages = 0;
+
+	ocfs2_init_dealloc_ctxt(&wc->w_dealloc);
+
+	*wcp = wc;
+
+	return 0;
 }
 
 /*
- * Map, fill and write a page to disk.
- *
- * The work of copying data is done via callback.  Newly allocated
- * pages which don't take user data will be zero'd (set 'new' to
- * indicate an allocating write)
- *
- * Returns a negative error code or the number of bytes copied into
- * the page.
+ * If a page has any new buffers, zero them out here, and mark them uptodate
+ * and dirty so they'll be written out (in order to prevent uninitialised
+ * block data from leaking). And clear the new bit.
  */
-static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
-				 u64 *p_blkno, struct page *page,
-				 struct ocfs2_write_ctxt *wc, int new)
+static void ocfs2_zero_new_buffers(struct page *page, unsigned from, unsigned to)
 {
-	int ret, copied = 0;
-	unsigned int from = 0, to = 0;
-	unsigned int cluster_start, cluster_end;
-	unsigned int zero_from = 0, zero_to = 0;
+	unsigned int block_start, block_end;
+	struct buffer_head *head, *bh;
 
-	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), wc->w_cpos,
+	BUG_ON(!PageLocked(page));
+	if (!page_has_buffers(page))
+		return;
+
+	bh = head = page_buffers(page);
+	block_start = 0;
+	do {
+		block_end = block_start + bh->b_size;
+
+		if (buffer_new(bh)) {
+			if (block_end > from && block_start < to) {
+				if (!PageUptodate(page)) {
+					unsigned start, end;
+
+					start = max(from, block_start);
+					end = min(to, block_end);
+
+					zero_user_page(page, start, end - start, KM_USER0);
+					set_buffer_uptodate(bh);
+				}
+
+				clear_buffer_new(bh);
+				mark_buffer_dirty(bh);
+			}
+		}
+
+		block_start = block_end;
+		bh = bh->b_this_page;
+	} while (bh != head);
+}
+
+/*
+ * Only called when we have a failure during allocating write to write
+ * zero's to the newly allocated region.
+ */
+static void ocfs2_write_failure(struct inode *inode,
+				struct ocfs2_write_ctxt *wc,
+				loff_t user_pos, unsigned user_len)
+{
+	int i;
+	unsigned from, to;
+	struct page *tmppage;
+
+	ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len);
+
+	if (wc->w_large_pages) {
+		from = wc->w_target_from;
+		to = wc->w_target_to;
+	} else {
+		from = 0;
+		to = PAGE_CACHE_SIZE;
+	}
+
+	for(i = 0; i < wc->w_num_pages; i++) {
+		tmppage = wc->w_pages[i];
+
+		if (ocfs2_should_order_data(inode))
+			walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+					  from, to, NULL,
+					  ocfs2_journal_dirty_data);
+
+		block_commit_write(tmppage, from, to);
+	}
+}
+
+static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
+					struct ocfs2_write_ctxt *wc,
+					struct page *page, u32 cpos,
+					loff_t user_pos, unsigned user_len,
+					int new)
+{
+	int ret;
+	unsigned int map_from = 0, map_to = 0;
+	unsigned int cluster_start, cluster_end;
+	unsigned int user_data_from = 0, user_data_to = 0;
+
+	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
 					&cluster_start, &cluster_end);
 
-	if ((wc->w_pos >> PAGE_CACHE_SHIFT) == page->index
-	    && !wc->w_finished_copy) {
+	if (page == wc->w_target_page) {
+		map_from = user_pos & (PAGE_CACHE_SIZE - 1);
+		map_to = map_from + user_len;
 
-		wc->w_this_page = page;
-		wc->w_this_page_new = new;
-		ret = wc->w_write_data_page(inode, wc, p_blkno, &from, &to);
-		if (ret < 0) {
+		if (new)
+			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+						    cluster_start, cluster_end,
+						    new);
+		else
+			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+						    map_from, map_to, new);
+		if (ret) {
 			mlog_errno(ret);
 			goto out;
 		}
 
-		copied = ret;
-
-		zero_from = from;
-		zero_to = to;
+		user_data_from = map_from;
+		user_data_to = map_to;
 		if (new) {
-			from = cluster_start;
-			to = cluster_end;
+			map_from = cluster_start;
+			map_to = cluster_end;
 		}
+
+		wc->w_target_from = map_from;
+		wc->w_target_to = map_to;
 	} else {
 		/*
 		 * If we haven't allocated the new page yet, we
@@ -980,11 +1000,11 @@
 		 */
 		BUG_ON(!new);
 
-		from = cluster_start;
-		to = cluster_end;
+		map_from = cluster_start;
+		map_to = cluster_end;
 
 		ret = ocfs2_map_page_blocks(page, p_blkno, inode,
-					    cluster_start, cluster_end, 1);
+					    cluster_start, cluster_end, new);
 		if (ret) {
 			mlog_errno(ret);
 			goto out;
@@ -1003,108 +1023,113 @@
 	 */
 	if (new && !PageUptodate(page))
 		ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),
-					 wc->w_cpos, zero_from, zero_to);
+					 cpos, user_data_from, user_data_to);
 
 	flush_dcache_page(page);
 
-	if (ocfs2_should_order_data(inode)) {
-		ret = walk_page_buffers(handle,
-					page_buffers(page),
-					from, to, NULL,
-					ocfs2_journal_dirty_data);
-		if (ret < 0)
-			mlog_errno(ret);
-	}
-
-	/*
-	 * We don't use generic_commit_write() because we need to
-	 * handle our own i_size update.
-	 */
-	ret = block_commit_write(page, from, to);
-	if (ret)
-		mlog_errno(ret);
 out:
-
-	return copied ? copied : ret;
+	return ret;
 }
 
 /*
- * Do the actual write of some data into an inode. Optionally allocate
- * in order to fulfill the write.
- *
- * cpos is the logical cluster offset within the file to write at
- *
- * 'phys' is the physical mapping of that offset. a 'phys' value of
- * zero indicates that allocation is required. In this case, data_ac
- * and meta_ac should be valid (meta_ac can be null if metadata
- * allocation isn't required).
+ * This function will only grab one clusters worth of pages.
  */
-static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
-			   struct buffer_head *di_bh,
-			   struct ocfs2_alloc_context *data_ac,
-			   struct ocfs2_alloc_context *meta_ac,
-			   struct ocfs2_write_ctxt *wc)
+static int ocfs2_grab_pages_for_write(struct address_space *mapping,
+				      struct ocfs2_write_ctxt *wc,
+				      u32 cpos, loff_t user_pos, int new,
+				      struct page *mmap_page)
 {
-	int ret, i, numpages = 1, new;
-	unsigned int copied = 0;
-	u32 tmp_pos;
-	u64 v_blkno, p_blkno;
-	struct address_space *mapping = file->f_mapping;
+	int ret = 0, i;
+	unsigned long start, target_index, index;
 	struct inode *inode = mapping->host;
-	unsigned long index, start;
-	struct page **cpages;
 
-	new = phys == 0 ? 1 : 0;
+	target_index = user_pos >> PAGE_CACHE_SHIFT;
 
 	/*
 	 * Figure out how many pages we'll be manipulating here. For
 	 * non allocating write, we just change the one
 	 * page. Otherwise, we'll need a whole clusters worth.
 	 */
-	if (new)
-		numpages = ocfs2_pages_per_cluster(inode->i_sb);
-
-	cpages = kzalloc(sizeof(*cpages) * numpages, GFP_NOFS);
-	if (!cpages) {
-		ret = -ENOMEM;
-		mlog_errno(ret);
-		return ret;
-	}
-
-	/*
-	 * Fill our page array first. That way we've grabbed enough so
-	 * that we can zero and flush if we error after adding the
-	 * extent.
-	 */
 	if (new) {
-		start = ocfs2_align_clusters_to_page_index(inode->i_sb,
-							   wc->w_cpos);
-		v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, wc->w_cpos);
+		wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb);
+		start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);
 	} else {
-		start = wc->w_pos >> PAGE_CACHE_SHIFT;
-		v_blkno = wc->w_pos >> inode->i_sb->s_blocksize_bits;
+		wc->w_num_pages = 1;
+		start = target_index;
 	}
 
-	for(i = 0; i < numpages; i++) {
+	for(i = 0; i < wc->w_num_pages; i++) {
 		index = start + i;
 
-		cpages[i] = find_or_create_page(mapping, index, GFP_NOFS);
-		if (!cpages[i]) {
-			ret = -ENOMEM;
-			mlog_errno(ret);
-			goto out;
+		if (index == target_index && mmap_page) {
+			/*
+			 * ocfs2_pagemkwrite() is a little different
+			 * and wants us to directly use the page
+			 * passed in.
+			 */
+			lock_page(mmap_page);
+
+			if (mmap_page->mapping != mapping) {
+				unlock_page(mmap_page);
+				/*
+				 * Sanity check - the locking in
+				 * ocfs2_pagemkwrite() should ensure
+				 * that this code doesn't trigger.
+				 */
+				ret = -EINVAL;
+				mlog_errno(ret);
+				goto out;
+			}
+
+			page_cache_get(mmap_page);
+			wc->w_pages[i] = mmap_page;
+		} else {
+			wc->w_pages[i] = find_or_create_page(mapping, index,
+							     GFP_NOFS);
+			if (!wc->w_pages[i]) {
+				ret = -ENOMEM;
+				mlog_errno(ret);
+				goto out;
+			}
 		}
+
+		if (index == target_index)
+			wc->w_target_page = wc->w_pages[i];
 	}
+out:
+	return ret;
+}
+
+/*
+ * Prepare a single cluster for write one cluster into the file.
+ */
+static int ocfs2_write_cluster(struct address_space *mapping,
+			       u32 phys, unsigned int unwritten,
+			       struct ocfs2_alloc_context *data_ac,
+			       struct ocfs2_alloc_context *meta_ac,
+			       struct ocfs2_write_ctxt *wc, u32 cpos,
+			       loff_t user_pos, unsigned user_len)
+{
+	int ret, i, new, should_zero = 0;
+	u64 v_blkno, p_blkno;
+	struct inode *inode = mapping->host;
+
+	new = phys == 0 ? 1 : 0;
+	if (new || unwritten)
+		should_zero = 1;
 
 	if (new) {
+		u32 tmp_pos;
+
 		/*
 		 * This is safe to call with the page locks - it won't take
 		 * any additional semaphores or cluster locks.
 		 */
-		tmp_pos = wc->w_cpos;
+		tmp_pos = cpos;
 		ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,
-						 &tmp_pos, 1, di_bh, handle,
-						 data_ac, meta_ac, NULL);
+						 &tmp_pos, 1, 0, wc->w_di_bh,
+						 wc->w_handle, data_ac,
+						 meta_ac, NULL);
 		/*
 		 * This shouldn't happen because we must have already
 		 * calculated the correct meta data allocation required. The
@@ -1121,103 +1146,344 @@
 			mlog_errno(ret);
 			goto out;
 		}
+	} else if (unwritten) {
+		ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
+						wc->w_handle, cpos, 1, phys,
+						meta_ac, &wc->w_dealloc);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
 	}
 
+	if (should_zero)
+		v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, cpos);
+	else
+		v_blkno = user_pos >> inode->i_sb->s_blocksize_bits;
+
+	/*
+	 * The only reason this should fail is due to an inability to
+	 * find the extent added.
+	 */
 	ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,
 					  NULL);
 	if (ret < 0) {
-
-		/*
-		 * XXX: Should we go readonly here?
-		 */
-
-		mlog_errno(ret);
+		ocfs2_error(inode->i_sb, "Corrupting extend for inode %llu, "
+			    "at logical block %llu",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+			    (unsigned long long)v_blkno);
 		goto out;
 	}
 
 	BUG_ON(p_blkno == 0);
 
-	for(i = 0; i < numpages; i++) {
-		ret = ocfs2_write_data_page(inode, handle, &p_blkno, cpages[i],
-					    wc, new);
-		if (ret < 0) {
+	for(i = 0; i < wc->w_num_pages; i++) {
+		int tmpret;
+
+		tmpret = ocfs2_prepare_page_for_write(inode, &p_blkno, wc,
+						      wc->w_pages[i], cpos,
+						      user_pos, user_len,
+						      should_zero);
+		if (tmpret) {
+			mlog_errno(tmpret);
+			if (ret == 0)
+				tmpret = ret;
+		}
+	}
+
+	/*
+	 * We only have cleanup to do in case of allocating write.
+	 */
+	if (ret && new)
+		ocfs2_write_failure(inode, wc, user_pos, user_len);
+
+out:
+
+	return ret;
+}
+
+static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
+				       struct ocfs2_alloc_context *data_ac,
+				       struct ocfs2_alloc_context *meta_ac,
+				       struct ocfs2_write_ctxt *wc,
+				       loff_t pos, unsigned len)
+{
+	int ret, i;
+	struct ocfs2_write_cluster_desc *desc;
+
+	for (i = 0; i < wc->w_clen; i++) {
+		desc = &wc->w_desc[i];
+
+		ret = ocfs2_write_cluster(mapping, desc->c_phys,
+					  desc->c_unwritten, data_ac, meta_ac,
+					  wc, desc->c_cpos, pos, len);
+		if (ret) {
 			mlog_errno(ret);
 			goto out;
 		}
-
-		copied += ret;
 	}
 
+	ret = 0;
 out:
-	for(i = 0; i < numpages; i++) {
-		unlock_page(cpages[i]);
-		mark_page_accessed(cpages[i]);
-		page_cache_release(cpages[i]);
-	}
-	kfree(cpages);
-
-	return copied ? copied : ret;
-}
-
-static void ocfs2_write_ctxt_init(struct ocfs2_write_ctxt *wc,
-				  struct ocfs2_super *osb, loff_t pos,
-				  size_t count, ocfs2_page_writer *cb,
-				  void *cb_priv)
-{
-	wc->w_count = count;
-	wc->w_pos = pos;
-	wc->w_cpos = wc->w_pos >> osb->s_clustersize_bits;
-	wc->w_finished_copy = 0;
-
-	if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
-		wc->w_large_pages = 1;
-	else
-		wc->w_large_pages = 0;
-
-	wc->w_write_data_page = cb;
-	wc->w_private = cb_priv;
+	return ret;
 }
 
 /*
- * Write a cluster to an inode. The cluster may not be allocated yet,
- * in which case it will be. This only exists for buffered writes -
- * O_DIRECT takes a more "traditional" path through the kernel.
- *
- * The caller is responsible for incrementing pos, written counts, etc
- *
- * For file systems that don't support sparse files, pre-allocation
- * and page zeroing up until cpos should be done prior to this
- * function call.
- *
- * Callers should be holding i_sem, and the rw cluster lock.
- *
- * Returns the number of user bytes written, or less than zero for
- * error.
+ * ocfs2_write_end() wants to know which parts of the target page it
+ * should complete the write on. It's easiest to compute them ahead of
+ * time when a more complete view of the write is available.
  */
-ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
-				     size_t count, ocfs2_page_writer *actor,
-				     void *priv)
+static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
+					struct ocfs2_write_ctxt *wc,
+					loff_t pos, unsigned len, int alloc)
+{
+	struct ocfs2_write_cluster_desc *desc;
+
+	wc->w_target_from = pos & (PAGE_CACHE_SIZE - 1);
+	wc->w_target_to = wc->w_target_from + len;
+
+	if (alloc == 0)
+		return;
+
+	/*
+	 * Allocating write - we may have different boundaries based
+	 * on page size and cluster size.
+	 *
+	 * NOTE: We can no longer compute one value from the other as
+	 * the actual write length and user provided length may be
+	 * different.
+	 */
+
+	if (wc->w_large_pages) {
+		/*
+		 * We only care about the 1st and last cluster within
+		 * our range and whether they should be zero'd or not. Either
+		 * value may be extended out to the start/end of a
+		 * newly allocated cluster.
+		 */
+		desc = &wc->w_desc[0];
+		if (ocfs2_should_zero_cluster(desc))
+			ocfs2_figure_cluster_boundaries(osb,
+							desc->c_cpos,
+							&wc->w_target_from,
+							NULL);
+
+		desc = &wc->w_desc[wc->w_clen - 1];
+		if (ocfs2_should_zero_cluster(desc))
+			ocfs2_figure_cluster_boundaries(osb,
+							desc->c_cpos,
+							NULL,
+							&wc->w_target_to);
+	} else {
+		wc->w_target_from = 0;
+		wc->w_target_to = PAGE_CACHE_SIZE;
+	}
+}
+
+/*
+ * Populate each single-cluster write descriptor in the write context
+ * with information about the i/o to be done.
+ *
+ * Returns the number of clusters that will have to be allocated, as
+ * well as a worst case estimate of the number of extent records that
+ * would have to be created during a write to an unwritten region.
+ */
+static int ocfs2_populate_write_desc(struct inode *inode,
+				     struct ocfs2_write_ctxt *wc,
+				     unsigned int *clusters_to_alloc,
+				     unsigned int *extents_to_split)
+{
+	int ret;
+	struct ocfs2_write_cluster_desc *desc;
+	unsigned int num_clusters = 0;
+	unsigned int ext_flags = 0;
+	u32 phys = 0;
+	int i;
+
+	*clusters_to_alloc = 0;
+	*extents_to_split = 0;
+
+	for (i = 0; i < wc->w_clen; i++) {
+		desc = &wc->w_desc[i];
+		desc->c_cpos = wc->w_cpos + i;
+
+		if (num_clusters == 0) {
+			/*
+			 * Need to look up the next extent record.
+			 */
+			ret = ocfs2_get_clusters(inode, desc->c_cpos, &phys,
+						 &num_clusters, &ext_flags);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+
+			/*
+			 * Assume worst case - that we're writing in
+			 * the middle of the extent.
+			 *
+			 * We can assume that the write proceeds from
+			 * left to right, in which case the extent
+			 * insert code is smart enough to coalesce the
+			 * next splits into the previous records created.
+			 */
+			if (ext_flags & OCFS2_EXT_UNWRITTEN)
+				*extents_to_split = *extents_to_split + 2;
+		} else if (phys) {
+			/*
+			 * Only increment phys if it doesn't describe
+			 * a hole.
+			 */
+			phys++;
+		}
+
+		desc->c_phys = phys;
+		if (phys == 0) {
+			desc->c_new = 1;
+			*clusters_to_alloc = *clusters_to_alloc + 1;
+		}
+		if (ext_flags & OCFS2_EXT_UNWRITTEN)
+			desc->c_unwritten = 1;
+
+		num_clusters--;
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+int ocfs2_write_begin_nolock(struct address_space *mapping,
+			     loff_t pos, unsigned len, unsigned flags,
+			     struct page **pagep, void **fsdata,
+			     struct buffer_head *di_bh, struct page *mmap_page)
 {
 	int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
-	ssize_t written = 0;
-	u32 phys;
-	struct inode *inode = file->f_mapping->host;
+	unsigned int clusters_to_alloc, extents_to_split;
+	struct ocfs2_write_ctxt *wc;
+	struct inode *inode = mapping->host;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-	struct buffer_head *di_bh = NULL;
 	struct ocfs2_dinode *di;
 	struct ocfs2_alloc_context *data_ac = NULL;
 	struct ocfs2_alloc_context *meta_ac = NULL;
 	handle_t *handle;
-	struct ocfs2_write_ctxt wc;
 
-	ocfs2_write_ctxt_init(&wc, osb, pos, count, actor, priv);
+	ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
+	if (ret) {
+		mlog_errno(ret);
+		return ret;
+	}
 
-	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
+					&extents_to_split);
 	if (ret) {
 		mlog_errno(ret);
 		goto out;
 	}
-	di = (struct ocfs2_dinode *)di_bh->b_data;
+
+	di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+
+	/*
+	 * We set w_target_from, w_target_to here so that
+	 * ocfs2_write_end() knows which range in the target page to
+	 * write out. An allocation requires that we write the entire
+	 * cluster range.
+	 */
+	if (clusters_to_alloc || extents_to_split) {
+		/*
+		 * XXX: We are stretching the limits of
+		 * ocfs2_lock_allocators(). It greatly over-estimates
+		 * the work to be done.
+		 */
+		ret = ocfs2_lock_allocators(inode, di, clusters_to_alloc,
+					    extents_to_split, &data_ac, &meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		credits = ocfs2_calc_extend_credits(inode->i_sb, di,
+						    clusters_to_alloc);
+
+	}
+
+	ocfs2_set_target_boundaries(osb, wc, pos, len,
+				    clusters_to_alloc + extents_to_split);
+
+	handle = ocfs2_start_trans(osb, credits);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		mlog_errno(ret);
+		goto out;
+	}
+
+	wc->w_handle = handle;
+
+	/*
+	 * We don't want this to fail in ocfs2_write_end(), so do it
+	 * here.
+	 */
+	ret = ocfs2_journal_access(handle, inode, wc->w_di_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	/*
+	 * Fill our page array first. That way we've grabbed enough so
+	 * that we can zero and flush if we error after adding the
+	 * extent.
+	 */
+	ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
+					 clusters_to_alloc + extents_to_split,
+					 mmap_page);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
+					  len);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	if (data_ac)
+		ocfs2_free_alloc_context(data_ac);
+	if (meta_ac)
+		ocfs2_free_alloc_context(meta_ac);
+
+	*pagep = wc->w_target_page;
+	*fsdata = wc;
+	return 0;
+out_commit:
+	ocfs2_commit_trans(osb, handle);
+
+out:
+	ocfs2_free_write_ctxt(wc);
+
+	if (data_ac)
+		ocfs2_free_alloc_context(data_ac);
+	if (meta_ac)
+		ocfs2_free_alloc_context(meta_ac);
+	return ret;
+}
+
+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+		      loff_t pos, unsigned len, unsigned flags,
+		      struct page **pagep, void **fsdata)
+{
+	int ret;
+	struct buffer_head *di_bh = NULL;
+	struct inode *inode = mapping->host;
+
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret) {
+		mlog_errno(ret);
+		return ret;
+	}
 
 	/*
 	 * Take alloc sem here to prevent concurrent lookups. That way
@@ -1228,52 +1494,85 @@
 	 */
 	down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-	ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL, NULL);
-	if (ret) {
-		mlog_errno(ret);
-		goto out_meta;
-	}
-
-	/* phys == 0 means that allocation is required. */
-	if (phys == 0) {
-		ret = ocfs2_lock_allocators(inode, di, 1, &data_ac, &meta_ac);
-		if (ret) {
-			mlog_errno(ret);
-			goto out_meta;
-		}
-
-		credits = ocfs2_calc_extend_credits(inode->i_sb, di, 1);
-	}
-
 	ret = ocfs2_data_lock(inode, 1);
 	if (ret) {
 		mlog_errno(ret);
-		goto out_meta;
+		goto out_fail;
 	}
 
-	handle = ocfs2_start_trans(osb, credits);
-	if (IS_ERR(handle)) {
-		ret = PTR_ERR(handle);
-		mlog_errno(ret);
-		goto out_data;
-	}
-
-	written = ocfs2_write(file, phys, handle, di_bh, data_ac,
-			      meta_ac, &wc);
-	if (written < 0) {
-		ret = written;
-		mlog_errno(ret);
-		goto out_commit;
-	}
-
-	ret = ocfs2_journal_access(handle, inode, di_bh,
-				   OCFS2_JOURNAL_ACCESS_WRITE);
+	ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
+				       fsdata, di_bh, NULL);
 	if (ret) {
 		mlog_errno(ret);
-		goto out_commit;
+		goto out_fail_data;
 	}
 
-	pos += written;
+	brelse(di_bh);
+
+	return 0;
+
+out_fail_data:
+	ocfs2_data_unlock(inode, 1);
+out_fail:
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	brelse(di_bh);
+	ocfs2_meta_unlock(inode, 1);
+
+	return ret;
+}
+
+int ocfs2_write_end_nolock(struct address_space *mapping,
+			   loff_t pos, unsigned len, unsigned copied,
+			   struct page *page, void *fsdata)
+{
+	int i;
+	unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
+	struct inode *inode = mapping->host;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_write_ctxt *wc = fsdata;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+	handle_t *handle = wc->w_handle;
+	struct page *tmppage;
+
+	if (unlikely(copied < len)) {
+		if (!PageUptodate(wc->w_target_page))
+			copied = 0;
+
+		ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
+				       start+len);
+	}
+	flush_dcache_page(wc->w_target_page);
+
+	for(i = 0; i < wc->w_num_pages; i++) {
+		tmppage = wc->w_pages[i];
+
+		if (tmppage == wc->w_target_page) {
+			from = wc->w_target_from;
+			to = wc->w_target_to;
+
+			BUG_ON(from > PAGE_CACHE_SIZE ||
+			       to > PAGE_CACHE_SIZE ||
+			       to < from);
+		} else {
+			/*
+			 * Pages adjacent to the target (if any) imply
+			 * a hole-filling write in which case we want
+			 * to flush their entire range.
+			 */
+			from = 0;
+			to = PAGE_CACHE_SIZE;
+		}
+
+		if (ocfs2_should_order_data(inode))
+			walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+					  from, to, NULL,
+					  ocfs2_journal_dirty_data);
+
+		block_commit_write(tmppage, from, to);
+	}
+
+	pos += copied;
 	if (pos > inode->i_size) {
 		i_size_write(inode, pos);
 		mark_inode_dirty(inode);
@@ -1283,29 +1582,31 @@
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
 	di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+	ocfs2_journal_dirty(handle, wc->w_di_bh);
 
-	ret = ocfs2_journal_dirty(handle, di_bh);
-	if (ret)
-		mlog_errno(ret);
-
-out_commit:
 	ocfs2_commit_trans(osb, handle);
 
-out_data:
-	ocfs2_data_unlock(inode, 1);
+	ocfs2_run_deallocs(osb, &wc->w_dealloc);
 
-out_meta:
+	ocfs2_free_write_ctxt(wc);
+
+	return copied;
+}
+
+int ocfs2_write_end(struct file *file, struct address_space *mapping,
+		    loff_t pos, unsigned len, unsigned copied,
+		    struct page *page, void *fsdata)
+{
+	int ret;
+	struct inode *inode = mapping->host;
+
+	ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
+
+	ocfs2_data_unlock(inode, 1);
 	up_write(&OCFS2_I(inode)->ip_alloc_sem);
 	ocfs2_meta_unlock(inode, 1);
 
-out:
-	brelse(di_bh);
-	if (data_ac)
-		ocfs2_free_alloc_context(data_ac);
-	if (meta_ac)
-		ocfs2_free_alloc_context(meta_ac);
-
-	return written ? written : ret;
+	return ret;
 }
 
 const struct address_space_operations ocfs2_aops = {
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 45821d4..389579b 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -42,57 +42,22 @@
 			int (*fn)(	handle_t *handle,
 					struct buffer_head *bh));
 
-struct ocfs2_write_ctxt;
-typedef int (ocfs2_page_writer)(struct inode *, struct ocfs2_write_ctxt *,
-				u64 *, unsigned int *, unsigned int *);
+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+		      loff_t pos, unsigned len, unsigned flags,
+		      struct page **pagep, void **fsdata);
 
-ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
-				     size_t count, ocfs2_page_writer *actor,
-				     void *priv);
+int ocfs2_write_end(struct file *file, struct address_space *mapping,
+		    loff_t pos, unsigned len, unsigned copied,
+		    struct page *page, void *fsdata);
 
-struct ocfs2_write_ctxt {
-	size_t				w_count;
-	loff_t				w_pos;
-	u32				w_cpos;
-	unsigned int			w_finished_copy;
+int ocfs2_write_end_nolock(struct address_space *mapping,
+			   loff_t pos, unsigned len, unsigned copied,
+			   struct page *page, void *fsdata);
 
-	/* This is true if page_size > cluster_size */
-	unsigned int			w_large_pages;
-
-	/* Filler callback and private data */
-	ocfs2_page_writer		*w_write_data_page;
-	void				*w_private;
-
-	/* Only valid for the filler callback */
-	struct page			*w_this_page;
-	unsigned int			w_this_page_new;
-};
-
-struct ocfs2_buffered_write_priv {
-	char				*b_src_buf;
-	const struct iovec		*b_cur_iov; /* Current iovec */
-	size_t				b_cur_off; /* Offset in the
-						    * current iovec */
-};
-int ocfs2_map_and_write_user_data(struct inode *inode,
-				  struct ocfs2_write_ctxt *wc,
-				  u64 *p_blkno,
-				  unsigned int *ret_from,
-				  unsigned int *ret_to);
-
-struct ocfs2_splice_write_priv {
-	struct splice_desc		*s_sd;
-	struct pipe_buffer		*s_buf;
-	struct pipe_inode_info		*s_pipe;
-	/* Neither offset value is ever larger than one page */
-	unsigned int			s_offset;
-	unsigned int			s_buf_offset;
-};
-int ocfs2_map_and_write_splice_data(struct inode *inode,
-				    struct ocfs2_write_ctxt *wc,
-				    u64 *p_blkno,
-				    unsigned int *ret_from,
-				    unsigned int *ret_to);
+int ocfs2_write_begin_nolock(struct address_space *mapping,
+			     loff_t pos, unsigned len, unsigned flags,
+			     struct page **pagep, void **fsdata,
+			     struct buffer_head *di_bh, struct page *mmap_page);
 
 /* all ocfs2_dio_end_io()'s fault */
 #define ocfs2_iocb_is_rw_locked(iocb) \
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 9791134..2bd7f78 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -1335,6 +1335,7 @@
 	ret = wait_event_interruptible(o2hb_steady_queue,
 				atomic_read(&reg->hr_steady_iterations) == 0);
 	if (ret) {
+		/* We got interrupted (hello ptrace!).  Clean up */
 		spin_lock(&o2hb_live_lock);
 		hb_task = reg->hr_task;
 		reg->hr_task = NULL;
@@ -1345,7 +1346,16 @@
 		goto out;
 	}
 
-	ret = count;
+	/* Ok, we were woken.  Make sure it wasn't by drop_item() */
+	spin_lock(&o2hb_live_lock);
+	hb_task = reg->hr_task;
+	spin_unlock(&o2hb_live_lock);
+
+	if (hb_task)
+		ret = count;
+	else
+		ret = -EIO;
+
 out:
 	if (filp)
 		fput(filp);
@@ -1523,6 +1533,15 @@
 	if (hb_task)
 		kthread_stop(hb_task);
 
+	/*
+	 * If we're racing a dev_write(), we need to wake them.  They will
+	 * check reg->hr_task
+	 */
+	if (atomic_read(&reg->hr_steady_iterations) != 0) {
+		atomic_set(&reg->hr_steady_iterations, 0);
+		wake_up(&o2hb_steady_queue);
+	}
+
 	config_item_put(item);
 }
 
@@ -1665,7 +1684,67 @@
 }
 EXPORT_SYMBOL_GPL(o2hb_setup_callback);
 
-int o2hb_register_callback(struct o2hb_callback_func *hc)
+static struct o2hb_region *o2hb_find_region(const char *region_uuid)
+{
+	struct o2hb_region *p, *reg = NULL;
+
+	assert_spin_locked(&o2hb_live_lock);
+
+	list_for_each_entry(p, &o2hb_all_regions, hr_all_item) {
+		if (!strcmp(region_uuid, config_item_name(&p->hr_item))) {
+			reg = p;
+			break;
+		}
+	}
+
+	return reg;
+}
+
+static int o2hb_region_get(const char *region_uuid)
+{
+	int ret = 0;
+	struct o2hb_region *reg;
+
+	spin_lock(&o2hb_live_lock);
+
+	reg = o2hb_find_region(region_uuid);
+	if (!reg)
+		ret = -ENOENT;
+	spin_unlock(&o2hb_live_lock);
+
+	if (ret)
+		goto out;
+
+	ret = o2nm_depend_this_node();
+	if (ret)
+		goto out;
+
+	ret = o2nm_depend_item(&reg->hr_item);
+	if (ret)
+		o2nm_undepend_this_node();
+
+out:
+	return ret;
+}
+
+static void o2hb_region_put(const char *region_uuid)
+{
+	struct o2hb_region *reg;
+
+	spin_lock(&o2hb_live_lock);
+
+	reg = o2hb_find_region(region_uuid);
+
+	spin_unlock(&o2hb_live_lock);
+
+	if (reg) {
+		o2nm_undepend_item(&reg->hr_item);
+		o2nm_undepend_this_node();
+	}
+}
+
+int o2hb_register_callback(const char *region_uuid,
+			   struct o2hb_callback_func *hc)
 {
 	struct o2hb_callback_func *tmp;
 	struct list_head *iter;
@@ -1681,6 +1760,12 @@
 		goto out;
 	}
 
+	if (region_uuid) {
+		ret = o2hb_region_get(region_uuid);
+		if (ret)
+			goto out;
+	}
+
 	down_write(&o2hb_callback_sem);
 
 	list_for_each(iter, &hbcall->list) {
@@ -1702,16 +1787,21 @@
 }
 EXPORT_SYMBOL_GPL(o2hb_register_callback);
 
-void o2hb_unregister_callback(struct o2hb_callback_func *hc)
+void o2hb_unregister_callback(const char *region_uuid,
+			      struct o2hb_callback_func *hc)
 {
 	BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
 
 	mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n",
 	     __builtin_return_address(0), hc);
 
+	/* XXX Can this happen _with_ a region reference? */
 	if (list_empty(&hc->hc_item))
 		return;
 
+	if (region_uuid)
+		o2hb_region_put(region_uuid);
+
 	down_write(&o2hb_callback_sem);
 
 	list_del_init(&hc->hc_item);
diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h
index cc6d40b..35397dd 100644
--- a/fs/ocfs2/cluster/heartbeat.h
+++ b/fs/ocfs2/cluster/heartbeat.h
@@ -69,8 +69,10 @@
 			 o2hb_cb_func *func,
 			 void *data,
 			 int priority);
-int o2hb_register_callback(struct o2hb_callback_func *hc);
-void o2hb_unregister_callback(struct o2hb_callback_func *hc);
+int o2hb_register_callback(const char *region_uuid,
+			   struct o2hb_callback_func *hc);
+void o2hb_unregister_callback(const char *region_uuid,
+			      struct o2hb_callback_func *hc);
 void o2hb_fill_node_map(unsigned long *map,
 			unsigned bytes);
 void o2hb_init(void);
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index 9f5ad0f..af2070d 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -900,6 +900,46 @@
 	},
 };
 
+int o2nm_depend_item(struct config_item *item)
+{
+	return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
+}
+
+void o2nm_undepend_item(struct config_item *item)
+{
+	configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item);
+}
+
+int o2nm_depend_this_node(void)
+{
+	int ret = 0;
+	struct o2nm_node *local_node;
+
+	local_node = o2nm_get_node_by_num(o2nm_this_node());
+	if (!local_node) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = o2nm_depend_item(&local_node->nd_item);
+	o2nm_node_put(local_node);
+
+out:
+	return ret;
+}
+
+void o2nm_undepend_this_node(void)
+{
+	struct o2nm_node *local_node;
+
+	local_node = o2nm_get_node_by_num(o2nm_this_node());
+	BUG_ON(!local_node);
+
+	o2nm_undepend_item(&local_node->nd_item);
+	o2nm_node_put(local_node);
+}
+
+
 static void __exit exit_o2nm(void)
 {
 	if (ocfs2_table_header)
@@ -934,7 +974,7 @@
 		goto out_sysctl;
 
 	config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
-	init_MUTEX(&o2nm_cluster_group.cs_subsys.su_sem);
+	mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex);
 	ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
 	if (ret) {
 		printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h
index 0705221..7c86036 100644
--- a/fs/ocfs2/cluster/nodemanager.h
+++ b/fs/ocfs2/cluster/nodemanager.h
@@ -77,4 +77,9 @@
 void o2nm_node_get(struct o2nm_node *node);
 void o2nm_node_put(struct o2nm_node *node);
 
+int o2nm_depend_item(struct config_item *item);
+void o2nm_undepend_item(struct config_item *item);
+int o2nm_depend_this_node(void);
+void o2nm_undepend_this_node(void);
+
 #endif /* O2CLUSTER_NODEMANAGER_H */
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 0b229a9..f0bdfd9 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -261,14 +261,12 @@
 
 static void o2net_complete_nodes_nsw(struct o2net_node *nn)
 {
-	struct list_head *iter, *tmp;
+	struct o2net_status_wait *nsw, *tmp;
 	unsigned int num_kills = 0;
-	struct o2net_status_wait *nsw;
 
 	assert_spin_locked(&nn->nn_lock);
 
-	list_for_each_safe(iter, tmp, &nn->nn_status_list) {
-		nsw = list_entry(iter, struct o2net_status_wait, ns_node_item);
+	list_for_each_entry_safe(nsw, tmp, &nn->nn_status_list, ns_node_item) {
 		o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0);
 		num_kills++;
 	}
@@ -764,13 +762,10 @@
 
 void o2net_unregister_handler_list(struct list_head *list)
 {
-	struct list_head *pos, *n;
-	struct o2net_msg_handler *nmh;
+	struct o2net_msg_handler *nmh, *n;
 
 	write_lock(&o2net_handler_lock);
-	list_for_each_safe(pos, n, list) {
-		nmh = list_entry(pos, struct o2net_msg_handler,
-				 nh_unregister_item);
+	list_for_each_entry_safe(nmh, n, list, nh_unregister_item) {
 		mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n",
 		     nmh->nh_func, nmh->nh_msg_type, nmh->nh_key);
 		rb_erase(&nmh->nh_node, &o2net_handler_tree);
@@ -1638,8 +1633,8 @@
 
 void o2net_unregister_hb_callbacks(void)
 {
-	o2hb_unregister_callback(&o2net_hb_up);
-	o2hb_unregister_callback(&o2net_hb_down);
+	o2hb_unregister_callback(NULL, &o2net_hb_up);
+	o2hb_unregister_callback(NULL, &o2net_hb_down);
 }
 
 int o2net_register_hb_callbacks(void)
@@ -1651,9 +1646,9 @@
 	o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB,
 			    o2net_hb_node_up_cb, NULL, O2NET_HB_PRI);
 
-	ret = o2hb_register_callback(&o2net_hb_up);
+	ret = o2hb_register_callback(NULL, &o2net_hb_up);
 	if (ret == 0)
-		ret = o2hb_register_callback(&o2net_hb_down);
+		ret = o2hb_register_callback(NULL, &o2net_hb_down);
 
 	if (ret)
 		o2net_unregister_hb_callbacks();
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index c441ef1..0d5fdde 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -368,7 +368,7 @@
 		u32 offset = OCFS2_I(dir)->ip_clusters;
 
 		status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset,
-						    1, parent_fe_bh, handle,
+						    1, 0, parent_fe_bh, handle,
 						    data_ac, meta_ac, NULL);
 		BUG_ON(status == -EAGAIN);
 		if (status < 0) {
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index d836b98..6954565 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -1128,8 +1128,8 @@
 
 static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm)
 {
-	o2hb_unregister_callback(&dlm->dlm_hb_up);
-	o2hb_unregister_callback(&dlm->dlm_hb_down);
+	o2hb_unregister_callback(NULL, &dlm->dlm_hb_up);
+	o2hb_unregister_callback(NULL, &dlm->dlm_hb_down);
 	o2net_unregister_handler_list(&dlm->dlm_domain_handlers);
 }
 
@@ -1141,13 +1141,13 @@
 
 	o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB,
 			    dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI);
-	status = o2hb_register_callback(&dlm->dlm_hb_down);
+	status = o2hb_register_callback(NULL, &dlm->dlm_hb_down);
 	if (status)
 		goto bail;
 
 	o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB,
 			    dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI);
-	status = o2hb_register_callback(&dlm->dlm_hb_up);
+	status = o2hb_register_callback(NULL, &dlm->dlm_hb_up);
 	if (status)
 		goto bail;
 
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 6edffca..65b2b9b 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -192,25 +192,20 @@
 static void dlm_dump_mles(struct dlm_ctxt *dlm)
 {
 	struct dlm_master_list_entry *mle;
-	struct list_head *iter;
 	
 	mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
 	spin_lock(&dlm->master_lock);
-	list_for_each(iter, &dlm->master_list) {
-		mle = list_entry(iter, struct dlm_master_list_entry, list);
+	list_for_each_entry(mle, &dlm->master_list, list)
 		dlm_print_one_mle(mle);
-	}
 	spin_unlock(&dlm->master_lock);
 }
 
 int dlm_dump_all_mles(const char __user *data, unsigned int len)
 {
-	struct list_head *iter;
 	struct dlm_ctxt *dlm;
 
 	spin_lock(&dlm_domain_lock);
-	list_for_each(iter, &dlm_domains) {
-		dlm = list_entry (iter, struct dlm_ctxt, list);
+	list_for_each_entry(dlm, &dlm_domains, list) {
 		mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
 		dlm_dump_mles(dlm);
 	}
@@ -454,12 +449,10 @@
 			char *name, unsigned int namelen)
 {
 	struct dlm_master_list_entry *tmpmle;
-	struct list_head *iter;
 
 	assert_spin_locked(&dlm->master_lock);
 
-	list_for_each(iter, &dlm->master_list) {
-		tmpmle = list_entry(iter, struct dlm_master_list_entry, list);
+	list_for_each_entry(tmpmle, &dlm->master_list, list) {
 		if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
 			continue;
 		dlm_get_mle(tmpmle);
@@ -472,13 +465,10 @@
 void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up)
 {
 	struct dlm_master_list_entry *mle;
-	struct list_head *iter;
 
 	assert_spin_locked(&dlm->spinlock);
 	
-	list_for_each(iter, &dlm->mle_hb_events) {
-		mle = list_entry(iter, struct dlm_master_list_entry, 
-				 hb_events);
+	list_for_each_entry(mle, &dlm->mle_hb_events, hb_events) {
 		if (node_up)
 			dlm_mle_node_up(dlm, mle, NULL, idx);
 		else
@@ -2434,7 +2424,7 @@
 	int ret;
 	int i;
 	int count = 0;
-	struct list_head *queue, *iter;
+	struct list_head *queue;
 	struct dlm_lock *lock;
 
 	assert_spin_locked(&res->spinlock);
@@ -2453,8 +2443,7 @@
 	ret = 0;
 	queue = &res->granted;
 	for (i = 0; i < 3; i++) {
-		list_for_each(iter, queue) {
-			lock = list_entry(iter, struct dlm_lock, list);
+		list_for_each_entry(lock, queue, list) {
 			++count;
 			if (lock->ml.node == dlm->node_num) {
 				mlog(0, "found a lock owned by this node still "
@@ -2923,18 +2912,16 @@
 static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
 				      struct dlm_lock_resource *res)
 {
-	struct list_head *iter, *iter2;
 	struct list_head *queue = &res->granted;
 	int i, bit;
-	struct dlm_lock *lock;
+	struct dlm_lock *lock, *next;
 
 	assert_spin_locked(&res->spinlock);
 
 	BUG_ON(res->owner == dlm->node_num);
 
 	for (i=0; i<3; i++) {
-		list_for_each_safe(iter, iter2, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
+		list_for_each_entry_safe(lock, next, queue, list) {
 			if (lock->ml.node != dlm->node_num) {
 				mlog(0, "putting lock for node %u\n",
 				     lock->ml.node);
@@ -2976,7 +2963,6 @@
 {
 	int i;
 	struct list_head *queue = &res->granted;
-	struct list_head *iter;
 	struct dlm_lock *lock;
 	int nodenum;
 
@@ -2984,10 +2970,9 @@
 
 	spin_lock(&res->spinlock);
 	for (i=0; i<3; i++) {
-		list_for_each(iter, queue) {
+		list_for_each_entry(lock, queue, list) {
 			/* up to the caller to make sure this node
 			 * is alive */
-			lock = list_entry (iter, struct dlm_lock, list);
 			if (lock->ml.node != dlm->node_num) {
 				spin_unlock(&res->spinlock);
 				return lock->ml.node;
@@ -3234,8 +3219,7 @@
 
 void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
 {
-	struct list_head *iter, *iter2;
-	struct dlm_master_list_entry *mle;
+	struct dlm_master_list_entry *mle, *next;
 	struct dlm_lock_resource *res;
 	unsigned int hash;
 
@@ -3245,9 +3229,7 @@
 
 	/* clean the master list */
 	spin_lock(&dlm->master_lock);
-	list_for_each_safe(iter, iter2, &dlm->master_list) {
-		mle = list_entry(iter, struct dlm_master_list_entry, list);
-
+	list_for_each_entry_safe(mle, next, &dlm->master_list, list) {
 		BUG_ON(mle->type != DLM_MLE_BLOCK &&
 		       mle->type != DLM_MLE_MASTER &&
 		       mle->type != DLM_MLE_MIGRATION);
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 671c4ed..a2c3316 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -158,8 +158,7 @@
 	struct dlm_ctxt *dlm =
 		container_of(work, struct dlm_ctxt, dispatched_work);
 	LIST_HEAD(tmp_list);
-	struct list_head *iter, *iter2;
-	struct dlm_work_item *item;
+	struct dlm_work_item *item, *next;
 	dlm_workfunc_t *workfunc;
 	int tot=0;
 
@@ -167,13 +166,12 @@
 	list_splice_init(&dlm->work_list, &tmp_list);
 	spin_unlock(&dlm->work_lock);
 
-	list_for_each_safe(iter, iter2, &tmp_list) {
+	list_for_each_entry(item, &tmp_list, list) {
 		tot++;
 	}
 	mlog(0, "%s: work thread has %d work items\n", dlm->name, tot);
 
-	list_for_each_safe(iter, iter2, &tmp_list) {
-		item = list_entry(iter, struct dlm_work_item, list);
+	list_for_each_entry_safe(item, next, &tmp_list, list) {
 		workfunc = item->func;
 		list_del_init(&item->list);
 
@@ -549,7 +547,6 @@
 {
 	int status = 0;
 	struct dlm_reco_node_data *ndata;
-	struct list_head *iter;
 	int all_nodes_done;
 	int destroy = 0;
 	int pass = 0;
@@ -567,8 +564,7 @@
 
 	/* safe to access the node data list without a lock, since this
 	 * process is the only one to change the list */
-	list_for_each(iter, &dlm->reco.node_data) {
-		ndata = list_entry (iter, struct dlm_reco_node_data, list);
+	list_for_each_entry(ndata, &dlm->reco.node_data, list) {
 		BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
 		ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
 
@@ -655,9 +651,7 @@
 		 * done, or if anyone died */
 		all_nodes_done = 1;
 		spin_lock(&dlm_reco_state_lock);
-		list_for_each(iter, &dlm->reco.node_data) {
-			ndata = list_entry (iter, struct dlm_reco_node_data, list);
-
+		list_for_each_entry(ndata, &dlm->reco.node_data, list) {
 			mlog(0, "checking recovery state of node %u\n",
 			     ndata->node_num);
 			switch (ndata->state) {
@@ -774,16 +768,14 @@
 
 static void dlm_destroy_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
 {
-	struct list_head *iter, *iter2;
-	struct dlm_reco_node_data *ndata;
+	struct dlm_reco_node_data *ndata, *next;
 	LIST_HEAD(tmplist);
 
 	spin_lock(&dlm_reco_state_lock);
 	list_splice_init(&dlm->reco.node_data, &tmplist);
 	spin_unlock(&dlm_reco_state_lock);
 
-	list_for_each_safe(iter, iter2, &tmplist) {
-		ndata = list_entry (iter, struct dlm_reco_node_data, list);
+	list_for_each_entry_safe(ndata, next, &tmplist, list) {
 		list_del_init(&ndata->list);
 		kfree(ndata);
 	}
@@ -876,7 +868,6 @@
 	struct dlm_lock_resource *res;
 	struct dlm_ctxt *dlm;
 	LIST_HEAD(resources);
-	struct list_head *iter;
 	int ret;
 	u8 dead_node, reco_master;
 	int skip_all_done = 0;
@@ -920,8 +911,7 @@
 
 	/* any errors returned will be due to the new_master dying,
 	 * the dlm_reco_thread should detect this */
-	list_for_each(iter, &resources) {
-		res = list_entry (iter, struct dlm_lock_resource, recovering);
+	list_for_each_entry(res, &resources, recovering) {
 		ret = dlm_send_one_lockres(dlm, res, mres, reco_master,
 				   	DLM_MRES_RECOVERY);
 		if (ret < 0) {
@@ -983,7 +973,6 @@
 {
 	struct dlm_ctxt *dlm = data;
 	struct dlm_reco_data_done *done = (struct dlm_reco_data_done *)msg->buf;
-	struct list_head *iter;
 	struct dlm_reco_node_data *ndata = NULL;
 	int ret = -EINVAL;
 
@@ -1000,8 +989,7 @@
 			dlm->reco.dead_node, done->node_idx, dlm->node_num);
 
 	spin_lock(&dlm_reco_state_lock);
-	list_for_each(iter, &dlm->reco.node_data) {
-		ndata = list_entry (iter, struct dlm_reco_node_data, list);
+	list_for_each_entry(ndata, &dlm->reco.node_data, list) {
 		if (ndata->node_num != done->node_idx)
 			continue;
 
@@ -1049,13 +1037,11 @@
 					struct list_head *list,
 				       	u8 dead_node)
 {
-	struct dlm_lock_resource *res;
-	struct list_head *iter, *iter2;
+	struct dlm_lock_resource *res, *next;
 	struct dlm_lock *lock;
 
 	spin_lock(&dlm->spinlock);
-	list_for_each_safe(iter, iter2, &dlm->reco.resources) {
-		res = list_entry (iter, struct dlm_lock_resource, recovering);
+	list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
 		/* always prune any $RECOVERY entries for dead nodes,
 		 * otherwise hangs can occur during later recovery */
 		if (dlm_is_recovery_lock(res->lockname.name,
@@ -1169,7 +1155,7 @@
 					u8 flags, u8 master)
 {
 	/* mres here is one full page */
-	memset(mres, 0, PAGE_SIZE);
+	clear_page(mres);
 	mres->lockname_len = namelen;
 	memcpy(mres->lockname, lockname, namelen);
 	mres->num_locks = 0;
@@ -1252,7 +1238,7 @@
 			 struct dlm_migratable_lockres *mres,
 			 u8 send_to, u8 flags)
 {
-	struct list_head *queue, *iter;
+	struct list_head *queue;
 	int total_locks, i;
 	u64 mig_cookie = 0;
 	struct dlm_lock *lock;
@@ -1278,9 +1264,7 @@
 	total_locks = 0;
 	for (i=DLM_GRANTED_LIST; i<=DLM_BLOCKED_LIST; i++) {
 		queue = dlm_list_idx_to_ptr(res, i);
-		list_for_each(iter, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
-
+		list_for_each_entry(lock, queue, list) {
 			/* add another lock. */
 			total_locks++;
 			if (!dlm_add_lock_to_array(lock, mres, i))
@@ -1717,7 +1701,6 @@
 	struct dlm_lockstatus *lksb = NULL;
 	int ret = 0;
 	int i, j, bad;
-	struct list_head *iter;
 	struct dlm_lock *lock = NULL;
 	u8 from = O2NM_MAX_NODES;
 	unsigned int added = 0;
@@ -1755,8 +1738,7 @@
 			spin_lock(&res->spinlock);
 			for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) {
 				tmpq = dlm_list_idx_to_ptr(res, j);
-				list_for_each(iter, tmpq) {
-					lock = list_entry (iter, struct dlm_lock, list);
+				list_for_each_entry(lock, tmpq, list) {
 					if (lock->ml.cookie != ml->cookie)
 						lock = NULL;
 					else
@@ -1930,8 +1912,8 @@
 				       struct dlm_lock_resource *res)
 {
 	int i;
-	struct list_head *queue, *iter, *iter2;
-	struct dlm_lock *lock;
+	struct list_head *queue;
+	struct dlm_lock *lock, *next;
 
 	res->state |= DLM_LOCK_RES_RECOVERING;
 	if (!list_empty(&res->recovering)) {
@@ -1947,8 +1929,7 @@
 	/* find any pending locks and put them back on proper list */
 	for (i=DLM_BLOCKED_LIST; i>=DLM_GRANTED_LIST; i--) {
 		queue = dlm_list_idx_to_ptr(res, i);
-		list_for_each_safe(iter, iter2, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
+		list_for_each_entry_safe(lock, next, queue, list) {
 			dlm_lock_get(lock);
 			if (lock->convert_pending) {
 				/* move converting lock back to granted */
@@ -2013,18 +1994,15 @@
 					      u8 dead_node, u8 new_master)
 {
 	int i;
-	struct list_head *iter, *iter2;
 	struct hlist_node *hash_iter;
 	struct hlist_head *bucket;
-
-	struct dlm_lock_resource *res;
+	struct dlm_lock_resource *res, *next;
 
 	mlog_entry_void();
 
 	assert_spin_locked(&dlm->spinlock);
 
-	list_for_each_safe(iter, iter2, &dlm->reco.resources) {
-		res = list_entry (iter, struct dlm_lock_resource, recovering);
+	list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
 		if (res->owner == dead_node) {
 			list_del_init(&res->recovering);
 			spin_lock(&res->spinlock);
@@ -2099,7 +2077,7 @@
 static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
 			       struct dlm_lock_resource *res, u8 dead_node)
 {
-	struct list_head *iter, *queue;
+	struct list_head *queue;
 	struct dlm_lock *lock;
 	int blank_lvb = 0, local = 0;
 	int i;
@@ -2121,8 +2099,7 @@
 
 	for (i=DLM_GRANTED_LIST; i<=DLM_CONVERTING_LIST; i++) {
 		queue = dlm_list_idx_to_ptr(res, i);
-		list_for_each(iter, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
+		list_for_each_entry(lock, queue, list) {
 			if (lock->ml.node == search_node) {
 				if (dlm_lvb_needs_invalidation(lock, local)) {
 					/* zero the lksb lvb and lockres lvb */
@@ -2143,8 +2120,7 @@
 static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
 				struct dlm_lock_resource *res, u8 dead_node)
 {
-	struct list_head *iter, *tmpiter;
-	struct dlm_lock *lock;
+	struct dlm_lock *lock, *next;
 	unsigned int freed = 0;
 
 	/* this node is the lockres master:
@@ -2155,24 +2131,21 @@
 	assert_spin_locked(&res->spinlock);
 
 	/* TODO: check pending_asts, pending_basts here */
-	list_for_each_safe(iter, tmpiter, &res->granted) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry_safe(lock, next, &res->granted, list) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
 			freed++;
 		}
 	}
-	list_for_each_safe(iter, tmpiter, &res->converting) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry_safe(lock, next, &res->converting, list) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
 			freed++;
 		}
 	}
-	list_for_each_safe(iter, tmpiter, &res->blocked) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry_safe(lock, next, &res->blocked, list) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index d1bd305..f71250e 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -600,15 +600,13 @@
 static void lockres_set_flags(struct ocfs2_lock_res *lockres,
 			      unsigned long newflags)
 {
-	struct list_head *pos, *tmp;
-	struct ocfs2_mask_waiter *mw;
+	struct ocfs2_mask_waiter *mw, *tmp;
 
  	assert_spin_locked(&lockres->l_lock);
 
 	lockres->l_flags = newflags;
 
-	list_for_each_safe(pos, tmp, &lockres->l_mask_waiters) {
-		mw = list_entry(pos, struct ocfs2_mask_waiter, mw_item);
+	list_for_each_entry_safe(mw, tmp, &lockres->l_mask_waiters, mw_item) {
 		if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
 			continue;
 
diff --git a/fs/ocfs2/endian.h b/fs/ocfs2/endian.h
index f226b22..ff25762 100644
--- a/fs/ocfs2/endian.h
+++ b/fs/ocfs2/endian.h
@@ -32,6 +32,11 @@
 	*var = cpu_to_le32(le32_to_cpu(*var) + val);
 }
 
+static inline void le64_add_cpu(__le64 *var, u64 val)
+{
+	*var = cpu_to_le64(le64_to_cpu(*var) + val);
+}
+
 static inline void le32_and_cpu(__le32 *var, u32 val)
 {
 	*var = cpu_to_le32(le32_to_cpu(*var) & val);
diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h
index 5b77ee7..e08bed9 100644
--- a/fs/ocfs2/export.h
+++ b/fs/ocfs2/export.h
@@ -26,6 +26,8 @@
 #ifndef OCFS2_EXPORT_H
 #define OCFS2_EXPORT_H
 
+#include <linux/exportfs.h>
+
 extern struct export_operations ocfs2_export_ops;
 
 #endif /* OCFS2_EXPORT_H */
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index ba2b2ab..03c1d365 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -109,17 +109,14 @@
  */
 void ocfs2_extent_map_trunc(struct inode *inode, unsigned int cpos)
 {
-	struct list_head *p, *n;
-	struct ocfs2_extent_map_item *emi;
+	struct ocfs2_extent_map_item *emi, *n;
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 	struct ocfs2_extent_map *em = &oi->ip_extent_map;
 	LIST_HEAD(tmp_list);
 	unsigned int range;
 
 	spin_lock(&oi->ip_lock);
-	list_for_each_safe(p, n, &em->em_list) {
-		emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
-
+	list_for_each_entry_safe(emi, n, &em->em_list, ei_list) {
 		if (emi->ei_cpos >= cpos) {
 			/* Full truncate of this record. */
 			list_move(&emi->ei_list, &tmp_list);
@@ -136,8 +133,7 @@
 	}
 	spin_unlock(&oi->ip_lock);
 
-	list_for_each_safe(p, n, &tmp_list) {
-		emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
+	list_for_each_entry_safe(emi, n, &tmp_list, ei_list) {
 		list_del(&emi->ei_list);
 		kfree(emi);
 	}
@@ -377,37 +373,6 @@
 	return ret;
 }
 
-/*
- * Return the index of the extent record which contains cluster #v_cluster.
- * -1 is returned if it was not found.
- *
- * Should work fine on interior and exterior nodes.
- */
-static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
-				    u32 v_cluster)
-{
-	int ret = -1;
-	int i;
-	struct ocfs2_extent_rec *rec;
-	u32 rec_end, rec_start, clusters;
-
-	for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
-		rec = &el->l_recs[i];
-
-		rec_start = le32_to_cpu(rec->e_cpos);
-		clusters = ocfs2_rec_clusters(el, rec);
-
-		rec_end = rec_start + clusters;
-
-		if (v_cluster >= rec_start && v_cluster < rec_end) {
-			ret = i;
-			break;
-		}
-	}
-
-	return ret;
-}
-
 int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
 		       u32 *p_cluster, u32 *num_clusters,
 		       unsigned int *extent_flags)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 4979b66..f04c7aa 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -263,6 +263,7 @@
 	int status;
 	handle_t *handle;
 	struct ocfs2_dinode *di;
+	u64 cluster_bytes;
 
 	mlog_entry_void();
 
@@ -286,7 +287,9 @@
 	/*
 	 * Do this before setting i_size.
 	 */
-	status = ocfs2_zero_tail_for_truncate(inode, handle, new_i_size);
+	cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size);
+	status = ocfs2_zero_range_for_truncate(inode, handle, new_i_size,
+					       cluster_bytes);
 	if (status) {
 		mlog_errno(status);
 		goto out_commit;
@@ -326,9 +329,6 @@
 		   (unsigned long long)OCFS2_I(inode)->ip_blkno,
 		   (unsigned long long)new_i_size);
 
-	unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
-	truncate_inode_pages(inode->i_mapping, new_i_size);
-
 	fe = (struct ocfs2_dinode *) di_bh->b_data;
 	if (!OCFS2_IS_VALID_DINODE(fe)) {
 		OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
@@ -363,16 +363,23 @@
 	if (new_i_size == le64_to_cpu(fe->i_size))
 		goto bail;
 
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
 	/* This forces other nodes to sync and drop their pages. Do
 	 * this even if we have a truncate without allocation change -
 	 * ocfs2 cluster sizes can be much greater than page size, so
 	 * we have to truncate them anyway.  */
 	status = ocfs2_data_lock(inode, 1);
 	if (status < 0) {
+		up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
 		mlog_errno(status);
 		goto bail;
 	}
 
+	unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
+	truncate_inode_pages(inode->i_mapping, new_i_size);
+
 	/* alright, we're going to need to do a full blown alloc size
 	 * change. Orphan the inode so that recovery can complete the
 	 * truncate if necessary. This does the task of marking
@@ -399,6 +406,8 @@
 bail_unlock_data:
 	ocfs2_data_unlock(inode, 1);
 
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
 bail:
 
 	mlog_exit(status);
@@ -419,6 +428,7 @@
 			       struct inode *inode,
 			       u32 *logical_offset,
 			       u32 clusters_to_add,
+			       int mark_unwritten,
 			       struct buffer_head *fe_bh,
 			       handle_t *handle,
 			       struct ocfs2_alloc_context *data_ac,
@@ -431,9 +441,13 @@
 	enum ocfs2_alloc_restarted reason = RESTART_NONE;
 	u32 bit_off, num_bits;
 	u64 block;
+	u8 flags = 0;
 
 	BUG_ON(!clusters_to_add);
 
+	if (mark_unwritten)
+		flags = OCFS2_EXT_UNWRITTEN;
+
 	free_extents = ocfs2_num_free_extents(osb, inode, fe);
 	if (free_extents < 0) {
 		status = free_extents;
@@ -483,7 +497,7 @@
 	     num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
 	status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
 				     *logical_offset, block, num_bits,
-				     meta_ac);
+				     flags, meta_ac);
 	if (status < 0) {
 		mlog_errno(status);
 		goto leave;
@@ -516,25 +530,31 @@
  * For a given allocation, determine which allocators will need to be
  * accessed, and lock them, reserving the appropriate number of bits.
  *
- * Called from ocfs2_extend_allocation() for file systems which don't
- * support holes, and from ocfs2_write() for file systems which
- * understand sparse inodes.
+ * Sparse file systems call this from ocfs2_write_begin_nolock()
+ * and ocfs2_allocate_unwritten_extents().
+ *
+ * File systems which don't support holes call this from
+ * ocfs2_extend_allocation().
  */
 int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
-			  u32 clusters_to_add,
+			  u32 clusters_to_add, u32 extents_to_split,
 			  struct ocfs2_alloc_context **data_ac,
 			  struct ocfs2_alloc_context **meta_ac)
 {
-	int ret, num_free_extents;
+	int ret = 0, num_free_extents;
+	unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	*meta_ac = NULL;
-	*data_ac = NULL;
+	if (data_ac)
+		*data_ac = NULL;
+
+	BUG_ON(clusters_to_add != 0 && data_ac == NULL);
 
 	mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
-	     "clusters_to_add = %u\n",
+	     "clusters_to_add = %u, extents_to_split = %u\n",
 	     (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode),
-	     le32_to_cpu(di->i_clusters), clusters_to_add);
+	     le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
 
 	num_free_extents = ocfs2_num_free_extents(osb, inode, di);
 	if (num_free_extents < 0) {
@@ -552,9 +572,12 @@
 	 *
 	 * Most of the time we'll only be seeing this 1 cluster at a time
 	 * anyway.
+	 *
+	 * Always lock for any unwritten extents - we might want to
+	 * add blocks during a split.
 	 */
 	if (!num_free_extents ||
-	    (ocfs2_sparse_alloc(osb) && num_free_extents < clusters_to_add)) {
+	    (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
 		ret = ocfs2_reserve_new_metadata(osb, di, meta_ac);
 		if (ret < 0) {
 			if (ret != -ENOSPC)
@@ -563,6 +586,9 @@
 		}
 	}
 
+	if (clusters_to_add == 0)
+		goto out;
+
 	ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
 	if (ret < 0) {
 		if (ret != -ENOSPC)
@@ -585,14 +611,13 @@
 	return ret;
 }
 
-static int ocfs2_extend_allocation(struct inode *inode,
-				   u32 clusters_to_add)
+static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+				     u32 clusters_to_add, int mark_unwritten)
 {
 	int status = 0;
 	int restart_func = 0;
-	int drop_alloc_sem = 0;
 	int credits;
-	u32 prev_clusters, logical_start;
+	u32 prev_clusters;
 	struct buffer_head *bh = NULL;
 	struct ocfs2_dinode *fe = NULL;
 	handle_t *handle = NULL;
@@ -607,7 +632,7 @@
 	 * This function only exists for file systems which don't
 	 * support holes.
 	 */
-	BUG_ON(ocfs2_sparse_alloc(osb));
+	BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
 
 	status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
 				  OCFS2_BH_CACHED, inode);
@@ -623,19 +648,10 @@
 		goto leave;
 	}
 
-	logical_start = OCFS2_I(inode)->ip_clusters;
-
 restart_all:
 	BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
 
-	/* blocks peope in read/write from reading our allocation
-	 * until we're done changing it. We depend on i_mutex to block
-	 * other extend/truncate calls while we're here. Ordering wrt
-	 * start_trans is important here -- always do it before! */
-	down_write(&OCFS2_I(inode)->ip_alloc_sem);
-	drop_alloc_sem = 1;
-
-	status = ocfs2_lock_allocators(inode, fe, clusters_to_add, &data_ac,
+	status = ocfs2_lock_allocators(inode, fe, clusters_to_add, 0, &data_ac,
 				       &meta_ac);
 	if (status) {
 		mlog_errno(status);
@@ -668,6 +684,7 @@
 					    inode,
 					    &logical_start,
 					    clusters_to_add,
+					    mark_unwritten,
 					    bh,
 					    handle,
 					    data_ac,
@@ -720,10 +737,6 @@
 	     OCFS2_I(inode)->ip_clusters, i_size_read(inode));
 
 leave:
-	if (drop_alloc_sem) {
-		up_write(&OCFS2_I(inode)->ip_alloc_sem);
-		drop_alloc_sem = 0;
-	}
 	if (handle) {
 		ocfs2_commit_trans(osb, handle);
 		handle = NULL;
@@ -749,6 +762,25 @@
 	return status;
 }
 
+static int ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+				   u32 clusters_to_add, int mark_unwritten)
+{
+	int ret;
+
+	/*
+	 * The alloc sem blocks peope in read/write from reading our
+	 * allocation until we're done changing it. We depend on
+	 * i_mutex to block other extend/truncate calls while we're
+	 * here.
+	 */
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+	ret = __ocfs2_extend_allocation(inode, logical_start, clusters_to_add,
+					mark_unwritten);
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	return ret;
+}
+
 /* Some parts of this taken from generic_cont_expand, which turned out
  * to be too fragile to do exactly what we need without us having to
  * worry about recursive locking in ->prepare_write() and
@@ -890,7 +922,9 @@
 	}
 
 	if (clusters_to_add) {
-		ret = ocfs2_extend_allocation(inode, clusters_to_add);
+		ret = ocfs2_extend_allocation(inode,
+					      OCFS2_I(inode)->ip_clusters,
+					      clusters_to_add, 0);
 		if (ret < 0) {
 			mlog_errno(ret);
 			goto out_unlock;
@@ -995,6 +1029,13 @@
 		goto bail_unlock;
 	}
 
+	/*
+	 * This will intentionally not wind up calling vmtruncate(),
+	 * since all the work for a size change has been done above.
+	 * Otherwise, we could get into problems with truncate as
+	 * ip_alloc_sem is used there to protect against i_size
+	 * changes.
+	 */
 	status = inode_setattr(inode, attr);
 	if (status < 0) {
 		mlog_errno(status);
@@ -1070,17 +1111,16 @@
 	return ret;
 }
 
-static int ocfs2_write_remove_suid(struct inode *inode)
+static int __ocfs2_write_remove_suid(struct inode *inode,
+				     struct buffer_head *bh)
 {
 	int ret;
-	struct buffer_head *bh = NULL;
-	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 	handle_t *handle;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct ocfs2_dinode *di;
 
 	mlog_entry("(Inode %llu, mode 0%o)\n",
-		   (unsigned long long)oi->ip_blkno, inode->i_mode);
+		   (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode);
 
 	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
 	if (handle == NULL) {
@@ -1089,17 +1129,11 @@
 		goto out;
 	}
 
-	ret = ocfs2_read_block(osb, oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
-	if (ret < 0) {
-		mlog_errno(ret);
-		goto out_trans;
-	}
-
 	ret = ocfs2_journal_access(handle, inode, bh,
 				   OCFS2_JOURNAL_ACCESS_WRITE);
 	if (ret < 0) {
 		mlog_errno(ret);
-		goto out_bh;
+		goto out_trans;
 	}
 
 	inode->i_mode &= ~S_ISUID;
@@ -1112,8 +1146,7 @@
 	ret = ocfs2_journal_dirty(handle, bh);
 	if (ret < 0)
 		mlog_errno(ret);
-out_bh:
-	brelse(bh);
+
 out_trans:
 	ocfs2_commit_trans(osb, handle);
 out:
@@ -1159,6 +1192,460 @@
 	return ret;
 }
 
+static int ocfs2_write_remove_suid(struct inode *inode)
+{
+	int ret;
+	struct buffer_head *bh = NULL;
+	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+	ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+			       oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret =  __ocfs2_write_remove_suid(inode, bh);
+out:
+	brelse(bh);
+	return ret;
+}
+
+/*
+ * Allocate enough extents to cover the region starting at byte offset
+ * start for len bytes. Existing extents are skipped, any extents
+ * added are marked as "unwritten".
+ */
+static int ocfs2_allocate_unwritten_extents(struct inode *inode,
+					    u64 start, u64 len)
+{
+	int ret;
+	u32 cpos, phys_cpos, clusters, alloc_size;
+
+	/*
+	 * We consider both start and len to be inclusive.
+	 */
+	cpos = start >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+	clusters = ocfs2_clusters_for_bytes(inode->i_sb, start + len);
+	clusters -= cpos;
+
+	while (clusters) {
+		ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
+					 &alloc_size, NULL);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * Hole or existing extent len can be arbitrary, so
+		 * cap it to our own allocation request.
+		 */
+		if (alloc_size > clusters)
+			alloc_size = clusters;
+
+		if (phys_cpos) {
+			/*
+			 * We already have an allocation at this
+			 * region so we can safely skip it.
+			 */
+			goto next;
+		}
+
+		ret = __ocfs2_extend_allocation(inode, cpos, alloc_size, 1);
+		if (ret) {
+			if (ret != -ENOSPC)
+				mlog_errno(ret);
+			goto out;
+		}
+
+next:
+		cpos += alloc_size;
+		clusters -= alloc_size;
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int __ocfs2_remove_inode_range(struct inode *inode,
+				      struct buffer_head *di_bh,
+				      u32 cpos, u32 phys_cpos, u32 len,
+				      struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret;
+	u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct inode *tl_inode = osb->osb_tl_inode;
+	handle_t *handle;
+	struct ocfs2_alloc_context *meta_ac = NULL;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+
+	ret = ocfs2_lock_allocators(inode, di, 0, 1, NULL, &meta_ac);
+	if (ret) {
+		mlog_errno(ret);
+		return ret;
+	}
+
+	mutex_lock(&tl_inode->i_mutex);
+
+	if (ocfs2_truncate_log_needs_flush(osb)) {
+		ret = __ocfs2_flush_truncate_log(osb);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+	handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
+	if (handle == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access(handle, inode, di_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
+				  dealloc);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	OCFS2_I(inode)->ip_clusters -= len;
+	di->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
+
+	ret = ocfs2_journal_dirty(handle, di_bh);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
+	if (ret)
+		mlog_errno(ret);
+
+out_commit:
+	ocfs2_commit_trans(osb, handle);
+out:
+	mutex_unlock(&tl_inode->i_mutex);
+
+	if (meta_ac)
+		ocfs2_free_alloc_context(meta_ac);
+
+	return ret;
+}
+
+/*
+ * Truncate a byte range, avoiding pages within partial clusters. This
+ * preserves those pages for the zeroing code to write to.
+ */
+static void ocfs2_truncate_cluster_pages(struct inode *inode, u64 byte_start,
+					 u64 byte_len)
+{
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	loff_t start, end;
+	struct address_space *mapping = inode->i_mapping;
+
+	start = (loff_t)ocfs2_align_bytes_to_clusters(inode->i_sb, byte_start);
+	end = byte_start + byte_len;
+	end = end & ~(osb->s_clustersize - 1);
+
+	if (start < end) {
+		unmap_mapping_range(mapping, start, end - start, 0);
+		truncate_inode_pages_range(mapping, start, end - 1);
+	}
+}
+
+static int ocfs2_zero_partial_clusters(struct inode *inode,
+				       u64 start, u64 len)
+{
+	int ret = 0;
+	u64 tmpend, end = start + len;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	unsigned int csize = osb->s_clustersize;
+	handle_t *handle;
+
+	/*
+	 * The "start" and "end" values are NOT necessarily part of
+	 * the range whose allocation is being deleted. Rather, this
+	 * is what the user passed in with the request. We must zero
+	 * partial clusters here. There's no need to worry about
+	 * physical allocation - the zeroing code knows to skip holes.
+	 */
+	mlog(0, "byte start: %llu, end: %llu\n",
+	     (unsigned long long)start, (unsigned long long)end);
+
+	/*
+	 * If both edges are on a cluster boundary then there's no
+	 * zeroing required as the region is part of the allocation to
+	 * be truncated.
+	 */
+	if ((start & (csize - 1)) == 0 && (end & (csize - 1)) == 0)
+		goto out;
+
+	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+	if (handle == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * We want to get the byte offset of the end of the 1st cluster.
+	 */
+	tmpend = (u64)osb->s_clustersize + (start & ~(osb->s_clustersize - 1));
+	if (tmpend > end)
+		tmpend = end;
+
+	mlog(0, "1st range: start: %llu, tmpend: %llu\n",
+	     (unsigned long long)start, (unsigned long long)tmpend);
+
+	ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend);
+	if (ret)
+		mlog_errno(ret);
+
+	if (tmpend < end) {
+		/*
+		 * This may make start and end equal, but the zeroing
+		 * code will skip any work in that case so there's no
+		 * need to catch it up here.
+		 */
+		start = end & ~(osb->s_clustersize - 1);
+
+		mlog(0, "2nd range: start: %llu, end: %llu\n",
+		     (unsigned long long)start, (unsigned long long)end);
+
+		ret = ocfs2_zero_range_for_truncate(inode, handle, start, end);
+		if (ret)
+			mlog_errno(ret);
+	}
+
+	ocfs2_commit_trans(osb, handle);
+out:
+	return ret;
+}
+
+static int ocfs2_remove_inode_range(struct inode *inode,
+				    struct buffer_head *di_bh, u64 byte_start,
+				    u64 byte_len)
+{
+	int ret = 0;
+	u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_cached_dealloc_ctxt dealloc;
+
+	ocfs2_init_dealloc_ctxt(&dealloc);
+
+	if (byte_len == 0)
+		return 0;
+
+	trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start);
+	trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits;
+	if (trunc_len >= trunc_start)
+		trunc_len -= trunc_start;
+	else
+		trunc_len = 0;
+
+	mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, clen: %u\n",
+	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
+	     (unsigned long long)byte_start,
+	     (unsigned long long)byte_len, trunc_start, trunc_len);
+
+	ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	cpos = trunc_start;
+	while (trunc_len) {
+		ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
+					 &alloc_size, NULL);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (alloc_size > trunc_len)
+			alloc_size = trunc_len;
+
+		/* Only do work for non-holes */
+		if (phys_cpos != 0) {
+			ret = __ocfs2_remove_inode_range(inode, di_bh, cpos,
+							 phys_cpos, alloc_size,
+							 &dealloc);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		}
+
+		cpos += alloc_size;
+		trunc_len -= alloc_size;
+	}
+
+	ocfs2_truncate_cluster_pages(inode, byte_start, byte_len);
+
+out:
+	ocfs2_schedule_truncate_log_flush(osb, 1);
+	ocfs2_run_deallocs(osb, &dealloc);
+
+	return ret;
+}
+
+/*
+ * Parts of this function taken from xfs_change_file_space()
+ */
+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+			    struct ocfs2_space_resv *sr)
+{
+	int ret;
+	s64 llen;
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct buffer_head *di_bh = NULL;
+	handle_t *handle;
+	unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits);
+
+	if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) &&
+	    !ocfs2_writes_unwritten_extents(osb))
+		return -ENOTTY;
+	else if ((cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) &&
+		 !ocfs2_sparse_alloc(osb))
+		return -ENOTTY;
+
+	if (!S_ISREG(inode->i_mode))
+		return -EINVAL;
+
+	if (!(file->f_mode & FMODE_WRITE))
+		return -EBADF;
+
+	if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
+		return -EROFS;
+
+	mutex_lock(&inode->i_mutex);
+
+	/*
+	 * This prevents concurrent writes on other nodes
+	 */
+	ret = ocfs2_rw_lock(inode, 1);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_rw_unlock;
+	}
+
+	if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
+		ret = -EPERM;
+		goto out_meta_unlock;
+	}
+
+	switch (sr->l_whence) {
+	case 0: /*SEEK_SET*/
+		break;
+	case 1: /*SEEK_CUR*/
+		sr->l_start += file->f_pos;
+		break;
+	case 2: /*SEEK_END*/
+		sr->l_start += i_size_read(inode);
+		break;
+	default:
+		ret = -EINVAL;
+		goto out_meta_unlock;
+	}
+	sr->l_whence = 0;
+
+	llen = sr->l_len > 0 ? sr->l_len - 1 : sr->l_len;
+
+	if (sr->l_start < 0
+	    || sr->l_start > max_off
+	    || (sr->l_start + llen) < 0
+	    || (sr->l_start + llen) > max_off) {
+		ret = -EINVAL;
+		goto out_meta_unlock;
+	}
+
+	if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) {
+		if (sr->l_len <= 0) {
+			ret = -EINVAL;
+			goto out_meta_unlock;
+		}
+	}
+
+	if (should_remove_suid(file->f_path.dentry)) {
+		ret = __ocfs2_write_remove_suid(inode, di_bh);
+		if (ret) {
+			mlog_errno(ret);
+			goto out_meta_unlock;
+		}
+	}
+
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+	switch (cmd) {
+	case OCFS2_IOC_RESVSP:
+	case OCFS2_IOC_RESVSP64:
+		/*
+		 * This takes unsigned offsets, but the signed ones we
+		 * pass have been checked against overflow above.
+		 */
+		ret = ocfs2_allocate_unwritten_extents(inode, sr->l_start,
+						       sr->l_len);
+		break;
+	case OCFS2_IOC_UNRESVSP:
+	case OCFS2_IOC_UNRESVSP64:
+		ret = ocfs2_remove_inode_range(inode, di_bh, sr->l_start,
+					       sr->l_len);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_meta_unlock;
+	}
+
+	/*
+	 * We update c/mtime for these changes
+	 */
+	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		mlog_errno(ret);
+		goto out_meta_unlock;
+	}
+
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+	ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
+	if (ret < 0)
+		mlog_errno(ret);
+
+	ocfs2_commit_trans(osb, handle);
+
+out_meta_unlock:
+	brelse(di_bh);
+	ocfs2_meta_unlock(inode, 1);
+out_rw_unlock:
+	ocfs2_rw_unlock(inode, 1);
+
+	mutex_unlock(&inode->i_mutex);
+out:
+	return ret;
+}
+
 static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
 					 loff_t *ppos,
 					 size_t count,
@@ -1329,15 +1816,16 @@
 	*basep = base;
 }
 
-static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp,
+static struct page * ocfs2_get_write_source(char **ret_src_buf,
 					    const struct iovec *cur_iov,
 					    size_t iov_offset)
 {
 	int ret;
-	char *buf;
+	char *buf = cur_iov->iov_base + iov_offset;
 	struct page *src_page = NULL;
+	unsigned long off;
 
-	buf = cur_iov->iov_base + iov_offset;
+	off = (unsigned long)(buf) & ~PAGE_CACHE_MASK;
 
 	if (!segment_eq(get_fs(), KERNEL_DS)) {
 		/*
@@ -1349,18 +1837,17 @@
 				     (unsigned long)buf & PAGE_CACHE_MASK, 1,
 				     0, 0, &src_page, NULL);
 		if (ret == 1)
-			bp->b_src_buf = kmap(src_page);
+			*ret_src_buf = kmap(src_page) + off;
 		else
 			src_page = ERR_PTR(-EFAULT);
 	} else {
-		bp->b_src_buf = buf;
+		*ret_src_buf = buf;
 	}
 
 	return src_page;
 }
 
-static void ocfs2_put_write_source(struct ocfs2_buffered_write_priv *bp,
-				   struct page *page)
+static void ocfs2_put_write_source(struct page *page)
 {
 	if (page) {
 		kunmap(page);
@@ -1376,10 +1863,12 @@
 {
 	int ret = 0;
 	ssize_t copied, total = 0;
-	size_t iov_offset = 0;
+	size_t iov_offset = 0, bytes;
+	loff_t pos;
 	const struct iovec *cur_iov = iov;
-	struct ocfs2_buffered_write_priv bp;
-	struct page *page;
+	struct page *user_page, *page;
+	char *buf, *dst;
+	void *fsdata;
 
 	/*
 	 * handle partial DIO write.  Adjust cur_iov if needed.
@@ -1387,21 +1876,38 @@
 	ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written);
 
 	do {
-		bp.b_cur_off = iov_offset;
-		bp.b_cur_iov = cur_iov;
+		pos = *ppos;
 
-		page = ocfs2_get_write_source(&bp, cur_iov, iov_offset);
-		if (IS_ERR(page)) {
-			ret = PTR_ERR(page);
+		user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset);
+		if (IS_ERR(user_page)) {
+			ret = PTR_ERR(user_page);
 			goto out;
 		}
 
-		copied = ocfs2_buffered_write_cluster(file, *ppos, count,
-						      ocfs2_map_and_write_user_data,
-						      &bp);
+		/* Stay within our page boundaries */
+		bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)),
+			    (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK)));
+		/* Stay within the vector boundary */
+		bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset);
+		/* Stay within count */
+		bytes = min(bytes, count);
 
-		ocfs2_put_write_source(&bp, page);
+		page = NULL;
+		ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0,
+					&page, &fsdata);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
 
+		dst = kmap_atomic(page, KM_USER0);
+		memcpy(dst + (pos & (PAGE_CACHE_SIZE - 1)), buf, bytes);
+		kunmap_atomic(dst, KM_USER0);
+		flush_dcache_page(page);
+		ocfs2_put_write_source(user_page);
+
+		copied = ocfs2_write_end(file, file->f_mapping, pos, bytes,
+					 bytes, page, fsdata);
 		if (copied < 0) {
 			mlog_errno(copied);
 			ret = copied;
@@ -1409,7 +1915,7 @@
 		}
 
 		total += copied;
-		*ppos = *ppos + copied;
+		*ppos = pos + copied;
 		count -= copied;
 
 		ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied);
@@ -1579,52 +2085,46 @@
 				    struct pipe_buffer *buf,
 				    struct splice_desc *sd)
 {
-	int ret, count, total = 0;
+	int ret, count;
 	ssize_t copied = 0;
-	struct ocfs2_splice_write_priv sp;
+	struct file *file = sd->u.file;
+	unsigned int offset;
+	struct page *page = NULL;
+	void *fsdata;
+	char *src, *dst;
 
 	ret = buf->ops->confirm(pipe, buf);
 	if (ret)
 		goto out;
 
-	sp.s_sd = sd;
-	sp.s_buf = buf;
-	sp.s_pipe = pipe;
-	sp.s_offset = sd->pos & ~PAGE_CACHE_MASK;
-	sp.s_buf_offset = buf->offset;
-
+	offset = sd->pos & ~PAGE_CACHE_MASK;
 	count = sd->len;
-	if (count + sp.s_offset > PAGE_CACHE_SIZE)
-		count = PAGE_CACHE_SIZE - sp.s_offset;
+	if (count + offset > PAGE_CACHE_SIZE)
+		count = PAGE_CACHE_SIZE - offset;
 
-	do {
-		/*
-		 * splice wants us to copy up to one page at a
-		 * time. For pagesize > cluster size, this means we
-		 * might enter ocfs2_buffered_write_cluster() more
-		 * than once, so keep track of our progress here.
-		 */
-		copied = ocfs2_buffered_write_cluster(sd->u.file,
-						      (loff_t)sd->pos + total,
-						      count,
-						      ocfs2_map_and_write_splice_data,
-						      &sp);
-		if (copied < 0) {
-			mlog_errno(copied);
-			ret = copied;
-			goto out;
-		}
+	ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0,
+				&page, &fsdata);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
 
-		count -= copied;
-		sp.s_offset += copied;
-		sp.s_buf_offset += copied;
-		total += copied;
-	} while (count);
+	src = buf->ops->map(pipe, buf, 1);
+	dst = kmap_atomic(page, KM_USER1);
+	memcpy(dst + offset, src + buf->offset, count);
+	kunmap_atomic(page, KM_USER1);
+	buf->ops->unmap(pipe, buf, src);
 
-	ret = 0;
+	copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count,
+				 page, fsdata);
+	if (copied < 0) {
+		mlog_errno(copied);
+		ret = copied;
+		goto out;
+	}
 out:
 
-	return total ? total : ret;
+	return copied ? copied : ret;
 }
 
 static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index a4dd1fa..36fe27f 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -39,15 +39,16 @@
 };
 int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
 			       struct inode *inode,
-			       u32 *cluster_start,
+			       u32 *logical_offset,
 			       u32 clusters_to_add,
+			       int mark_unwritten,
 			       struct buffer_head *fe_bh,
 			       handle_t *handle,
 			       struct ocfs2_alloc_context *data_ac,
 			       struct ocfs2_alloc_context *meta_ac,
-			       enum ocfs2_alloc_restarted *reason);
+			       enum ocfs2_alloc_restarted *reason_ret);
 int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
-			  u32 clusters_to_add,
+			  u32 clusters_to_add, u32 extents_to_split,
 			  struct ocfs2_alloc_context **data_ac,
 			  struct ocfs2_alloc_context **meta_ac);
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
@@ -61,4 +62,7 @@
 int ocfs2_update_inode_atime(struct inode *inode,
 			     struct buffer_head *bh);
 
+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+			    struct ocfs2_space_resv *sr);
+
 #endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
index b25ef63..352eb4a 100644
--- a/fs/ocfs2/heartbeat.c
+++ b/fs/ocfs2/heartbeat.c
@@ -157,16 +157,16 @@
 	if (ocfs2_mount_local(osb))
 		return 0;
 
-	status = o2hb_register_callback(&osb->osb_hb_down);
+	status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_down);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
 	}
 
-	status = o2hb_register_callback(&osb->osb_hb_up);
+	status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_up);
 	if (status < 0) {
 		mlog_errno(status);
-		o2hb_unregister_callback(&osb->osb_hb_down);
+		o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
 	}
 
 bail:
@@ -178,8 +178,8 @@
 	if (ocfs2_mount_local(osb))
 		return;
 
-	o2hb_unregister_callback(&osb->osb_hb_down);
-	o2hb_unregister_callback(&osb->osb_hb_up);
+	o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
+	o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_up);
 }
 
 void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index f3ad21a..bd68c3f 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -14,6 +14,7 @@
 #include "ocfs2.h"
 #include "alloc.h"
 #include "dlmglue.h"
+#include "file.h"
 #include "inode.h"
 #include "journal.h"
 
@@ -115,6 +116,7 @@
 {
 	unsigned int flags;
 	int status;
+	struct ocfs2_space_resv sr;
 
 	switch (cmd) {
 	case OCFS2_IOC_GETFLAGS:
@@ -130,6 +132,14 @@
 
 		return ocfs2_set_inode_attr(inode, flags,
 			OCFS2_FL_MODIFIABLE);
+	case OCFS2_IOC_RESVSP:
+	case OCFS2_IOC_RESVSP64:
+	case OCFS2_IOC_UNRESVSP:
+	case OCFS2_IOC_UNRESVSP64:
+		if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
+			return -EFAULT;
+
+		return ocfs2_change_file_space(filp, cmd, &sr);
 	default:
 		return -ENOTTY;
 	}
@@ -148,6 +158,11 @@
 	case OCFS2_IOC32_SETFLAGS:
 		cmd = OCFS2_IOC_SETFLAGS;
 		break;
+	case OCFS2_IOC_RESVSP:
+	case OCFS2_IOC_RESVSP64:
+	case OCFS2_IOC_UNRESVSP:
+	case OCFS2_IOC_UNRESVSP64:
+		break;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index dc11880..dbfb20b 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -722,8 +722,7 @@
 		container_of(work, struct ocfs2_journal, j_recovery_work);
 	struct ocfs2_super *osb = journal->j_osb;
 	struct ocfs2_dinode *la_dinode, *tl_dinode;
-	struct ocfs2_la_recovery_item *item;
-	struct list_head *p, *n;
+	struct ocfs2_la_recovery_item *item, *n;
 	LIST_HEAD(tmp_la_list);
 
 	mlog_entry_void();
@@ -734,8 +733,7 @@
 	list_splice_init(&journal->j_la_cleanups, &tmp_la_list);
 	spin_unlock(&journal->j_lock);
 
-	list_for_each_safe(p, n, &tmp_la_list) {
-		item = list_entry(p, struct ocfs2_la_recovery_item, lri_list);
+	list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) {
 		list_del_init(&item->lri_list);
 
 		mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 3db5de4..ce60aab 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -289,6 +289,8 @@
 #define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE 		      \
 					 + OCFS2_TRUNCATE_LOG_UPDATE)
 
+#define OCFS2_REMOVE_EXTENT_CREDITS (OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS)
+
 /* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
  * bitmap block for the new bit) */
 #define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index af01158..d79aa12 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -37,11 +37,29 @@
 
 #include "ocfs2.h"
 
+#include "aops.h"
 #include "dlmglue.h"
 #include "file.h"
 #include "inode.h"
 #include "mmap.h"
 
+static inline int ocfs2_vm_op_block_sigs(sigset_t *blocked, sigset_t *oldset)
+{
+	/* The best way to deal with signals in the vm path is
+	 * to block them upfront, rather than allowing the
+	 * locking paths to return -ERESTARTSYS. */
+	sigfillset(blocked);
+
+	/* We should technically never get a bad return value
+	 * from sigprocmask */
+	return sigprocmask(SIG_BLOCK, blocked, oldset);
+}
+
+static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
+{
+	return sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
 static struct page *ocfs2_nopage(struct vm_area_struct * area,
 				 unsigned long address,
 				 int *type)
@@ -53,14 +71,7 @@
 	mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address,
 		   type);
 
-	/* The best way to deal with signals in this path is
-	 * to block them upfront, rather than allowing the
-	 * locking paths to return -ERESTARTSYS. */
-	sigfillset(&blocked);
-
-	/* We should technically never get a bad ret return
-	 * from sigprocmask */
-	ret = sigprocmask(SIG_BLOCK, &blocked, &oldset);
+	ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
 	if (ret < 0) {
 		mlog_errno(ret);
 		goto out;
@@ -68,7 +79,7 @@
 
 	page = filemap_nopage(area, address, type);
 
-	ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
+	ret = ocfs2_vm_op_unblock_sigs(&oldset);
 	if (ret < 0)
 		mlog_errno(ret);
 out:
@@ -76,27 +87,135 @@
 	return page;
 }
 
+static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
+				struct page *page)
+{
+	int ret;
+	struct address_space *mapping = inode->i_mapping;
+	loff_t pos = page->index << PAGE_CACHE_SHIFT;
+	unsigned int len = PAGE_CACHE_SIZE;
+	pgoff_t last_index;
+	struct page *locked_page = NULL;
+	void *fsdata;
+	loff_t size = i_size_read(inode);
+
+	/*
+	 * Another node might have truncated while we were waiting on
+	 * cluster locks.
+	 */
+	last_index = size >> PAGE_CACHE_SHIFT;
+	if (page->index > last_index) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * The i_size check above doesn't catch the case where nodes
+	 * truncated and then re-extended the file. We'll re-check the
+	 * page mapping after taking the page lock inside of
+	 * ocfs2_write_begin_nolock().
+	 */
+	if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Call ocfs2_write_begin() and ocfs2_write_end() to take
+	 * advantage of the allocation code there. We pass a write
+	 * length of the whole page (chopped to i_size) to make sure
+	 * the whole thing is allocated.
+	 *
+	 * Since we know the page is up to date, we don't have to
+	 * worry about ocfs2_write_begin() skipping some buffer reads
+	 * because the "write" would invalidate their data.
+	 */
+	if (page->index == last_index)
+		len = size & ~PAGE_CACHE_MASK;
+
+	ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page,
+				       &fsdata, di_bh, page);
+	if (ret) {
+		if (ret != -ENOSPC)
+			mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
+				     fsdata);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+	BUG_ON(ret != len);
+	ret = 0;
+out:
+	return ret;
+}
+
+static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+	struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+	struct buffer_head *di_bh = NULL;
+	sigset_t blocked, oldset;
+	int ret, ret2;
+
+	ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
+	if (ret < 0) {
+		mlog_errno(ret);
+		return ret;
+	}
+
+	/*
+	 * The cluster locks taken will block a truncate from another
+	 * node. Taking the data lock will also ensure that we don't
+	 * attempt page truncation as part of a downconvert.
+	 */
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * The alloc sem should be enough to serialize with
+	 * ocfs2_truncate_file() changing i_size as well as any thread
+	 * modifying the inode btree.
+	 */
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	ret = ocfs2_data_lock(inode, 1);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out_meta_unlock;
+	}
+
+	ret = __ocfs2_page_mkwrite(inode, di_bh, page);
+
+	ocfs2_data_unlock(inode, 1);
+
+out_meta_unlock:
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	brelse(di_bh);
+	ocfs2_meta_unlock(inode, 1);
+
+out:
+	ret2 = ocfs2_vm_op_unblock_sigs(&oldset);
+	if (ret2 < 0)
+		mlog_errno(ret2);
+
+	return ret;
+}
+
 static struct vm_operations_struct ocfs2_file_vm_ops = {
-	.nopage = ocfs2_nopage,
+	.nopage		= ocfs2_nopage,
+	.page_mkwrite	= ocfs2_page_mkwrite,
 };
 
 int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	int ret = 0, lock_level = 0;
-	struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
-
-	/*
-	 * Only support shared writeable mmap for local mounts which
-	 * don't know about holes.
-	 */
-	if ((!ocfs2_mount_local(osb) || ocfs2_sparse_alloc(osb)) &&
-	    ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
-	    ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
-		mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
-		/* This is -EINVAL because generic_file_readonly_mmap
-		 * returns it in a similar situation. */
-		return -EINVAL;
-	}
 
 	ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode,
 				    file->f_vfsmnt, &lock_level);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 36289e6..d430fda 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1674,7 +1674,7 @@
 		u32 offset = 0;
 
 		inode->i_op = &ocfs2_symlink_inode_operations;
-		status = ocfs2_do_extend_allocation(osb, inode, &offset, 1,
+		status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0,
 						    new_fe_bh,
 						    handle, data_ac, NULL,
 						    NULL);
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index a860633..5cc90a4 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -219,6 +219,7 @@
 	u16 max_slots;
 	s16 node_num;
 	s16 slot_num;
+	s16 preferred_slot;
 	int s_sectsize_bits;
 	int s_clustersize;
 	int s_clustersize_bits;
@@ -305,6 +306,19 @@
 	return 0;
 }
 
+static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super *osb)
+{
+	/*
+	 * Support for sparse files is a pre-requisite
+	 */
+	if (!ocfs2_sparse_alloc(osb))
+		return 0;
+
+	if (osb->s_feature_ro_compat & OCFS2_FEATURE_RO_COMPAT_UNWRITTEN)
+		return 1;
+	return 0;
+}
+
 /* set / clear functions because cluster events can make these happen
  * in parallel so we want the transitions to be atomic. this also
  * means that any future flags osb_flags must be protected by spinlock
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index f0d9eb0..82f8a75 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -88,7 +88,7 @@
 #define OCFS2_FEATURE_COMPAT_SUPP	OCFS2_FEATURE_COMPAT_BACKUP_SB
 #define OCFS2_FEATURE_INCOMPAT_SUPP	(OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
 					 | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
-#define OCFS2_FEATURE_RO_COMPAT_SUPP	0
+#define OCFS2_FEATURE_RO_COMPAT_SUPP	OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
 
 /*
  * Heartbeat-only devices are missing journals and other files.  The
@@ -116,6 +116,11 @@
  */
 #define OCFS2_FEATURE_COMPAT_BACKUP_SB		0x0001
 
+/*
+ * Unwritten extents support.
+ */
+#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN	0x0001
+
 /* The byte offset of the first backup block will be 1G.
  * The following will be 4G, 16G, 64G, 256G and 1T.
  */
@@ -170,6 +175,32 @@
 #define OCFS2_IOC32_SETFLAGS	_IOW('f', 2, int)
 
 /*
+ * Space reservation / allocation / free ioctls and argument structure
+ * are designed to be compatible with XFS.
+ *
+ * ALLOCSP* and FREESP* are not and will never be supported, but are
+ * included here for completeness.
+ */
+struct ocfs2_space_resv {
+	__s16		l_type;
+	__s16		l_whence;
+	__s64		l_start;
+	__s64		l_len;		/* len == 0 means until end of file */
+	__s32		l_sysid;
+	__u32		l_pid;
+	__s32		l_pad[4];	/* reserve area			    */
+};
+
+#define OCFS2_IOC_ALLOCSP		_IOW ('X', 10, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP		_IOW ('X', 11, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP		_IOW ('X', 40, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP	_IOW ('X', 41, struct ocfs2_space_resv)
+#define OCFS2_IOC_ALLOCSP64	_IOW ('X', 36, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP64	_IOW ('X', 37, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP64	_IOW ('X', 42, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP64	_IOW ('X', 43, struct ocfs2_space_resv)
+
+/*
  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
  */
 #define OCFS2_JOURNAL_DIRTY_FL	(0x00000001)	/* Journal needs recovery */
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index d8b7906..af4882b 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -121,17 +121,25 @@
 	return ret;
 }
 
-static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si)
+static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred)
 {
 	int i;
 	s16 ret = OCFS2_INVALID_SLOT;
 
+	if (preferred >= 0 && preferred < si->si_num_slots) {
+		if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
+			ret = preferred;
+			goto out;
+		}
+	}
+
 	for(i = 0; i < si->si_num_slots; i++) {
 		if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
 			ret = (s16) i;
 			break;
 		}
 	}
+out:
 	return ret;
 }
 
@@ -248,7 +256,7 @@
 	if (slot == OCFS2_INVALID_SLOT) {
 		/* if no slot yet, then just take 1st available
 		 * one. */
-		slot = __ocfs2_find_empty_slot(si);
+		slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
 		if (slot == OCFS2_INVALID_SLOT) {
 			spin_unlock(&si->si_lock);
 			mlog(ML_ERROR, "no free slots available!\n");
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index e343762..d9c5c9f 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -98,14 +98,6 @@
 				    u16 chain);
 static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
 						     u32 wanted);
-static int ocfs2_free_suballoc_bits(handle_t *handle,
-				    struct inode *alloc_inode,
-				    struct buffer_head *alloc_bh,
-				    unsigned int start_bit,
-				    u64 bg_blkno,
-				    unsigned int count);
-static inline u64 ocfs2_which_suballoc_group(u64 block,
-					     unsigned int bit);
 static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
 						   u64 bg_blkno,
 						   u16 bg_bit_off);
@@ -496,13 +488,7 @@
 
 	(*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
 	(*ac)->ac_which = OCFS2_AC_USE_META;
-
-#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
-	slot = 0;
-#else
 	slot = osb->slot_num;
-#endif
-
 	(*ac)->ac_group_search = ocfs2_block_group_search;
 
 	status = ocfs2_reserve_suballoc_bits(osb, (*ac),
@@ -1626,12 +1612,12 @@
 /*
  * expects the suballoc inode to already be locked.
  */
-static int ocfs2_free_suballoc_bits(handle_t *handle,
-				    struct inode *alloc_inode,
-				    struct buffer_head *alloc_bh,
-				    unsigned int start_bit,
-				    u64 bg_blkno,
-				    unsigned int count)
+int ocfs2_free_suballoc_bits(handle_t *handle,
+			     struct inode *alloc_inode,
+			     struct buffer_head *alloc_bh,
+			     unsigned int start_bit,
+			     u64 bg_blkno,
+			     unsigned int count)
 {
 	int status = 0;
 	u32 tmp_used;
@@ -1703,13 +1689,6 @@
 	return status;
 }
 
-static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
-{
-	u64 group = block - (u64) bit;
-
-	return group;
-}
-
 int ocfs2_free_dinode(handle_t *handle,
 		      struct inode *inode_alloc_inode,
 		      struct buffer_head *inode_alloc_bh,
@@ -1723,19 +1702,6 @@
 					inode_alloc_bh, bit, bg_blkno, 1);
 }
 
-int ocfs2_free_extent_block(handle_t *handle,
-			    struct inode *eb_alloc_inode,
-			    struct buffer_head *eb_alloc_bh,
-			    struct ocfs2_extent_block *eb)
-{
-	u64 blk = le64_to_cpu(eb->h_blkno);
-	u16 bit = le16_to_cpu(eb->h_suballoc_bit);
-	u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
-
-	return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
-					bit, bg_blkno, 1);
-}
-
 int ocfs2_free_clusters(handle_t *handle,
 		       struct inode *bitmap_inode,
 		       struct buffer_head *bitmap_bh,
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index 1a3c94c..f212dc0 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -86,20 +86,29 @@
 			 u32 *cluster_start,
 			 u32 *num_clusters);
 
+int ocfs2_free_suballoc_bits(handle_t *handle,
+			     struct inode *alloc_inode,
+			     struct buffer_head *alloc_bh,
+			     unsigned int start_bit,
+			     u64 bg_blkno,
+			     unsigned int count);
 int ocfs2_free_dinode(handle_t *handle,
 		      struct inode *inode_alloc_inode,
 		      struct buffer_head *inode_alloc_bh,
 		      struct ocfs2_dinode *di);
-int ocfs2_free_extent_block(handle_t *handle,
-			    struct inode *eb_alloc_inode,
-			    struct buffer_head *eb_alloc_bh,
-			    struct ocfs2_extent_block *eb);
 int ocfs2_free_clusters(handle_t *handle,
 			struct inode *bitmap_inode,
 			struct buffer_head *bitmap_bh,
 			u64 start_blk,
 			unsigned int num_clusters);
 
+static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
+{
+	u64 group = block - (u64) bit;
+
+	return group;
+}
+
 static inline u32 ocfs2_cluster_from_desc(struct ocfs2_super *osb,
 					  u64 bg_blkno)
 {
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 86b559c..3a5a1ed 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -82,7 +82,8 @@
 MODULE_LICENSE("GPL");
 
 static int ocfs2_parse_options(struct super_block *sb, char *options,
-			       unsigned long *mount_opt, int is_remount);
+			       unsigned long *mount_opt, s16 *slot,
+			       int is_remount);
 static void ocfs2_put_super(struct super_block *sb);
 static int ocfs2_mount_volume(struct super_block *sb);
 static int ocfs2_remount(struct super_block *sb, int *flags, char *data);
@@ -114,8 +115,6 @@
 static struct inode *ocfs2_alloc_inode(struct super_block *sb);
 static void ocfs2_destroy_inode(struct inode *inode);
 
-static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
-
 static const struct super_operations ocfs2_sops = {
 	.statfs		= ocfs2_statfs,
 	.alloc_inode	= ocfs2_alloc_inode,
@@ -140,6 +139,7 @@
 	Opt_data_ordered,
 	Opt_data_writeback,
 	Opt_atime_quantum,
+	Opt_slot,
 	Opt_err,
 };
 
@@ -154,6 +154,7 @@
 	{Opt_data_ordered, "data=ordered"},
 	{Opt_data_writeback, "data=writeback"},
 	{Opt_atime_quantum, "atime_quantum=%u"},
+	{Opt_slot, "preferred_slot=%u"},
 	{Opt_err, NULL}
 };
 
@@ -318,7 +319,7 @@
 /* From xfs_super.c:xfs_max_file_offset
  * Copyright (c) 2000-2004 Silicon Graphics, Inc.
  */
-static unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
+unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
 {
 	unsigned int pagefactor = 1;
 	unsigned int bitshift = BITS_PER_LONG - 1;
@@ -355,9 +356,10 @@
 	int incompat_features;
 	int ret = 0;
 	unsigned long parsed_options;
+	s16 slot;
 	struct ocfs2_super *osb = OCFS2_SB(sb);
 
-	if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) {
+	if (!ocfs2_parse_options(sb, data, &parsed_options, &slot, 1)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -534,6 +536,7 @@
 	struct dentry *root;
 	int status, sector_size;
 	unsigned long parsed_opt;
+	s16 slot;
 	struct inode *inode = NULL;
 	struct ocfs2_super *osb = NULL;
 	struct buffer_head *bh = NULL;
@@ -541,7 +544,7 @@
 
 	mlog_entry("%p, %p, %i", sb, data, silent);
 
-	if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
+	if (!ocfs2_parse_options(sb, data, &parsed_opt, &slot, 0)) {
 		status = -EINVAL;
 		goto read_super_error;
 	}
@@ -571,6 +574,7 @@
 	brelse(bh);
 	bh = NULL;
 	osb->s_mount_opt = parsed_opt;
+	osb->preferred_slot = slot;
 
 	sb->s_magic = OCFS2_SUPER_MAGIC;
 
@@ -713,6 +717,7 @@
 static int ocfs2_parse_options(struct super_block *sb,
 			       char *options,
 			       unsigned long *mount_opt,
+			       s16 *slot,
 			       int is_remount)
 {
 	int status;
@@ -722,6 +727,7 @@
 		   options ? options : "(none)");
 
 	*mount_opt = 0;
+	*slot = OCFS2_INVALID_SLOT;
 
 	if (!options) {
 		status = 1;
@@ -782,6 +788,15 @@
 			else
 				osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
 			break;
+		case Opt_slot:
+			option = 0;
+			if (match_int(&args[0], &option)) {
+				status = 0;
+				goto bail;
+			}
+			if (option)
+				*slot = (s16)option;
+			break;
 		default:
 			mlog(ML_ERROR,
 			     "Unrecognized mount option \"%s\" "
diff --git a/fs/ocfs2/super.h b/fs/ocfs2/super.h
index 783f527..3b9cb3d 100644
--- a/fs/ocfs2/super.h
+++ b/fs/ocfs2/super.h
@@ -45,4 +45,6 @@
 
 #define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
 
+unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
+
 #endif /* OCFS2_SUPER_H */
diff --git a/fs/open.c b/fs/open.c
index 0d515d1..be6a457 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -855,7 +855,7 @@
 /*
  * Find an empty file descriptor entry, and mark it busy.
  */
-int get_unused_fd(void)
+int get_unused_fd_flags(int flags)
 {
 	struct files_struct * files = current->files;
 	int fd, error;
@@ -891,7 +891,10 @@
 	}
 
 	FD_SET(fd, fdt->open_fds);
-	FD_CLR(fd, fdt->close_on_exec);
+	if (flags & O_CLOEXEC)
+		FD_SET(fd, fdt->close_on_exec);
+	else
+		FD_CLR(fd, fdt->close_on_exec);
 	files->next_fd = fd + 1;
 #if 1
 	/* Sanity check */
@@ -907,6 +910,11 @@
 	return error;
 }
 
+int get_unused_fd(void)
+{
+	return get_unused_fd_flags(0);
+}
+
 EXPORT_SYMBOL(get_unused_fd);
 
 static void __put_unused_fd(struct files_struct *files, unsigned int fd)
@@ -959,7 +967,7 @@
 	int fd = PTR_ERR(tmp);
 
 	if (!IS_ERR(tmp)) {
-		fd = get_unused_fd();
+		fd = get_unused_fd_flags(flags);
 		if (fd >= 0) {
 			struct file *f = do_filp_open(dfd, tmp, flags, mode);
 			if (IS_ERR(f)) {
diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c
index e349132..3d3e166 100644
--- a/fs/partitions/acorn.c
+++ b/fs/partitions/acorn.c
@@ -25,6 +25,8 @@
 #define PARTITION_RISCIX_SCSI	2
 #define PARTITION_LINUX		9
 
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+	defined(CONFIG_ACORN_PARTITION_ADFS)
 static struct adfs_discrecord *
 adfs_partition(struct parsed_partitions *state, char *name, char *data,
 	       unsigned long first_sector, int slot)
@@ -48,6 +50,7 @@
 	put_partition(state, slot, first_sector, nr_sects);
 	return dr;
 }
+#endif
 
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
 
@@ -65,6 +68,8 @@
 	struct riscix_part part[8];
 };
 
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+	defined(CONFIG_ACORN_PARTITION_ADFS)
 static int
 riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
 		unsigned long first_sect, int slot, unsigned long nr_sects)
@@ -105,6 +110,7 @@
 	return slot;
 }
 #endif
+#endif
 
 #define LINUX_NATIVE_MAGIC 0xdeafa1de
 #define LINUX_SWAP_MAGIC   0xdeafab1e
@@ -115,6 +121,8 @@
 	__le32 nr_sects;
 };
 
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+	defined(CONFIG_ACORN_PARTITION_ADFS)
 static int
 linux_partition(struct parsed_partitions *state, struct block_device *bdev,
 		unsigned long first_sect, int slot, unsigned long nr_sects)
@@ -146,6 +154,7 @@
 	put_dev_sector(sect);
 	return slot;
 }
+#endif
 
 #ifdef CONFIG_ACORN_PARTITION_CUMANA
 int
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
index 99873a2..e7dd1d4 100644
--- a/fs/partitions/ldm.c
+++ b/fs/partitions/ldm.c
@@ -677,15 +677,24 @@
  * Return:  -1 Error, the calculated offset exceeded the size of the buffer
  *           n OK, a range-checked offset into buffer
  */
-static int ldm_relative (const u8 *buffer, int buflen, int base, int offset)
+static int ldm_relative(const u8 *buffer, int buflen, int base, int offset)
 {
 
 	base += offset;
-	if ((!buffer) || (offset < 0) || (base > buflen))
+	if (!buffer || offset < 0 || base > buflen) {
+		if (!buffer)
+			ldm_error("!buffer");
+		if (offset < 0)
+			ldm_error("offset (%d) < 0", offset);
+		if (base > buflen)
+			ldm_error("base (%d) > buflen (%d)", base, buflen);
 		return -1;
-	if ((base + buffer[base]) >= buflen)
+	}
+	if (base + buffer[base] >= buflen) {
+		ldm_error("base (%d) + buffer[base] (%d) >= buflen (%d)", base,
+				buffer[base], buflen);
 		return -1;
-
+	}
 	return buffer[base] + offset + 1;
 }
 
@@ -1054,60 +1063,98 @@
  * Return:  'true'   @vb contains a Volume VBLK
  *          'false'  @vb contents are not defined
  */
-static bool ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb)
 {
-	int r_objid, r_name, r_vtype, r_child, r_size, r_id1, r_id2, r_size2;
-	int r_drive, len;
+	int r_objid, r_name, r_vtype, r_disable_drive_letter, r_child, r_size;
+	int r_id1, r_id2, r_size2, r_drive, len;
 	struct vblk_volu *volu;
 
-	BUG_ON (!buffer || !vb);
-
-	r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
-	r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
-	r_vtype  = ldm_relative (buffer, buflen, 0x18, r_name);
-	r_child  = ldm_relative (buffer, buflen, 0x2E, r_vtype);
-	r_size   = ldm_relative (buffer, buflen, 0x3E, r_child);
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_ID1)
-		r_id1 = ldm_relative (buffer, buflen, 0x53, r_size);
-	else
+	BUG_ON(!buffer || !vb);
+	r_objid = ldm_relative(buffer, buflen, 0x18, 0);
+	if (r_objid < 0) {
+		ldm_error("r_objid %d < 0", r_objid);
+		return false;
+	}
+	r_name = ldm_relative(buffer, buflen, 0x18, r_objid);
+	if (r_name < 0) {
+		ldm_error("r_name %d < 0", r_name);
+		return false;
+	}
+	r_vtype = ldm_relative(buffer, buflen, 0x18, r_name);
+	if (r_vtype < 0) {
+		ldm_error("r_vtype %d < 0", r_vtype);
+		return false;
+	}
+	r_disable_drive_letter = ldm_relative(buffer, buflen, 0x18, r_vtype);
+	if (r_disable_drive_letter < 0) {
+		ldm_error("r_disable_drive_letter %d < 0",
+				r_disable_drive_letter);
+		return false;
+	}
+	r_child = ldm_relative(buffer, buflen, 0x2D, r_disable_drive_letter);
+	if (r_child < 0) {
+		ldm_error("r_child %d < 0", r_child);
+		return false;
+	}
+	r_size = ldm_relative(buffer, buflen, 0x3D, r_child);
+	if (r_size < 0) {
+		ldm_error("r_size %d < 0", r_size);
+		return false;
+	}
+	if (buffer[0x12] & VBLK_FLAG_VOLU_ID1) {
+		r_id1 = ldm_relative(buffer, buflen, 0x52, r_size);
+		if (r_id1 < 0) {
+			ldm_error("r_id1 %d < 0", r_id1);
+			return false;
+		}
+	} else
 		r_id1 = r_size;
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_ID2)
-		r_id2 = ldm_relative (buffer, buflen, 0x53, r_id1);
-	else
+	if (buffer[0x12] & VBLK_FLAG_VOLU_ID2) {
+		r_id2 = ldm_relative(buffer, buflen, 0x52, r_id1);
+		if (r_id2 < 0) {
+			ldm_error("r_id2 %d < 0", r_id2);
+			return false;
+		}
+	} else
 		r_id2 = r_id1;
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE)
-		r_size2 = ldm_relative (buffer, buflen, 0x53, r_id2);
-	else
+	if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE) {
+		r_size2 = ldm_relative(buffer, buflen, 0x52, r_id2);
+		if (r_size2 < 0) {
+			ldm_error("r_size2 %d < 0", r_size2);
+			return false;
+		}
+	} else
 		r_size2 = r_id2;
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE)
-		r_drive = ldm_relative (buffer, buflen, 0x53, r_size2);
-	else
-		r_drive = r_size2;
-
-	len = r_drive;
-	if (len < 0)
-		return false;
-
-	len += VBLK_SIZE_VOL5;
-	if (len != BE32 (buffer + 0x14))
-		return false;
-
-	volu = &vb->vblk.volu;
-
-	ldm_get_vstr (buffer + 0x18 + r_name,  volu->volume_type,
-		sizeof (volu->volume_type));
-	memcpy (volu->volume_state, buffer + 0x19 + r_vtype,
-			sizeof (volu->volume_state));
-	volu->size = ldm_get_vnum (buffer + 0x3E + r_child);
-	volu->partition_type = buffer[0x42 + r_size];
-	memcpy (volu->guid, buffer + 0x43 + r_size,  sizeof (volu->guid));
 	if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
-		ldm_get_vstr (buffer + 0x53 + r_size,  volu->drive_hint,
-			sizeof (volu->drive_hint));
+		r_drive = ldm_relative(buffer, buflen, 0x52, r_size2);
+		if (r_drive < 0) {
+			ldm_error("r_drive %d < 0", r_drive);
+			return false;
+		}
+	} else
+		r_drive = r_size2;
+	len = r_drive;
+	if (len < 0) {
+		ldm_error("len %d < 0", len);
+		return false;
+	}
+	len += VBLK_SIZE_VOL5;
+	if (len > BE32(buffer + 0x14)) {
+		ldm_error("len %d > BE32(buffer + 0x14) %d", len,
+				BE32(buffer + 0x14));
+		return false;
+	}
+	volu = &vb->vblk.volu;
+	ldm_get_vstr(buffer + 0x18 + r_name, volu->volume_type,
+			sizeof(volu->volume_type));
+	memcpy(volu->volume_state, buffer + 0x18 + r_disable_drive_letter,
+			sizeof(volu->volume_state));
+	volu->size = ldm_get_vnum(buffer + 0x3D + r_child);
+	volu->partition_type = buffer[0x41 + r_size];
+	memcpy(volu->guid, buffer + 0x42 + r_size, sizeof(volu->guid));
+	if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
+		ldm_get_vstr(buffer + 0x52 + r_size, volu->drive_hint,
+				sizeof(volu->drive_hint));
 	}
 	return true;
 }
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h
index d2e6a30..80f63b5 100644
--- a/fs/partitions/ldm.h
+++ b/fs/partitions/ldm.h
@@ -68,7 +68,7 @@
 #define VBLK_SIZE_DSK3		12
 #define VBLK_SIZE_DSK4		45
 #define VBLK_SIZE_PRT3		28
-#define VBLK_SIZE_VOL5		59
+#define VBLK_SIZE_VOL5		58
 
 /* component types */
 #define COMP_STRIPE		0x01		/* Stripe-set */
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 98e78e2..965625a 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -62,6 +62,8 @@
 #include <linux/mman.h>
 #include <linux/proc_fs.h>
 #include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
@@ -76,9 +78,7 @@
 #include <linux/rcupdate.h>
 #include <linux/delayacct.h>
 
-#include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/io.h>
 #include <asm/processor.h>
 #include "internal.h"
 
@@ -87,10 +87,10 @@
 do { memcpy(buffer, string, strlen(string)); \
      buffer += strlen(string); } while (0)
 
-static inline char * task_name(struct task_struct *p, char * buf)
+static inline char *task_name(struct task_struct *p, char *buf)
 {
 	int i;
-	char * name;
+	char *name;
 	char tcomm[sizeof(p->comm)];
 
 	get_task_comm(tcomm, p);
@@ -138,7 +138,7 @@
 	"X (dead)"		/* 32 */
 };
 
-static inline const char * get_task_state(struct task_struct *tsk)
+static inline const char *get_task_state(struct task_struct *tsk)
 {
 	unsigned int state = (tsk->state & (TASK_RUNNING |
 					    TASK_INTERRUPTIBLE |
@@ -156,7 +156,7 @@
 	return *p;
 }
 
-static inline char * task_state(struct task_struct *p, char *buffer)
+static inline char *task_state(struct task_struct *p, char *buffer)
 {
 	struct group_info *group_info;
 	int g;
@@ -172,8 +172,8 @@
 		"Uid:\t%d\t%d\t%d\t%d\n"
 		"Gid:\t%d\t%d\t%d\t%d\n",
 		get_task_state(p),
-	       	p->tgid, p->pid,
-	       	pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
+		p->tgid, p->pid,
+		pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
 		pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
 		p->uid, p->euid, p->suid, p->fsuid,
 		p->gid, p->egid, p->sgid, p->fsgid);
@@ -191,15 +191,15 @@
 	get_group_info(group_info);
 	task_unlock(p);
 
-	for (g = 0; g < min(group_info->ngroups,NGROUPS_SMALL); g++)
-		buffer += sprintf(buffer, "%d ", GROUP_AT(group_info,g));
+	for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
+		buffer += sprintf(buffer, "%d ", GROUP_AT(group_info, g));
 	put_group_info(group_info);
 
 	buffer += sprintf(buffer, "\n");
 	return buffer;
 }
 
-static char * render_sigset_t(const char *header, sigset_t *set, char *buffer)
+static char *render_sigset_t(const char *header, sigset_t *set, char *buffer)
 {
 	int i, len;
 
@@ -239,7 +239,7 @@
 	}
 }
 
-static inline char * task_sig(struct task_struct *p, char *buffer)
+static inline char *task_sig(struct task_struct *p, char *buffer)
 {
 	unsigned long flags;
 	sigset_t pending, shpending, blocked, ignored, caught;
@@ -289,14 +289,23 @@
 			    cap_t(p->cap_effective));
 }
 
-int proc_pid_status(struct task_struct *task, char * buffer)
+static inline char *task_context_switch_counts(struct task_struct *p,
+						char *buffer)
 {
-	char * orig = buffer;
+	return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n"
+			    "nonvoluntary_ctxt_switches:\t%lu\n",
+			    p->nvcsw,
+			    p->nivcsw);
+}
+
+int proc_pid_status(struct task_struct *task, char *buffer)
+{
+	char *orig = buffer;
 	struct mm_struct *mm = get_task_mm(task);
 
 	buffer = task_name(task, buffer);
 	buffer = task_state(task, buffer);
- 
+
 	if (mm) {
 		buffer = task_mem(mm, buffer);
 		mmput(mm);
@@ -307,6 +316,7 @@
 #if defined(CONFIG_S390)
 	buffer = task_show_regs(task, buffer);
 #endif
+	buffer = task_context_switch_counts(task, buffer);
 	return buffer - orig;
 }
 
@@ -332,7 +342,7 @@
 
 static clock_t task_stime(struct task_struct *p)
 {
-	clock_t stime = cputime_to_clock_t(p->stime);
+	clock_t stime;
 
 	/*
 	 * Use CFS's precise accounting. (we subtract utime from
@@ -344,8 +354,7 @@
 	return stime;
 }
 
-
-static int do_task_stat(struct task_struct *task, char * buffer, int whole)
+static int do_task_stat(struct task_struct *task, char *buffer, int whole)
 {
 	unsigned long vsize, eip, esp, wchan = ~0UL;
 	long priority, nice;
@@ -353,7 +362,7 @@
 	sigset_t sigign, sigcatch;
 	char state;
 	int res;
- 	pid_t ppid = 0, pgid = -1, sid = -1;
+	pid_t ppid = 0, pgid = -1, sid = -1;
 	int num_threads = 0;
 	struct mm_struct *mm;
 	unsigned long long start_time;
@@ -424,7 +433,7 @@
 	}
 	rcu_read_unlock();
 
-	if (!whole || num_threads<2)
+	if (!whole || num_threads < 2)
 		wchan = get_wchan(task);
 	if (!whole) {
 		min_flt = task->min_flt;
@@ -440,12 +449,13 @@
 
 	/* Temporary variable needed for gcc-2.96 */
 	/* convert timespec -> nsec*/
-	start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC
-				+ task->start_time.tv_nsec;
+	start_time =
+		(unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
+				+ task->real_start_time.tv_nsec;
 	/* convert nsec -> ticks */
 	start_time = nsec_to_clock_t(start_time);
 
-	res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %lu \
+	res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
 %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n",
 		task->pid,
@@ -471,7 +481,7 @@
 		start_time,
 		vsize,
 		mm ? get_mm_rss(mm) : 0,
-	        rsslim,
+		rsslim,
 		mm ? mm->start_code : 0,
 		mm ? mm->end_code : 0,
 		mm ? mm->start_stack : 0,
@@ -493,17 +503,17 @@
 		task->rt_priority,
 		task->policy,
 		(unsigned long long)delayacct_blkio_ticks(task));
-	if(mm)
+	if (mm)
 		mmput(mm);
 	return res;
 }
 
-int proc_tid_stat(struct task_struct *task, char * buffer)
+int proc_tid_stat(struct task_struct *task, char *buffer)
 {
 	return do_task_stat(task, buffer, 0);
 }
 
-int proc_tgid_stat(struct task_struct *task, char * buffer)
+int proc_tgid_stat(struct task_struct *task, char *buffer)
 {
 	return do_task_stat(task, buffer, 1);
 }
@@ -512,12 +522,12 @@
 {
 	int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
 	struct mm_struct *mm = get_task_mm(task);
-	
+
 	if (mm) {
 		size = task_statm(mm, &shared, &text, &data, &resident);
 		mmput(mm);
 	}
 
-	return sprintf(buffer,"%d %d %d %d %d %d %d\n",
+	return sprintf(buffer, "%d %d %d %d %d %d %d\n",
 		       size, resident, shared, text, lib, data, 0);
 }
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 46ea5d5..42cb4f5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -67,7 +67,6 @@
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
-#include <linux/seccomp.h>
 #include <linux/cpuset.h>
 #include <linux/audit.h>
 #include <linux/poll.h>
@@ -204,12 +203,17 @@
 	int res = 0;
 	struct mm_struct *mm = get_task_mm(task);
 	if (mm) {
-		unsigned int len = mm->env_end - mm->env_start;
+		unsigned int len;
+
+		res = -ESRCH;
+		if (!ptrace_may_attach(task))
+			goto out;
+
+		len  = mm->env_end - mm->env_start;
 		if (len > PAGE_SIZE)
 			len = PAGE_SIZE;
 		res = access_process_vm(task, mm->env_start, buffer, len, 0);
-		if (!ptrace_may_attach(task))
-			res = -ESRCH;
+out:
 		mmput(mm);
 	}
 	return res;
@@ -279,7 +283,7 @@
 static int proc_pid_wchan(struct task_struct *task, char *buffer)
 {
 	unsigned long wchan;
-	char symname[KSYM_NAME_LEN+1];
+	char symname[KSYM_NAME_LEN];
 
 	wchan = get_wchan(task);
 
@@ -812,71 +816,6 @@
 };
 #endif
 
-#ifdef CONFIG_SECCOMP
-static ssize_t seccomp_read(struct file *file, char __user *buf,
-			    size_t count, loff_t *ppos)
-{
-	struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
-	char __buf[20];
-	size_t len;
-
-	if (!tsk)
-		return -ESRCH;
-	/* no need to print the trailing zero, so use only len */
-	len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
-	put_task_struct(tsk);
-
-	return simple_read_from_buffer(buf, count, ppos, __buf, len);
-}
-
-static ssize_t seccomp_write(struct file *file, const char __user *buf,
-			     size_t count, loff_t *ppos)
-{
-	struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
-	char __buf[20], *end;
-	unsigned int seccomp_mode;
-	ssize_t result;
-
-	result = -ESRCH;
-	if (!tsk)
-		goto out_no_task;
-
-	/* can set it only once to be even more secure */
-	result = -EPERM;
-	if (unlikely(tsk->seccomp.mode))
-		goto out;
-
-	result = -EFAULT;
-	memset(__buf, 0, sizeof(__buf));
-	count = min(count, sizeof(__buf) - 1);
-	if (copy_from_user(__buf, buf, count))
-		goto out;
-
-	seccomp_mode = simple_strtoul(__buf, &end, 0);
-	if (*end == '\n')
-		end++;
-	result = -EINVAL;
-	if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
-		tsk->seccomp.mode = seccomp_mode;
-		set_tsk_thread_flag(tsk, TIF_SECCOMP);
-	} else
-		goto out;
-	result = -EIO;
-	if (unlikely(!(end - __buf)))
-		goto out;
-	result = end - __buf;
-out:
-	put_task_struct(tsk);
-out_no_task:
-	return result;
-}
-
-static const struct file_operations proc_seccomp_operations = {
-	.read		= seccomp_read,
-	.write		= seccomp_write,
-};
-#endif /* CONFIG_SECCOMP */
-
 #ifdef CONFIG_FAULT_INJECTION
 static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
 				      size_t count, loff_t *ppos)
@@ -2037,9 +1976,6 @@
 	REG("numa_maps",  S_IRUGO, numa_maps),
 #endif
 	REG("mem",        S_IRUSR|S_IWUSR, mem),
-#ifdef CONFIG_SECCOMP
-	REG("seccomp",    S_IRUSR|S_IWUSR, seccomp),
-#endif
 	LNK("cwd",        cwd),
 	LNK("root",       root),
 	LNK("exe",        exe),
@@ -2324,9 +2260,6 @@
 	REG("numa_maps", S_IRUGO, numa_maps),
 #endif
 	REG("mem",       S_IRUSR|S_IWUSR, mem),
-#ifdef CONFIG_SECCOMP
-	REG("seccomp",   S_IRUSR|S_IWUSR, seccomp),
-#endif
 	LNK("cwd",       cwd),
 	LNK("root",      root),
 	LNK("exe",       exe),
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a40e15..b5e7155 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -20,6 +20,7 @@
 #include <linux/namei.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
+#include <linux/completion.h>
 #include <asm/uaccess.h>
 
 #include "internal.h"
@@ -529,12 +530,6 @@
 		return -EAGAIN;
 	dp->low_ino = i;
 
-	spin_lock(&proc_subdir_lock);
-	dp->next = dir->subdir;
-	dp->parent = dir;
-	dir->subdir = dp;
-	spin_unlock(&proc_subdir_lock);
-
 	if (S_ISDIR(dp->mode)) {
 		if (dp->proc_iops == NULL) {
 			dp->proc_fops = &proc_dir_operations;
@@ -550,6 +545,13 @@
 		if (dp->proc_iops == NULL)
 			dp->proc_iops = &proc_file_inode_operations;
 	}
+
+	spin_lock(&proc_subdir_lock);
+	dp->next = dir->subdir;
+	dp->parent = dir;
+	dir->subdir = dp;
+	spin_unlock(&proc_subdir_lock);
+
 	return 0;
 }
 
@@ -613,6 +615,9 @@
 	ent->namelen = len;
 	ent->mode = mode;
 	ent->nlink = nlink;
+	ent->pde_users = 0;
+	spin_lock_init(&ent->pde_unload_lock);
+	ent->pde_unload_completion = NULL;
  out:
 	return ent;
 }
@@ -649,9 +654,6 @@
 
 	ent = proc_create(&parent, name, S_IFDIR | mode, 2);
 	if (ent) {
-		ent->proc_fops = &proc_dir_operations;
-		ent->proc_iops = &proc_dir_inode_operations;
-
 		if (proc_register(parent, ent) < 0) {
 			kfree(ent);
 			ent = NULL;
@@ -686,10 +688,6 @@
 
 	ent = proc_create(&parent,name,mode,nlink);
 	if (ent) {
-		if (S_ISDIR(mode)) {
-			ent->proc_fops = &proc_dir_operations;
-			ent->proc_iops = &proc_dir_inode_operations;
-		}
 		if (proc_register(parent, ent) < 0) {
 			kfree(ent);
 			ent = NULL;
@@ -734,9 +732,35 @@
 		de = *p;
 		*p = de->next;
 		de->next = NULL;
+
+		spin_lock(&de->pde_unload_lock);
+		/*
+		 * Stop accepting new callers into module. If you're
+		 * dynamically allocating ->proc_fops, save a pointer somewhere.
+		 */
+		de->proc_fops = NULL;
+		/* Wait until all existing callers into module are done. */
+		if (de->pde_users > 0) {
+			DECLARE_COMPLETION_ONSTACK(c);
+
+			if (!de->pde_unload_completion)
+				de->pde_unload_completion = &c;
+
+			spin_unlock(&de->pde_unload_lock);
+			spin_unlock(&proc_subdir_lock);
+
+			wait_for_completion(de->pde_unload_completion);
+
+			spin_lock(&proc_subdir_lock);
+			goto continue_removing;
+		}
+		spin_unlock(&de->pde_unload_lock);
+
+continue_removing:
 		if (S_ISDIR(de->mode))
 			parent->nlink--;
-		proc_kill_inodes(de);
+		if (!S_ISREG(de->mode))
+			proc_kill_inodes(de);
 		de->nlink = 0;
 		WARN_ON(de->subdir);
 		if (!atomic_read(&de->count))
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d5ce65c..dd28e86 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/completion.h>
 #include <linux/file.h>
 #include <linux/limits.h>
 #include <linux/init.h>
@@ -140,6 +141,251 @@
 	.remount_fs	= proc_remount,
 };
 
+static void pde_users_dec(struct proc_dir_entry *pde)
+{
+	spin_lock(&pde->pde_unload_lock);
+	pde->pde_users--;
+	if (pde->pde_unload_completion && pde->pde_users == 0)
+		complete(pde->pde_unload_completion);
+	spin_unlock(&pde->pde_unload_lock);
+}
+
+static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	loff_t rv = -EINVAL;
+	loff_t (*llseek)(struct file *, loff_t, int);
+
+	spin_lock(&pde->pde_unload_lock);
+	/*
+	 * remove_proc_entry() is going to delete PDE (as part of module
+	 * cleanup sequence). No new callers into module allowed.
+	 */
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	/*
+	 * Bump refcount so that remove_proc_entry will wail for ->llseek to
+	 * complete.
+	 */
+	pde->pde_users++;
+	/*
+	 * Save function pointer under lock, to protect against ->proc_fops
+	 * NULL'ifying right after ->pde_unload_lock is dropped.
+	 */
+	llseek = pde->proc_fops->llseek;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (!llseek)
+		llseek = default_llseek;
+	rv = llseek(file, offset, whence);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	ssize_t rv = -EIO;
+	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	read = pde->proc_fops->read;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (read)
+		rv = read(file, buf, count, ppos);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	ssize_t rv = -EIO;
+	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	write = pde->proc_fops->write;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (write)
+		rv = write(file, buf, count, ppos);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	unsigned int rv = 0;
+	unsigned int (*poll)(struct file *, struct poll_table_struct *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	poll = pde->proc_fops->poll;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (poll)
+		rv = poll(file, pts);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	long rv = -ENOTTY;
+	long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
+	int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	unlocked_ioctl = pde->proc_fops->unlocked_ioctl;
+	ioctl = pde->proc_fops->ioctl;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (unlocked_ioctl) {
+		rv = unlocked_ioctl(file, cmd, arg);
+		if (rv == -ENOIOCTLCMD)
+			rv = -EINVAL;
+	} else if (ioctl) {
+		lock_kernel();
+		rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
+		unlock_kernel();
+	}
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+#ifdef CONFIG_COMPAT
+static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	long rv = -ENOTTY;
+	long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	compat_ioctl = pde->proc_fops->compat_ioctl;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (compat_ioctl)
+		rv = compat_ioctl(file, cmd, arg);
+
+	pde_users_dec(pde);
+	return rv;
+}
+#endif
+
+static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	int rv = -EIO;
+	int (*mmap)(struct file *, struct vm_area_struct *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	mmap = pde->proc_fops->mmap;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (mmap)
+		rv = mmap(file, vma);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static int proc_reg_open(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *pde = PDE(inode);
+	int rv = 0;
+	int (*open)(struct inode *, struct file *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	open = pde->proc_fops->open;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (open)
+		rv = open(inode, file);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static int proc_reg_release(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *pde = PDE(inode);
+	int rv = 0;
+	int (*release)(struct inode *, struct file *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	release = pde->proc_fops->release;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (release)
+		rv = release(inode, file);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static const struct file_operations proc_reg_file_ops = {
+	.llseek		= proc_reg_llseek,
+	.read		= proc_reg_read,
+	.write		= proc_reg_write,
+	.poll		= proc_reg_poll,
+	.unlocked_ioctl	= proc_reg_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= proc_reg_compat_ioctl,
+#endif
+	.mmap		= proc_reg_mmap,
+	.open		= proc_reg_open,
+	.release	= proc_reg_release,
+};
+
 struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
 				struct proc_dir_entry *de)
 {
@@ -166,8 +412,12 @@
 			inode->i_nlink = de->nlink;
 		if (de->proc_iops)
 			inode->i_op = de->proc_iops;
-		if (de->proc_fops)
-			inode->i_fop = de->proc_fops;
+		if (de->proc_fops) {
+			if (S_ISREG(inode->i_mode))
+				inode->i_fop = &proc_reg_file_ops;
+			else
+				inode->i_fop = de->proc_fops;
+		}
 	}
 
 	return inode;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 5fd49e4..d24b8d4 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -105,6 +105,7 @@
 	cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
 
 	do_posix_clock_monotonic_gettime(&uptime);
+	monotonic_to_bootbased(&uptime);
 	cputime_to_timespec(idletime, &idle);
 	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
 			(unsigned long) uptime.tv_sec,
@@ -443,12 +444,12 @@
 	unsigned long jif;
 	cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
 	u64 sum = 0;
+	struct timespec boottime;
 
 	user = nice = system = idle = iowait =
 		irq = softirq = steal = cputime64_zero;
-	jif = - wall_to_monotonic.tv_sec;
-	if (wall_to_monotonic.tv_nsec)
-		--jif;
+	getboottime(&boottime);
+	jif = boottime.tv_sec;
 
 	for_each_possible_cpu(i) {
 		int j;
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index b3a473b..2284622 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -69,7 +69,7 @@
 
 static int show_tty_driver(struct seq_file *m, void *v)
 {
-	struct tty_driver *p = v;
+	struct tty_driver *p = list_entry(v, struct tty_driver, tty_drivers);
 	dev_t from = MKDEV(p->major, p->minor_start);
 	dev_t to = from + p->num;
 
@@ -106,22 +106,13 @@
 /* iterator */
 static void *t_start(struct seq_file *m, loff_t *pos)
 {
-	struct list_head *p;
-	loff_t l = *pos;
-
 	mutex_lock(&tty_mutex);
-	list_for_each(p, &tty_drivers)
-		if (!l--)
-			return list_entry(p, struct tty_driver, tty_drivers);
-	return NULL;
+	return seq_list_start(&tty_drivers, *pos);
 }
 
 static void *t_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	struct list_head *p = ((struct tty_driver *)v)->tty_drivers.next;
-	(*pos)++;
-	return p==&tty_drivers ? NULL :
-			list_entry(p, struct tty_driver, tty_drivers);
+	return seq_list_next(v, &tty_drivers, pos);
 }
 
 static void t_stop(struct seq_file *m, void *v)
diff --git a/fs/quota.c b/fs/quota.c
index 9f237d6..e6577ac 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -10,12 +10,14 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
+#include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/types.h>
 
 /* Check validity of generic quotactl commands */
 static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
@@ -384,3 +386,119 @@
 
 	return ret;
 }
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 dqb_bsoftlimit;
+	compat_u64 dqb_curspace;
+	compat_u64 dqb_ihardlimit;
+	compat_u64 dqb_isoftlimit;
+	compat_u64 dqb_curinodes;
+	compat_u64 dqb_btime;
+	compat_u64 dqb_itime;
+	compat_uint_t dqb_valid;
+};
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 qfs_nblks;
+	compat_uint_t qfs_nextents;
+};
+
+struct compat_fs_quota_stat {
+	__s8		qs_version;
+	__u16		qs_flags;
+	__s8		qs_pad;
+	struct compat_fs_qfilestat	qs_uquota;
+	struct compat_fs_qfilestat	qs_gquota;
+	compat_uint_t	qs_incoredqs;
+	compat_int_t	qs_btimelimit;
+	compat_int_t	qs_itimelimit;
+	compat_int_t	qs_rtbtimelimit;
+	__u16		qs_bwarnlimit;
+	__u16		qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	unsigned int cmds;
+	struct if_dqblk __user *dqblk;
+	struct compat_if_dqblk __user *compat_dqblk;
+	struct fs_quota_stat __user *fsqstat;
+	struct compat_fs_quota_stat __user *compat_fsqstat;
+	compat_uint_t data;
+	u16 xdata;
+	long ret;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+	case Q_GETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		if (ret)
+			break;
+		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &dqblk->dqb_valid) ||
+			put_user(data, &compat_dqblk->dqb_valid))
+			ret = -EFAULT;
+		break;
+	case Q_SETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = -EFAULT;
+		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &compat_dqblk->dqb_valid) ||
+			put_user(data, &dqblk->dqb_valid))
+			break;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		break;
+	case Q_XGETQSTAT:
+		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+		compat_fsqstat = addr;
+		ret = sys_quotactl(cmd, special, id, fsqstat);
+		if (ret)
+			break;
+		ret = -EFAULT;
+		/* Copying qs_version, qs_flags, qs_pad */
+		if (copy_in_user(compat_fsqstat, fsqstat,
+			offsetof(struct compat_fs_quota_stat, qs_uquota)))
+			break;
+		/* Copying qs_uquota */
+		if (copy_in_user(&compat_fsqstat->qs_uquota,
+			&fsqstat->qs_uquota,
+			sizeof(compat_fsqstat->qs_uquota)) ||
+			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+			break;
+		/* Copying qs_gquota */
+		if (copy_in_user(&compat_fsqstat->qs_gquota,
+			&fsqstat->qs_gquota,
+			sizeof(compat_fsqstat->qs_gquota)) ||
+			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+			break;
+		/* Copying the rest */
+		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+			&fsqstat->qs_incoredqs,
+			sizeof(struct compat_fs_quota_stat) -
+			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+			break;
+		ret = 0;
+		break;
+	default:
+		ret = sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
+#endif
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index d40d22b..ef2b46d 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -60,6 +60,7 @@
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &ramfs_aops;
 		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
+		mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
 		default:
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 30eebfb..2070aee 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1305,7 +1305,6 @@
 	if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
 	    *ppos + count > MAX_NON_LFS) {
 		if (*ppos >= MAX_NON_LFS) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 		if (count > MAX_NON_LFS - (unsigned long)*ppos)
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 1272d11..ddde489 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -7,6 +7,7 @@
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 #include <linux/reiserfs_xattr.h>
+#include <linux/exportfs.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b4ac911..5a93cfe 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/mnt_namespace.h>
 #include <linux/mount.h>
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 49194a4..bbb19be 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -177,21 +177,23 @@
 
 static int traverse(struct seq_file *m, loff_t offset)
 {
-	loff_t pos = 0;
+	loff_t pos = 0, index;
 	int error = 0;
 	void *p;
 
 	m->version = 0;
-	m->index = 0;
+	index = 0;
 	m->count = m->from = 0;
-	if (!offset)
+	if (!offset) {
+		m->index = index;
 		return 0;
+	}
 	if (!m->buf) {
 		m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
 		if (!m->buf)
 			return -ENOMEM;
 	}
-	p = m->op->start(m, &m->index);
+	p = m->op->start(m, &index);
 	while (p) {
 		error = PTR_ERR(p);
 		if (IS_ERR(p))
@@ -204,15 +206,17 @@
 		if (pos + m->count > offset) {
 			m->from = offset - pos;
 			m->count -= m->from;
+			m->index = index;
 			break;
 		}
 		pos += m->count;
 		m->count = 0;
 		if (pos == offset) {
-			m->index++;
+			index++;
+			m->index = index;
 			break;
 		}
-		p = m->op->next(m, p, &m->index);
+		p = m->op->next(m, p, &index);
 	}
 	m->op->stop(m, p);
 	return error;
@@ -260,8 +264,8 @@
 				}
 			}
 	}
-	mutex_unlock(&m->lock);
 	file->f_version = m->version;
+	mutex_unlock(&m->lock);
 	return retval;
 }
 EXPORT_SYMBOL(seq_lseek);
diff --git a/fs/splice.c b/fs/splice.c
index 6c98286..53fc208 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1061,8 +1061,9 @@
 
 	while (len) {
 		size_t read_len;
+		loff_t pos = sd->pos;
 
-		ret = do_splice_to(in, &sd->pos, pipe, len, flags);
+		ret = do_splice_to(in, &pos, pipe, len, flags);
 		if (unlikely(ret <= 0))
 			goto out_release;
 
@@ -1080,6 +1081,7 @@
 
 		bytes += ret;
 		len -= ret;
+		sd->pos = pos;
 
 		if (ret < read_len)
 			goto out_release;
diff --git a/fs/super.c b/fs/super.c
index 5260d62..fc8ebed 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -884,6 +884,7 @@
 	error = type->get_sb(type, flags, name, data, mnt);
 	if (error < 0)
 		goto out_free_secdata;
+	BUG_ON(!mnt->mnt_sb);
 
  	error = security_sb_kern_mount(mnt->mnt_sb, secdata);
  	if (error)
diff --git a/fs/udf/crc.c b/fs/udf/crc.c
index 1b82a4a..ef2bfaa 100644
--- a/fs/udf/crc.c
+++ b/fs/udf/crc.c
@@ -106,8 +106,8 @@
 {
 	unsigned short x;
 
-	x = udf_crc16(bytes, sizeof bytes);
-	printf("udf_crc16: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
+	x = udf_crc(bytes, sizeof bytes);
+	printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
 
 	return 0;
 }
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 8206983..10f3188 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -50,7 +50,7 @@
 		else
 			UDF_SB_LVIDIU(sb)->numFiles =
 				cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1);
-		
+
 		mark_buffer_dirty(sbi->s_lvidbh);
 	}
 	mutex_unlock(&sbi->s_alloc_mutex);
@@ -136,6 +136,13 @@
 		UDF_I_EFE(inode) = 0;
 		UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
 	}
+	if (!UDF_I_DATA(inode))
+	{
+		iput(inode);
+		*err = -ENOMEM;
+		mutex_unlock(&sbi->s_alloc_mutex);
+		return NULL;
+	}
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index bf7de0b..5b82e48 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -49,6 +49,7 @@
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
+static int udf_alloc_i_data(struct inode *inode, size_t size);
 static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
 	long *, int *);
 static int8_t udf_insert_aext(struct inode *, struct extent_position,
@@ -734,7 +735,7 @@
 			(*c) ++;
 			(*endnum) ++;
 		}
-		
+
 		laarr[curr].extLocation.logicalBlockNum = newblocknum;
 		if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
 			laarr[curr].extLocation.partitionReferenceNum =
@@ -836,7 +837,7 @@
 				{
 					numalloc -= elen;
 					if (*endnum > (i+1))
-						memmove(&laarr[i], &laarr[i+1], 
+						memmove(&laarr[i], &laarr[i+1],
 							sizeof(long_ad) * (*endnum - (i+1)));
 					i --;
 					(*endnum) --;
@@ -1024,7 +1025,7 @@
 	{
 		block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block);
 		udf_truncate_extents(inode);
-	}	
+	}
 
 	inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
 	if (IS_SYNC(inode))
@@ -1087,10 +1088,10 @@
 			{
 				kernel_lb_addr loc;
 				ie = (struct indirectEntry *)ibh->b_data;
-	
+
 				loc = lelb_to_cpu(ie->indirectICB.extLocation);
-	
-				if (ie->indirectICB.extLength && 
+
+				if (ie->indirectICB.extLength &&
 					(nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident)))
 				{
 					if (ident == TAG_IDENT_FE ||
@@ -1156,14 +1157,22 @@
 	{
 		UDF_I_EFE(inode) = 1;
 		UDF_I_USE(inode) = 0;
-		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)))
+		{
+			make_bad_inode(inode);
+			return;
+		}
 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
 	}
 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
 	{
 		UDF_I_EFE(inode) = 0;
 		UDF_I_USE(inode) = 0;
-		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct fileEntry)))
+		{
+			make_bad_inode(inode);
+			return;
+		}
 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
 	}
 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
@@ -1173,7 +1182,11 @@
 		UDF_I_LENALLOC(inode) =
 			le32_to_cpu(
 				((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
-		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
+		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)))
+		{
+			make_bad_inode(inode);
+			return;
+		}
 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
 		return;
 	}
@@ -1191,7 +1204,7 @@
 	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
 	if (!inode->i_nlink)
 		inode->i_nlink = 1;
-	
+
 	inode->i_size = le64_to_cpu(fe->informationLength);
 	UDF_I_LENEXTENTS(inode) = inode->i_size;
 
@@ -1243,7 +1256,7 @@
 	}
 	else
 	{
-		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << 
+		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
 			(inode->i_sb->s_blocksize_bits - 9);
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
@@ -1374,6 +1387,20 @@
 	}
 }
 
+static int udf_alloc_i_data(struct inode *inode, size_t size)
+{
+	UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL);
+
+	if (!UDF_I_DATA(inode))
+	{
+		printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) no free memory\n",
+		       inode->i_ino);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 static mode_t
 udf_convert_permissions(struct fileEntry *fe)
 {
@@ -2072,7 +2099,7 @@
 			mark_buffer_dirty_inode(oepos.bh, inode);
 		}
 	}
-	
+
 	brelse(epos.bh);
 	brelse(oepos.bh);
 	return (elen >> 30);
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 22ff6ed..2b30116 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -87,6 +87,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
+#include <linux/log2.h>
 
 #include "swab.h"
 #include "util.h"
@@ -854,7 +855,7 @@
 	uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
 	uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
 
-	if (uspi->s_fsize & (uspi->s_fsize - 1)) {
+	if (!is_power_of_2(uspi->s_fsize)) {
 		printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n",
 			uspi->s_fsize);
 			goto failed;
@@ -869,7 +870,7 @@
 			uspi->s_fsize);
 		goto failed;
 	}
-	if (uspi->s_bsize & (uspi->s_bsize - 1)) {
+	if (!is_power_of_2(uspi->s_bsize)) {
 		printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n",
 			uspi->s_bsize);
 		goto failed;
diff --git a/fs/utimes.c b/fs/utimes.c
index b3c8895..83a7e69 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -106,7 +106,7 @@
                 if (IS_IMMUTABLE(inode))
                         goto dput_and_out;
 
-		if (current->fsuid != inode->i_uid) {
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) {
 			if (f) {
 				if (!(f->f_mode & FMODE_WRITE))
 					goto dput_and_out;
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 2df6362..b0f0e58 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -35,10 +35,13 @@
 #include <linux/freezer.h>
 
 static kmem_zone_t *xfs_buf_zone;
-static struct shrinker *xfs_buf_shake;
 STATIC int xfsbufd(void *);
 STATIC int xfsbufd_wakeup(int, gfp_t);
 STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
+static struct shrinker xfs_buf_shake = {
+	.shrink = xfsbufd_wakeup,
+	.seeks = DEFAULT_SEEKS,
+};
 
 static struct workqueue_struct *xfslogd_workqueue;
 struct workqueue_struct *xfsdatad_workqueue;
@@ -1832,14 +1835,9 @@
 	if (!xfsdatad_workqueue)
 		goto out_destroy_xfslogd_workqueue;
 
-	xfs_buf_shake = set_shrinker(DEFAULT_SEEKS, xfsbufd_wakeup);
-	if (!xfs_buf_shake)
-		goto out_destroy_xfsdatad_workqueue;
-
+	register_shrinker(&xfs_buf_shake);
 	return 0;
 
- out_destroy_xfsdatad_workqueue:
-	destroy_workqueue(xfsdatad_workqueue);
  out_destroy_xfslogd_workqueue:
 	destroy_workqueue(xfslogd_workqueue);
  out_free_buf_zone:
@@ -1854,7 +1852,7 @@
 void
 xfs_buf_terminate(void)
 {
-	remove_shrinker(xfs_buf_shake);
+	unregister_shrinker(&xfs_buf_shake);
 	destroy_workqueue(xfsdatad_workqueue);
 	destroy_workqueue(xfslogd_workqueue);
 	kmem_zone_destroy(xfs_buf_zone);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 06894cf..4528f9a 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -562,6 +562,7 @@
 	bhv_vfs_sync_work_t	*work, *n;
 	LIST_HEAD		(tmp);
 
+	set_freezable();
 	timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
 	for (;;) {
 		timeleft = schedule_timeout_interruptible(timeleft);
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 33dd1ca..201cc32 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -18,6 +18,8 @@
 #ifndef __XFS_SUPER_H__
 #define __XFS_SUPER_H__
 
+#include <linux/exportfs.h>
+
 #ifdef CONFIG_XFS_DMAPI
 # define vfs_insertdmapi(vfs)	vfs_insertops(vfsp, &xfs_dmops)
 # define vfs_initdmapi()	dmapi_init()
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 7def4c6..2d274b2 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -62,7 +62,6 @@
 
 kmem_zone_t	*qm_dqzone;
 kmem_zone_t	*qm_dqtrxzone;
-static struct shrinker *xfs_qm_shaker;
 
 static cred_t	xfs_zerocr;
 
@@ -78,6 +77,11 @@
 STATIC int	xfs_qm_init_quotainfo(xfs_mount_t *);
 STATIC int	xfs_qm_shake(int, gfp_t);
 
+static struct shrinker xfs_qm_shaker = {
+	.shrink = xfs_qm_shake,
+	.seeks = DEFAULT_SEEKS,
+};
+
 #ifdef DEBUG
 extern mutex_t	qcheck_lock;
 #endif
@@ -149,7 +153,7 @@
 	} else
 		xqm->qm_dqzone = qm_dqzone;
 
-	xfs_qm_shaker = set_shrinker(DEFAULT_SEEKS, xfs_qm_shake);
+	register_shrinker(&xfs_qm_shaker);
 
 	/*
 	 * The t_dqinfo portion of transactions.
@@ -181,7 +185,7 @@
 
 	ASSERT(xqm != NULL);
 	ASSERT(xqm->qm_nrefs == 0);
-	remove_shrinker(xfs_qm_shaker);
+	unregister_shrinker(&xfs_qm_shaker);
 	hsize = xqm->qm_dqhashmask + 1;
 	for (i = 0; i < hsize; i++) {
 		xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
diff --git a/include/asm-alpha/fb.h b/include/asm-alpha/fb.h
new file mode 100644
index 0000000..fa9bbb9
--- /dev/null
+++ b/include/asm-alpha/fb.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/device.h>
+
+/* Caching is off in the I/O space quadrant by design.  */
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index 21a86f1..ab5b60d 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -4,6 +4,7 @@
 #ifdef __KERNEL__
 
 #include <linux/kernel.h>
+#include <linux/mm.h>
 #include <asm/compiler.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -90,6 +91,11 @@
 
 #define page_to_phys(page)	page_to_pa(page)
 
+static inline dma_addr_t __deprecated isa_page_to_bus(struct page *page)
+{
+	return page_to_phys(page);
+}
+
 /* This depends on working iommu.  */
 #define BIO_VMERGE_BOUNDARY	(alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0)
 
@@ -102,12 +108,12 @@
  *
  * Note that this only works for a limited range of kernel addresses,
  * and very well may not span all memory.  Consider this interface 
- * deprecated in favour of the mapping functions in <asm/pci.h>.
+ * deprecated in favour of the DMA-mapping API.
  */
 extern unsigned long __direct_map_base;
 extern unsigned long __direct_map_size;
 
-static inline unsigned long virt_to_bus(void *address)
+static inline unsigned long __deprecated virt_to_bus(void *address)
 {
 	unsigned long phys = virt_to_phys(address);
 	unsigned long bus = phys + __direct_map_base;
@@ -115,7 +121,7 @@
 }
 #define isa_virt_to_bus virt_to_bus
 
-static inline void *bus_to_virt(unsigned long address)
+static inline void * __deprecated bus_to_virt(unsigned long address)
 {
 	void *virt;
 
@@ -126,6 +132,7 @@
 	virt = phys_to_virt(address);
 	return (long)address <= 0 ? NULL : virt;
 }
+#define isa_bus_to_virt bus_to_virt
 
 /*
  * There are different chipsets to interface the Alpha CPUs to the world.
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index d2bed3c..bae7f05 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -17,7 +17,8 @@
 extern void clear_page(void *page);
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vmaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vmaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 extern void copy_page(void * _to, void * _from);
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 616d206..99037b0 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -264,21 +264,15 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern inline int pte_read(pte_t pte)		{ return !(pte_val(pte) & _PAGE_FOR); }
 extern inline int pte_write(pte_t pte)		{ return !(pte_val(pte) & _PAGE_FOW); }
-extern inline int pte_exec(pte_t pte)		{ return !(pte_val(pte) & _PAGE_FOE); }
 extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 extern inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 
 extern inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_FOW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_FOR; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_FOE; return pte; }
 extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~(__DIRTY_BITS); return pte; }
 extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~(__ACCESS_BITS); return pte; }
 extern inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) &= ~_PAGE_FOW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) &= ~_PAGE_FOR; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte)	{ pte_val(pte) &= ~_PAGE_FOE; return pte; }
 extern inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= __DIRTY_BITS; return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= __ACCESS_BITS; return pte; }
 
diff --git a/include/asm-alpha/termios.h b/include/asm-alpha/termios.h
index 39e492c..fa13716 100644
--- a/include/asm-alpha/termios.h
+++ b/include/asm-alpha/termios.h
@@ -81,7 +81,7 @@
 
 #define user_termio_to_kernel_termios(a_termios, u_termio)			\
 ({										\
-	struct termios *k_termios = (a_termios);				\
+	struct ktermios *k_termios = (a_termios);				\
 	struct termio k_termio;							\
 	int canon, ret;								\
 										\
@@ -113,7 +113,7 @@
  */
 #define kernel_termios_to_user_termio(u_termio, a_termios)		\
 ({									\
-	struct termios *k_termios = (a_termios);			\
+	struct ktermios *k_termios = (a_termios);			\
 	struct termio k_termio;						\
 	int canon;							\
 									\
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
index 0ce6ee9..d96b10f 100644
--- a/include/asm-arm/arch-at91/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -64,6 +64,7 @@
 
  /* Ethernet (EMAC & MACB) */
 struct at91_eth_data {
+	u32		phy_mask;
 	u8		phy_irq_pin;	/* PHY IRQ */
 	u8		is_rmii;	/* using RMII interface? */
 };
diff --git a/include/asm-arm/fb.h b/include/asm-arm/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-arm/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 21dec9f..d2e8171 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -83,14 +83,14 @@
  * means that a write to a clean page will cause a permission fault, and
  * the Linux MM layer will mark the page dirty via handle_pte_fault().
  * For the hardware to notice the permission change, the TLB entry must
- * be flushed, and ptep_establish() does that for us.
+ * be flushed, and ptep_set_access_flags() does that for us.
  *
  * The "accessed" or "young" bit is emulated by a similar method; we only
  * allow accesses to the page if the "young" bit is set.  Accesses to the
  * page will cause a fault, and handle_pte_fault() will set the young bit
  * for us as long as the page is marked present in the corresponding Linux
- * PTE entry.  Again, ptep_establish() will ensure that the TLB is up to
- * date.
+ * PTE entry.  Again, ptep_set_access_flags() will ensure that the TLB is
+ * up to date.
  *
  * However, when the "young" bit is cleared, we deny access to the page
  * by clearing the hardware PTE.  Currently Linux does not flush the TLB
@@ -257,9 +257,7 @@
  * Undefined behaviour if not..
  */
 #define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT)
-#define pte_read(pte)		(pte_val(pte) & L_PTE_USER)
 #define pte_write(pte)		(pte_val(pte) & L_PTE_WRITE)
-#define pte_exec(pte)		(pte_val(pte) & L_PTE_EXEC)
 #define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY)
 #define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG)
 
@@ -275,12 +273,8 @@
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
-/*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/
-/*PTE_BIT_FUNC(mkread,    |= L_PTE_USER);*/
 PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
 PTE_BIT_FUNC(mkwrite,   |= L_PTE_WRITE);
-PTE_BIT_FUNC(exprotect, &= ~L_PTE_EXEC);
-PTE_BIT_FUNC(mkexec,    |= L_PTE_EXEC);
 PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
 PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
 PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
diff --git a/include/asm-arm26/dma-mapping.h b/include/asm-arm26/dma-mapping.h
deleted file mode 100644
index a95eae0..0000000
--- a/include/asm-arm26/dma-mapping.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include <asm-generic/dma-mapping-broken.h>
-
diff --git a/include/asm-arm26/fb.h b/include/asm-arm26/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-arm26/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-arm26/ioctls.h b/include/asm-arm26/ioctls.h
index ba9c7d8..8a32962 100644
--- a/include/asm-arm26/ioctls.h
+++ b/include/asm-arm26/ioctls.h
@@ -47,6 +47,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index 2b20e9f..55a1a69 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -218,9 +218,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-#define pte_read(pte)                   (!(pte_val(pte) & _PAGE_NOT_USER))
 #define pte_write(pte)                  (!(pte_val(pte) & _PAGE_READONLY))
-#define pte_exec(pte)                   (!(pte_val(pte) & _PAGE_NOT_USER))
 #define pte_dirty(pte)                  (!(pte_val(pte) & _PAGE_CLEAN))
 #define pte_young(pte)                  (!(pte_val(pte) & _PAGE_OLD))
 //ONLY when !pte_present() I think. nicked from arm32 (FIXME!)
@@ -231,8 +229,6 @@
 
 PTE_BIT_FUNC(wrprotect, |=  _PAGE_READONLY);
 PTE_BIT_FUNC(mkwrite,   &= ~_PAGE_READONLY);
-PTE_BIT_FUNC(exprotect, |=  _PAGE_NOT_USER);
-PTE_BIT_FUNC(mkexec,    &= ~_PAGE_NOT_USER);
 PTE_BIT_FUNC(mkclean,   |=  _PAGE_CLEAN);
 PTE_BIT_FUNC(mkdirty,   &= ~_PAGE_CLEAN);
 PTE_BIT_FUNC(mkold,     |=  _PAGE_OLD);
diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h
index f66b518..48d2f5c 100644
--- a/include/asm-arm26/termbits.h
+++ b/include/asm-arm26/termbits.h
@@ -138,6 +138,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define   BOTHER  0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -153,10 +154,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR    010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define IBSHIFT	  16		/* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-arm26/termios.h b/include/asm-arm26/termios.h
index 329c324..293e3f1 100644
--- a/include/asm-arm26/termios.h
+++ b/include/asm-arm26/termios.h
@@ -82,8 +82,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index 9fd2e32..9744804 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -21,6 +21,7 @@
 struct platform_device *at32_add_device_usart(unsigned int id);
 
 struct eth_platform_data {
+	u32	phy_mask;
 	u8	is_rmii;
 };
 struct platform_device *
diff --git a/include/asm-avr32/fb.h b/include/asm-avr32/fb.h
new file mode 100644
index 0000000..41baf84
--- /dev/null
+++ b/include/asm-avr32/fb.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
+				      & ~_PAGE_CACHABLE)
+				     | (_PAGE_BUFFER | _PAGE_DIRTY));
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-avr32/pgtable.h b/include/asm-avr32/pgtable.h
index f6cc2b0..c07bdd1 100644
--- a/include/asm-avr32/pgtable.h
+++ b/include/asm-avr32/pgtable.h
@@ -201,18 +201,10 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_USER;
-}
 static inline int pte_write(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_RW;
 }
-static inline int pte_exec(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_EXECUTE;
-}
 static inline int pte_dirty(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_DIRTY;
@@ -231,21 +223,11 @@
 }
 
 /* Mutator functions for PTE bits */
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER));
-	return pte;
-}
 static inline pte_t pte_wrprotect(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW));
 	return pte;
 }
-static inline pte_t pte_exprotect(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE));
-	return pte;
-}
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY));
@@ -256,21 +238,11 @@
 	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED));
 	return pte;
 }
-static inline pte_t pte_mkread(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER));
-	return pte;
-}
 static inline pte_t pte_mkwrite(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW));
 	return pte;
 }
-static inline pte_t pte_mkexec(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE));
-	return pte;
-}
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY));
diff --git a/include/asm-blackfin/fb.h b/include/asm-blackfin/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-blackfin/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-cris/fb.h b/include/asm-cris/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-cris/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-cris/ioctls.h b/include/asm-cris/ioctls.h
index 97787c3..4f4e525 100644
--- a/include/asm-cris/ioctls.h
+++ b/include/asm-cris/ioctls.h
@@ -48,6 +48,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index 9f13c32..0648e31 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -20,7 +20,8 @@
 #define clear_user_page(page, vaddr, pg)    clear_page(page)
 #define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
index c94a710..417f711 100644
--- a/include/asm-cris/pgtable.h
+++ b/include/asm-cris/pgtable.h
@@ -111,9 +111,7 @@
  * Undefined behaviour if not..
  */
 
-static inline int pte_read(pte_t pte)           { return pte_val(pte) & _PAGE_READ; }
 static inline int pte_write(pte_t pte)          { return pte_val(pte) & _PAGE_WRITE; }
-static inline int pte_exec(pte_t pte)           { return pte_val(pte) & _PAGE_READ; }
 static inline int pte_dirty(pte_t pte)          { return pte_val(pte) & _PAGE_MODIFIED; }
 static inline int pte_young(pte_t pte)          { return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)           { return pte_val(pte) & _PAGE_FILE; }
@@ -124,18 +122,6 @@
         return pte;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-        pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	return pte;
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{
-        pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); 
@@ -156,22 +142,6 @@
         return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-        pte_val(pte) |= _PAGE_READ;
-        if (pte_val(pte) & _PAGE_ACCESSED)
-                pte_val(pte) |= _PAGE_SILENT_READ;
-        return pte;
-}
-
-static inline pte_t pte_mkexec(pte_t pte)
-{
-        pte_val(pte) |= _PAGE_READ;
-        if (pte_val(pte) & _PAGE_ACCESSED)
-                pte_val(pte) |= _PAGE_SILENT_READ;
-        return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
         pte_val(pte) |= _PAGE_MODIFIED;
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index 6cc2e27..71c1b36 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -166,6 +166,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define  BOTHER  0010000
 #define  B57600  0010001
 #define  B115200 0010002
 #define  B230400 0010003
diff --git a/include/asm-cris/termios.h b/include/asm-cris/termios.h
index c9dbd4d..b0124e6c 100644
--- a/include/asm-cris/termios.h
+++ b/include/asm-cris/termios.h
@@ -81,8 +81,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-frv/fb.h b/include/asm-frv/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-frv/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 114aefa..147e995 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -377,30 +377,17 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return !((pte).pte & _PAGE_SUPER); }
-static inline int pte_exec(pte_t pte)		{ return !((pte).pte & _PAGE_SUPER); }
 static inline int pte_dirty(pte_t pte)		{ return (pte).pte & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return (pte).pte & _PAGE_ACCESSED; }
 static inline int pte_write(pte_t pte)		{ return !((pte).pte & _PAGE_WP); }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte |= _PAGE_SUPER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte |= _PAGE_SUPER; return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte &= ~_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte |= _PAGE_WP; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte &= ~_PAGE_SUPER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte &= ~_PAGE_SUPER; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte &= ~_PAGE_WP; return pte; }
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	int i = test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
-	asm volatile("dcf %M0" :: "U"(*ptep));
-	return i;
-}
-
 static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
@@ -510,7 +497,6 @@
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index d0ea678..7306c71 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -326,10 +326,14 @@
 #define __NR_move_pages		317
 #define __NR_getcpu		318
 #define __NR_epoll_pwait	319
+#define __NR_utimensat		320
+#define __NR_signalfd		321
+#define __NR_timerfd		322
+#define __NR_eventfd		323
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 320
+#define NR_syscalls 324
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 7f30cce..344e309 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -28,7 +28,7 @@
 #endif
 
 #ifndef HAVE_ARCH_BUG_ON
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
 #endif
 
 #ifndef HAVE_ARCH_WARN_ON
diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h
index 29413d3..e2468f8 100644
--- a/include/asm-generic/dma-mapping-broken.h
+++ b/include/asm-generic/dma-mapping-broken.h
@@ -1,24 +1,82 @@
 #ifndef _ASM_GENERIC_DMA_MAPPING_H
 #define _ASM_GENERIC_DMA_MAPPING_H
 
-/* This is used for archs that do not support DMA */
+/* define the dma api to allow compilation but not linking of
+ * dma dependent code.  Code that depends on the dma-mapping
+ * API needs to set 'depends on HAS_DMA' in its Kconfig
+ */
 
-static inline void *
+struct scatterlist;
+
+extern void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   gfp_t flag)
-{
-	BUG();
-	return NULL;
-}
+		   gfp_t flag);
 
-static inline void
+extern void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-		    dma_addr_t dma_handle)
-{
-	BUG();
-}
+		    dma_addr_t dma_handle);
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+extern dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+	       enum dma_data_direction direction);
+
+extern void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction);
+
+extern int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction);
+
+extern void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction);
+
+extern dma_addr_t
+dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+	     size_t size, enum dma_data_direction direction);
+
+extern void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction);
+
+extern void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+			enum dma_data_direction direction);
+
+extern void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			      unsigned long offset, size_t size,
+			      enum dma_data_direction direction);
+
+extern void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+		    enum dma_data_direction direction);
+
+#define dma_sync_single_for_device dma_sync_single_for_cpu
+#define dma_sync_single_range_for_device dma_sync_single_range_for_cpu
+#define dma_sync_sg_for_device dma_sync_sg_for_cpu
+
+extern int
+dma_mapping_error(dma_addr_t dma_addr);
+
+extern int
+dma_supported(struct device *dev, u64 mask);
+
+extern int
+dma_set_mask(struct device *dev, u64 mask);
+
+extern int
+dma_get_cache_alignment(void);
+
+extern int
+dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+
+extern void
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+	       enum dma_data_direction direction);
+
 #endif /* _ASM_GENERIC_DMA_MAPPING_H */
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index c154b9d..b847741 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -48,6 +48,9 @@
 #ifndef O_NOATIME
 #define O_NOATIME	01000000
 #endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC	02000000	/* set close_on_exec */
+#endif
 #ifndef O_NDELAY
 #define O_NDELAY	O_NONBLOCK
 #endif
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 7d7bcf9..f605e8d 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -3,25 +3,6 @@
 
 #ifndef __ASSEMBLY__
 
-#ifndef __HAVE_ARCH_PTEP_ESTABLISH
-/*
- * Establish a new mapping:
- *  - flush the old one
- *  - update the page tables
- *  - inform the TLB about the new one
- *
- * 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.
- */
-#define ptep_establish(__vma, __address, __ptep, __entry)		\
-do {				  					\
-	set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry);	\
-	flush_tlb_page(__vma, __address);				\
-} while (0)
-#endif
-
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 /*
  * Largely same as above, but only sets the access flags (dirty,
@@ -68,31 +49,6 @@
 })
 #endif
 
-#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __address, __ptep)		\
-({									\
-	pte_t __pte = *__ptep;						\
-	int r = 1;							\
-	if (!pte_dirty(__pte))						\
-		r = 0;							\
-	else								\
-		set_pte_at((__vma)->vm_mm, (__address), (__ptep),	\
-			   pte_mkclean(__pte));				\
-	r;								\
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep)		\
-({									\
-	int __dirty;							\
-	__dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep);	\
-	if (__dirty)							\
-		flush_tlb_page(__vma, __address);			\
-	__dirty;							\
-})
-#endif
-
 #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define ptep_get_and_clear(__mm, __address, __ptep)			\
 ({									\
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index 09ec447..16a466e 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -18,7 +18,8 @@
 #define get_unaligned(ptr) \
 	__get_unaligned((ptr), sizeof(*(ptr)))
 #define put_unaligned(x,ptr) \
-	__put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
+	((void)sizeof(*(ptr)=(x)),\
+	__put_unaligned((__force __u64)(x), (ptr), sizeof(*(ptr))))
 
 /*
  * This function doesn't actually exist.  The idea is that when
@@ -95,21 +96,21 @@
 	default:				\
 		bad_unaligned_access_length();	\
 	};					\
-	(__typeof__(*(ptr)))val;		\
+	(__force __typeof__(*(ptr)))val;	\
 })
 
 #define __put_unaligned(val, ptr, size)		\
-do {						\
+({						\
 	void *__gu_p = ptr;			\
 	switch (size) {				\
 	case 1:					\
-		*(__u8 *)__gu_p = val;		\
+		*(__u8 *)__gu_p = (__force __u8)val;		\
 	        break;				\
 	case 2:					\
-		__ustw(val, __gu_p);		\
+		__ustw((__force __u16)val, __gu_p);		\
 		break;				\
 	case 4:					\
-		__ustl(val, __gu_p);		\
+		__ustl((__force __u32)val, __gu_p);		\
 		break;				\
 	case 8:					\
 		__ustq(val, __gu_p);		\
@@ -117,6 +118,7 @@
 	default:				\
 	    	bad_unaligned_access_length();	\
 	};					\
-} while(0)
+	(void)0;				\
+})
 
 #endif /* _ASM_GENERIC_UNALIGNED_H */
diff --git a/include/asm-h8300/dma-mapping.h b/include/asm-h8300/dma-mapping.h
deleted file mode 100644
index d00e400..0000000
--- a/include/asm-h8300/dma-mapping.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/dma-mapping-broken.h>
diff --git a/include/asm-h8300/fb.h b/include/asm-h8300/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-h8300/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-h8300/ioctls.h b/include/asm-h8300/ioctls.h
index ac20457..98a53d0 100644
--- a/include/asm-h8300/ioctls.h
+++ b/include/asm-h8300/ioctls.h
@@ -47,6 +47,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index 3b4f290..c8cc81a 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -22,7 +22,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h
index e877b40..31eca81 100644
--- a/include/asm-h8300/termbits.h
+++ b/include/asm-h8300/termbits.h
@@ -141,6 +141,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -156,10 +157,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define IBSHIFT	  16			/* shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-h8300/termios.h b/include/asm-h8300/termios.h
index fb2925d..70eea64 100644
--- a/include/asm-h8300/termios.h
+++ b/include/asm-h8300/termios.h
@@ -82,8 +82,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index 45f09dc..aee4009 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -92,6 +92,7 @@
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -99,6 +100,7 @@
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
diff --git a/include/asm-i386/fb.h b/include/asm-i386/fb.h
new file mode 100644
index 0000000..d1c6297
--- /dev/null
+++ b/include/asm-i386/fb.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+extern int fb_is_primary_device(struct fb_info *info);
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (boot_cpu_data.x86 > 3)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 80ea052..249e753 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -54,6 +54,8 @@
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VDSO,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h
index 0fc240c..e7817a3 100644
--- a/include/asm-i386/ide.h
+++ b/include/asm-i386/ide.h
@@ -40,14 +40,13 @@
 
 static __inline__ unsigned long ide_default_io_base(int index)
 {
-	struct pci_dev *pdev;
 	/*
 	 *	If PCI is present then it is not safe to poke around
 	 *	the other legacy IDE ports. Only 0x1f0 and 0x170 are
 	 *	defined compatibility mode ports for PCI. A user can 
 	 *	override this using ide= but we must default safe.
 	 */
-	if ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL)) == NULL) {
+	if (no_pci_devices()) {
 		switch(index) {
 			case 2: return 0x1e8;
 			case 3: return 0x168;
@@ -55,7 +54,6 @@
 			case 5: return 0x160;
 		}
 	}
-	pci_dev_put(pdev);
 	switch (index) {
 		case 0:	return 0x1f0;
 		case 1:	return 0x170;
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index e797586..7b65b5b 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -129,6 +129,7 @@
  */
 extern void *bt_ioremap(unsigned long offset, unsigned long size);
 extern void bt_iounmap(void *addr, unsigned long size);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
 /* Use early IO mappings for DMI because it's initialized early */
 #define dmi_ioremap bt_ioremap
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 818ac8b..99cf5d3 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -34,7 +34,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index a50fd17..84b03cf 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -57,14 +57,6 @@
 #define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
 /*
- * All present user pages are user-executable:
- */
-static inline int pte_exec(pte_t pte)
-{
-	return pte_user(pte);
-}
-
-/*
  * All present pages are kernel-executable:
  */
 static inline int pte_exec_kernel(pte_t pte)
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index eb0f1d7..948a334 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -20,26 +20,11 @@
 #define pud_present(pud)			1
 
 /*
- * Is the pte executable?
- */
-static inline int pte_x(pte_t pte)
-{
-	return !(pte_val(pte) & _PAGE_NX);
-}
-
-/*
- * All present user-pages with !NX bit are user-executable:
- */
-static inline int pte_exec(pte_t pte)
-{
-	return pte_user(pte) && pte_x(pte);
-}
-/*
  * All present pages with !NX bit are kernel-executable:
  */
 static inline int pte_exec_kernel(pte_t pte)
 {
-	return pte_x(pte);
+	return !(pte_val(pte) & _PAGE_NX);
 }
 
 /* Rules for using set_pte: the pte being assigned *must* be
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 628fa77..c7fefa6 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -79,7 +79,7 @@
  * area for the same reason. ;)
  */
 #define VMALLOC_OFFSET	(8*1024*1024)
-#define VMALLOC_START	(((unsigned long) high_memory + vmalloc_earlyreserve + \
+#define VMALLOC_START	(((unsigned long) high_memory + \
 			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
 #ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
@@ -218,8 +218,6 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_user(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
-static inline int pte_read(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
 static inline int pte_dirty(pte_t pte)		{ return (pte).pte_low & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return (pte).pte_low & _PAGE_ACCESSED; }
 static inline int pte_write(pte_t pte)		{ return (pte).pte_low & _PAGE_RW; }
@@ -230,13 +228,9 @@
  */
 static inline int pte_file(pte_t pte)		{ return (pte).pte_low & _PAGE_FILE; }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_RW; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte_low |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
@@ -295,17 +289,6 @@
 	__changed;							\
 })
 
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(vma, addr, ptep) ({			\
-	int __ret = 0;							\
-	if (pte_dirty(*(ptep)))						\
-		__ret = test_and_clear_bit(_PAGE_BIT_DIRTY,		\
-						&(ptep)->pte_low);	\
-	if (__ret)							\
-		pte_update((vma)->vm_mm, addr, ptep);			\
-	__ret;								\
-})
-
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define ptep_test_and_clear_young(vma, addr, ptep) ({			\
 	int __ret = 0;							\
@@ -317,27 +300,6 @@
 	__ret;								\
 })
 
-/*
- * Rules for using ptep_establish: the pte MUST be a user pte, and
- * must be a present->present transition.
- */
-#define __HAVE_ARCH_PTEP_ESTABLISH
-#define ptep_establish(vma, address, ptep, pteval)			\
-do {									\
-	set_pte_present((vma)->vm_mm, address, ptep, pteval);		\
-	flush_tlb_page(vma, address);					\
-} while (0)
-
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(vma, address, ptep)			\
-({									\
-	int __dirty;							\
-	__dirty = ptep_test_and_clear_dirty((vma), (address), (ptep));	\
-	if (__dirty)							\
-		flush_tlb_page(vma, address);				\
-	__dirty;							\
-})
-
 #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
 #define ptep_clear_flush_young(vma, address, ptep)			\
 ({									\
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 94e0c14..422cffe 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -228,6 +228,10 @@
 
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
 
+extern void hard_disable_TSC(void);
+extern void disable_TSC(void);
+extern void hard_enable_TSC(void);
+
 /*
  * Size of io_bitmap.
  */
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 4cb0f91..54424e0 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -137,6 +137,7 @@
 #define TIF_DEBUG		17	/* uses debug registers */
 #define TIF_IO_BITMAP		18	/* uses I/O bitmap */
 #define TIF_FREEZE		19	/* is freezing for suspend */
+#define TIF_NOTSC		20	/* TSC is not accessible in userland */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -151,6 +152,7 @@
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
+#define _TIF_NOTSC		(1<<TIF_NOTSC)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
@@ -160,7 +162,8 @@
 #define _TIF_ALLWORK_MASK	(0x0000FFFF & ~_TIF_SECCOMP)
 
 /* flags to check in __switch_to() */
-#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP)
+#define _TIF_WORK_CTXSW_NEXT (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUG)
+#define _TIF_WORK_CTXSW_PREV (_TIF_IO_BITMAP | _TIF_NOTSC)
 
 /*
  * Thread-synchronous status.
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index 40d01d8..0f6e526 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -31,8 +31,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64 __attribute__((aligned(4))) compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64 __attribute__((aligned(4))) compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-ia64/fb.h b/include/asm-ia64/fb.h
new file mode 100644
index 0000000..89a397c
--- /dev/null
+++ b/include/asm-ia64/fb.h
@@ -0,0 +1,23 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <linux/efi.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	else
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-ia64/ioctls.h b/include/asm-ia64/ioctls.h
index 31ee521..f41b636 100644
--- a/include/asm-ia64/ioctls.h
+++ b/include/asm-ia64/ioctls.h
@@ -53,6 +53,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 485759b..d634546 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -87,12 +87,13 @@
 } while (0)
 
 
-#define alloc_zeroed_user_highpage(vma, vaddr) \
-({						\
-	struct page *page = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr); \
-	if (page)				\
- 		flush_dcache_page(page);	\
-	page;					\
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr)		\
+({									\
+	struct page *page = alloc_page_vma(				\
+		GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr);	\
+	if (page)							\
+ 		flush_dcache_page(page);				\
+	page;								\
 })
 
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 6580f31..de6d01e 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -297,8 +297,6 @@
 /*
  * The following have defined behavior only work if pte_present() is true.
  */
-#define pte_user(pte)		((pte_val(pte) & _PAGE_PL_MASK) == _PAGE_PL_3)
-#define pte_read(pte)		(((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) < 6)
 #define pte_write(pte)	((unsigned) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) - 2) <= 4)
 #define pte_exec(pte)		((pte_val(pte) & _PAGE_AR_RX) != 0)
 #define pte_dirty(pte)		((pte_val(pte) & _PAGE_D) != 0)
@@ -310,7 +308,6 @@
  */
 #define pte_wrprotect(pte)	(__pte(pte_val(pte) & ~_PAGE_AR_RW))
 #define pte_mkwrite(pte)	(__pte(pte_val(pte) | _PAGE_AR_RW))
-#define pte_mkexec(pte)		(__pte(pte_val(pte) | _PAGE_AR_RX))
 #define pte_mkold(pte)		(__pte(pte_val(pte) & ~_PAGE_A))
 #define pte_mkyoung(pte)	(__pte(pte_val(pte) | _PAGE_A))
 #define pte_mkclean(pte)	(__pte(pte_val(pte) & ~_PAGE_D))
@@ -398,22 +395,6 @@
 #endif
 }
 
-static inline int
-ptep_test_and_clear_dirty (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
-	if (!pte_dirty(*ptep))
-		return 0;
-	return test_and_clear_bit(_PAGE_D_BIT, ptep);
-#else
-	pte_t pte = *ptep;
-	if (!pte_dirty(pte))
-		return 0;
-	set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
-	return 1;
-#endif
-}
-
 static inline pte_t
 ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -546,8 +527,10 @@
 # define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
 ({									\
 	int __changed = !pte_same(*(__ptep), __entry);			\
-	if (__changed)							\
-		ptep_establish(__vma, __addr, __ptep, __entry);		\
+	if (__changed) {						\
+		set_pte_at((__vma)->vm_mm, (__addr), __ptep, __entry);	\
+		flush_tlb_page(__vma, __addr);				\
+	}								\
 	__changed;							\
 })
 #endif
@@ -591,7 +574,6 @@
 #endif
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h
index 7fae310..9f162e0 100644
--- a/include/asm-ia64/termbits.h
+++ b/include/asm-ia64/termbits.h
@@ -149,6 +149,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -164,10 +165,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define IBSHIFT	16		/* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-ia64/termios.h b/include/asm-ia64/termios.h
index 08750c2..689d218 100644
--- a/include/asm-ia64/termios.h
+++ b/include/asm-ia64/termios.h
@@ -87,8 +87,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC);	\
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 # endif /* __KERNEL__ */
 
diff --git a/include/asm-m32r/dma-mapping.h b/include/asm-m32r/dma-mapping.h
deleted file mode 100644
index f9b58eb..0000000
--- a/include/asm-m32r/dma-mapping.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_M32R_DMA_MAPPING_H
-#define _ASM_M32R_DMA_MAPPING_H
-
-#include <asm-generic/dma-mapping-broken.h>
-
-#endif /* _ASM_M32R_DMA_MAPPING_H */
diff --git a/include/asm-m32r/fb.h b/include/asm-m32r/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-m32r/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m32r/ioctls.h b/include/asm-m32r/ioctls.h
index d23cfc4..b9f54bb 100644
--- a/include/asm-m32r/ioctls.h
+++ b/include/asm-m32r/ioctls.h
@@ -47,6 +47,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 6f6ecf7..04fd183 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -15,7 +15,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 6604303..92d7266 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -191,16 +191,6 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_READ;
-}
-
-static inline int pte_exec(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_EXEC;
-}
-
 static inline int pte_dirty(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_DIRTY;
@@ -224,18 +214,6 @@
 	return pte_val(pte) & _PAGE_FILE;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	pte_val(pte) &= ~_PAGE_READ;
-	return pte;
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{
-	pte_val(pte) &= ~_PAGE_EXEC;
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_val(pte) &= ~_PAGE_DIRTY;
@@ -254,18 +232,6 @@
 	return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_READ;
-	return pte;
-}
-
-static inline pte_t pte_mkexec(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_EXEC;
-	return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_DIRTY;
@@ -284,11 +250,6 @@
 	return pte;
 }
 
-static inline  int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
-}
-
 static inline  int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
@@ -382,7 +343,6 @@
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
index 6be3b8a..bc10400 100644
--- a/include/asm-m32r/termbits.h
+++ b/include/asm-m32r/termbits.h
@@ -140,6 +140,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -155,11 +156,13 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/** input baud rate */
 #define CTVB	  004000000000		/* VisioBraille Terminal flow control */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define	IBSHIFT	16			/* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-m32r/termios.h b/include/asm-m32r/termios.h
index 4943dd8..93ce79f 100644
--- a/include/asm-m32r/termios.h
+++ b/include/asm-m32r/termios.h
@@ -81,8 +81,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-m68k/atari_SLM.h b/include/asm-m68k/atari_SLM.h
deleted file mode 100644
index 42f4fcd..0000000
--- a/include/asm-m68k/atari_SLM.h
+++ /dev/null
@@ -1,28 +0,0 @@
-
-#ifndef _ATARI_SLM_H
-#define _ATARI_SLM_H
-
-/* Atari SLM laser printer specific ioctls */
-
-#define	SLMIOGSTAT	0xa100
-#define	SLMIOGPSIZE	0xa101
-#define	SLMIOGMFEED	0xa102
-
-#define	SLMIORESET	0xa140
-
-#define	SLMIOSPSIZE	0xa181
-#define	SLMIOSMFEED	0xa182
-
-/* Status returning structure (SLMIOGSTAT) */
-struct SLM_status {
-	int		stat;		/* numeric status code */
-	char	str[40];	/* status string */
-};
-
-/* Paper size structure (SLMIO[GS]PSIZE) */
-struct SLM_paper_size {
-	int		width;
-	int		height;
-};
-
-#endif /* _ATARI_SLM_H */
diff --git a/include/asm-m68k/atari_acsi.h b/include/asm-m68k/atari_acsi.h
deleted file mode 100644
index 10fea68..0000000
--- a/include/asm-m68k/atari_acsi.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _ASM_ATARI_ACSI_H
-#define _ASM_ATARI_ACSI_H
-
-/* Functions exported by drivers/block/acsi.c */
-
-void acsi_delay_start( void );
-void acsi_delay_end( long usec );
-int acsi_wait_for_IRQ( unsigned timeout );
-int acsi_wait_for_noIRQ( unsigned timeout );
-int acsicmd_nodma( const char *cmd, int enable);
-int acsi_getstatus( void );
-int acsi_extstatus( char *buffer, int cnt );
-void acsi_end_extstatus( void );
-int acsi_extcmd( unsigned char *buffer, int cnt );
-
-/* The ACSI buffer is guarantueed to reside in ST-RAM and may be used by other
- * drivers that work on the ACSI bus, too. It's data are valid only as long as
- * the ST-DMA is locked. */
-extern char *acsi_buffer;
-extern unsigned long phys_acsi_buffer;
-
-/* Utility macros */
-
-/* Send one data byte over the bus and set mode for next operation
- * with one move.l -- Atari recommends this...
- */
-
-#define DMA_LONG_WRITE(data,mode)							\
-    do {													\
-		*((unsigned long *)&dma_wd.fdc_acces_seccount) =	\
-			((data)<<16) | (mode);							\
-	} while(0)
-
-#define ENABLE_IRQ()	atari_turnon_irq( IRQ_MFP_ACSI )
-#define DISABLE_IRQ()	atari_turnoff_irq( IRQ_MFP_ACSI )
-
-#endif /* _ASM_ATARI_ACSI_H */
diff --git a/include/asm-m68k/fb.h b/include/asm-m68k/fb.h
new file mode 100644
index 0000000..380b97a
--- /dev/null
+++ b/include/asm-m68k/fb.h
@@ -0,0 +1,34 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+#ifdef CONFIG_SUN3
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
+}
+#else
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (CPU_IS_020_OR_030)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
+	if (CPU_IS_040_OR_060) {
+		pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
+		/* Use no-cache mode, serialized */
+		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
+	}
+}
+#endif /* CONFIG_SUN3 */
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
index b5b78c0..d029b75 100644
--- a/include/asm-m68k/motorola_pgtable.h
+++ b/include/asm-m68k/motorola_pgtable.h
@@ -164,21 +164,15 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return 1; }
 static inline int pte_write(pte_t pte)		{ return !(pte_val(pte) & _PAGE_RONLY); }
-static inline int pte_exec(pte_t pte)		{ return 1; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 
 static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_RONLY; return pte; }
-static inline pte_t pte_rdprotect(pte_t pte)	{ return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) &= ~_PAGE_RONLY; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mknocache(pte_t pte)
diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
index b9e62c1..b766fc2 100644
--- a/include/asm-m68k/sun3_pgtable.h
+++ b/include/asm-m68k/sun3_pgtable.h
@@ -165,21 +165,15 @@
  * Undefined behaviour if not...
  * [we have the full set here even if they don't change from m68k]
  */
-static inline int pte_read(pte_t pte)		{ return 1; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_WRITEABLE; }
-static inline int pte_exec(pte_t pte)		{ return 1; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_MODIFIED; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_ACCESSED; }
 
 static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_WRITEABLE; return pte; }
-static inline pte_t pte_rdprotect(pte_t pte)	{ return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_MODIFIED; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_WRITEABLE; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_MODIFIED; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mknocache(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_NOCACHE; return pte; }
diff --git a/include/asm-m68knommu/fb.h b/include/asm-m68knommu/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-m68knommu/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index 2a1b8bd..9efa0a9 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -22,7 +22,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 67c3f8e..568c76c 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -37,8 +37,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-mips/fb.h b/include/asm-mips/fb.h
new file mode 100644
index 0000000..bd3f68c
--- /dev/null
+++ b/include/asm-mips/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 27d77d9..2e2d70d 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -178,9 +178,7 @@
  * The following only work if pte_present() is true.
  * 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_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; }
 static inline int pte_young(pte_t pte)	{ return pte.pte_low & _PAGE_ACCESSED; }
@@ -193,13 +191,6 @@
 	return pte;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	pte.pte_low  &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	pte.pte_high &= ~_PAGE_SILENT_READ;
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte.pte_low  &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
@@ -224,16 +215,6 @@
 	return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-	pte.pte_low |= _PAGE_READ;
-	if (pte.pte_low & _PAGE_ACCESSED) {
-		pte.pte_low  |= _PAGE_SILENT_READ;
-		pte.pte_high |= _PAGE_SILENT_READ;
-	}
-	return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte.pte_low |= _PAGE_MODIFIED;
@@ -253,7 +234,6 @@
 	return pte;
 }
 #else
-static inline int pte_read(pte_t pte)	{ return pte_val(pte) & _PAGE_READ; }
 static inline int pte_write(pte_t pte)	{ return pte_val(pte) & _PAGE_WRITE; }
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_MODIFIED; }
 static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
@@ -265,12 +245,6 @@
 	return pte;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
@@ -291,14 +265,6 @@
 	return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_READ;
-	if (pte_val(pte) & _PAGE_ACCESSED)
-		pte_val(pte) |= _PAGE_SILENT_READ;
-	return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_MODIFIED;
diff --git a/include/asm-mips/sibyte/bcm1480_regs.h b/include/asm-mips/sibyte/bcm1480_regs.h
index bda391d..2738c13 100644
--- a/include/asm-mips/sibyte/bcm1480_regs.h
+++ b/include/asm-mips/sibyte/bcm1480_regs.h
@@ -220,17 +220,25 @@
 #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 A_BCM1480_DUART_CHANREG(chan, reg)				\
+	(A_BCM1480_DUART(chan) +					\
+	 BCM1480_DUART_CHANREG_SPACING * (((chan) & 1) + 1) + (reg))
+#define A_BCM1480_DUART_CTRLREG(chan, reg)				\
+	(A_BCM1480_DUART(chan) +					\
+	 BCM1480_DUART_CHANREG_SPACING * 3 + (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 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))
-#define A_BCM1480_DUART_IN_PORT(chan)       (A_BCM1480_DUART(chan) + R_DUART_INP_ORT)
+#define A_BCM1480_DUART_IMRREG(chan)					\
+	(A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_IMRREG(chan)))
+#define A_BCM1480_DUART_ISRREG(chan)					\
+	(A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_ISRREG(chan)))
+
+#define A_BCM1480_DUART_IN_PORT(chan)					\
+	(A_BCM1480_DUART_CTRLREG((chan), R_DUART_IN_PORT))
 
 /*
  * These constants are the absolute addresses.
diff --git a/include/asm-mips/sibyte/sb1250_regs.h b/include/asm-mips/sibyte/sb1250_regs.h
index da7c188..220b7e9 100644
--- a/include/asm-mips/sibyte/sb1250_regs.h
+++ b/include/asm-mips/sibyte/sb1250_regs.h
@@ -272,59 +272,69 @@
     ********************************************************************* */
 
 
-#if SIBYTE_HDR_FEATURE_1250_112x		/* This MC only on 1250 & 112x */
+#if SIBYTE_HDR_FEATURE_1250_112x    /* This MC only on 1250 & 112x */
 #define R_DUART_NUM_PORTS           2
 
 #define A_DUART                     0x0010060000
 
 #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))
+
+#define A_DUART_CHANREG(chan, reg)					\
+	(A_DUART + DUART_CHANREG_SPACING * ((chan) + 1) + (reg))
 #endif	/* 1250 & 112x */
 
-#define R_DUART_MODE_REG_1	    0x100
-#define R_DUART_MODE_REG_2	    0x110
-#define R_DUART_STATUS              0x120
-#define R_DUART_CLK_SEL             0x130
-#define R_DUART_CMD                 0x150
-#define R_DUART_RX_HOLD             0x160
-#define R_DUART_TX_HOLD             0x170
+#define R_DUART_MODE_REG_1	    0x000
+#define R_DUART_MODE_REG_2	    0x010
+#define R_DUART_STATUS		    0x020
+#define R_DUART_CLK_SEL		    0x030
+#define R_DUART_CMD		    0x050
+#define R_DUART_RX_HOLD		    0x060
+#define R_DUART_TX_HOLD		    0x070
 
 #if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
-#define R_DUART_FULL_CTL	    0x140
-#define R_DUART_OPCR_X		    0x180
-#define R_DUART_AUXCTL_X	    0x190
-#endif /* 1250 PASS2 || 112x PASS1 || 1480*/
+#define R_DUART_FULL_CTL	    0x040
+#define R_DUART_OPCR_X		    0x080
+#define R_DUART_AUXCTL_X	    0x090
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 
 /*
  * The IMR and ISR can't be addressed with A_DUART_CHANREG,
- * so use this macro instead.
+ * so use these macros instead.
  */
 
-#define R_DUART_AUX_CTRL            0x310
-#define R_DUART_ISR_A               0x320
-#define R_DUART_IMR_A               0x330
-#define R_DUART_ISR_B               0x340
-#define R_DUART_IMR_B               0x350
-#define R_DUART_OUT_PORT            0x360
-#define R_DUART_OPCR                0x370
-#define R_DUART_IN_PORT             0x380
+#if SIBYTE_HDR_FEATURE_1250_112x    /* This MC only on 1250 & 112x */
+#define DUART_IMRISR_SPACING	    0x20
+#define DUART_INCHNG_SPACING	    0x10
 
-#define R_DUART_SET_OPR		    0x3B0
-#define R_DUART_CLEAR_OPR	    0x3C0
+#define A_DUART_CTRLREG(reg)						\
+	(A_DUART + DUART_CHANREG_SPACING * 3 + (reg))
 
-#define DUART_IMRISR_SPACING        0x20
+#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 R_DUART_INCHREG(chan)						\
+	(R_DUART_IN_CHNG_A + (chan) * DUART_INCHNG_SPACING)
 
-#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))
+#define A_DUART_IMRREG(chan)	    A_DUART_CTRLREG(R_DUART_IMRREG(chan))
+#define A_DUART_ISRREG(chan)	    A_DUART_CTRLREG(R_DUART_ISRREG(chan))
+#define A_DUART_INCHREG(chan)	    A_DUART_CTRLREG(R_DUART_INCHREG(chan))
 #endif	/* 1250 & 112x */
 
+#define R_DUART_AUX_CTRL	    0x010
+#define R_DUART_ISR_A		    0x020
+#define R_DUART_IMR_A		    0x030
+#define R_DUART_ISR_B		    0x040
+#define R_DUART_IMR_B		    0x050
+#define R_DUART_OUT_PORT	    0x060
+#define R_DUART_OPCR		    0x070
+#define R_DUART_IN_PORT		    0x080
 
+#define R_DUART_SET_OPR		    0x0B0
+#define R_DUART_CLEAR_OPR	    0x0C0
+#define R_DUART_IN_CHNG_A	    0x0D0
+#define R_DUART_IN_CHNG_B	    0x0E0
 
 
 /*
diff --git a/include/asm-mips/sibyte/sb1250_uart.h b/include/asm-mips/sibyte/sb1250_uart.h
index e87045e..cf74fed 100644
--- a/include/asm-mips/sibyte/sb1250_uart.h
+++ b/include/asm-mips/sibyte/sb1250_uart.h
@@ -75,7 +75,8 @@
 #define V_DUART_PARITY_MODE_ADD_FIXED V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_ADD_FIXED)
 #define V_DUART_PARITY_MODE_NONE      V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_NONE)
 
-#define M_DUART_ERR_MODE            _SB_MAKEMASK1(5)    /* must be zero */
+#define M_DUART_TX_IRQ_SEL_TXRDY    0
+#define M_DUART_TX_IRQ_SEL_TXEMPT   _SB_MAKEMASK1(5)
 
 #define M_DUART_RX_IRQ_SEL_RXRDY    0
 #define M_DUART_RX_IRQ_SEL_RXFULL   _SB_MAKEMASK1(6)
@@ -246,10 +247,13 @@
 
 #define M_DUART_ISR_BRK_A           _SB_MAKEMASK1(2)
 #define M_DUART_ISR_IN_A            _SB_MAKEMASK1(3)
+#define M_DUART_ISR_ALL_A	    _SB_MAKEMASK(4,0)
+
 #define M_DUART_ISR_TX_B            _SB_MAKEMASK1(4)
 #define M_DUART_ISR_RX_B            _SB_MAKEMASK1(5)
 #define M_DUART_ISR_BRK_B           _SB_MAKEMASK1(6)
 #define M_DUART_ISR_IN_B            _SB_MAKEMASK1(7)
+#define M_DUART_ISR_ALL_B	    _SB_MAKEMASK(4,4)
 
 /*
  * DUART Channel A Interrupt Status Register (Table 10-17)
@@ -262,6 +266,7 @@
 #define M_DUART_ISR_RX              _SB_MAKEMASK1(1)
 #define M_DUART_ISR_BRK             _SB_MAKEMASK1(2)
 #define M_DUART_ISR_IN              _SB_MAKEMASK1(3)
+#define M_DUART_ISR_ALL		    _SB_MAKEMASK(4,0)
 #define M_DUART_ISR_RESERVED        _SB_MAKEMASK(4,4)
 
 /*
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 11f4222..5a85d1b 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -31,8 +31,10 @@
 
 typedef s32	compat_int_t;
 typedef s32	compat_long_t;
+typedef s64	compat_s64;
 typedef u32	compat_uint_t;
 typedef u32	compat_ulong_t;
+typedef u64	compat_u64;
 
 struct compat_timespec {
 	compat_time_t		tv_sec;
diff --git a/include/asm-parisc/fb.h b/include/asm-parisc/fb.h
new file mode 100644
index 0000000..4d503a0
--- /dev/null
+++ b/include/asm-parisc/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-parisc/fcntl.h b/include/asm-parisc/fcntl.h
index 317851f..1e1c824 100644
--- a/include/asm-parisc/fcntl.h
+++ b/include/asm-parisc/fcntl.h
@@ -3,21 +3,22 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_APPEND	00000010
-#define O_BLKSEEK	00000100 /* HPUX only */
-#define O_CREAT		00000400 /* not fcntl */
-#define O_EXCL		00002000 /* not fcntl */
-#define O_LARGEFILE	00004000
-#define O_SYNC		00100000
-#define O_NONBLOCK	00200004 /* HPUX has separate NDELAY & NONBLOCK */
-#define O_NOCTTY	00400000 /* not fcntl */
-#define O_DSYNC		01000000 /* HPUX only */
-#define O_RSYNC		02000000 /* HPUX only */
-#define O_NOATIME	04000000
+#define O_APPEND	000000010
+#define O_BLKSEEK	000000100 /* HPUX only */
+#define O_CREAT		000000400 /* not fcntl */
+#define O_EXCL		000002000 /* not fcntl */
+#define O_LARGEFILE	000004000
+#define O_SYNC		000100000
+#define O_NONBLOCK	000200004 /* HPUX has separate NDELAY & NONBLOCK */
+#define O_NOCTTY	000400000 /* not fcntl */
+#define O_DSYNC		001000000 /* HPUX only */
+#define O_RSYNC		002000000 /* HPUX only */
+#define O_NOATIME	004000000
+#define O_CLOEXEC	010000000 /* set close_on_exec */
 
-#define O_DIRECTORY	00010000 /* must be a directory */
-#define O_NOFOLLOW	00000200 /* don't follow links */
-#define O_INVISIBLE	04000000 /* invisible I/O, for DMAPI/XDSM */
+#define O_DIRECTORY	000010000 /* must be a directory */
+#define O_NOFOLLOW	000000200 /* don't follow links */
+#define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */
 
 #define F_GETLK64	8
 #define F_SETLK64	9
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index beb2adb..e88cacd 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -335,18 +335,14 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_READ; }
 extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 extern inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_WRITE; }
 extern inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
-extern inline int pte_user(pte_t pte) 		{ return pte_val(pte) & _PAGE_USER; }
 
-extern inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_READ; return pte; }
 extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
 extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 extern inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_WRITE; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_READ; return pte; }
 extern inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 extern inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_WRITE; return pte; }
@@ -451,21 +447,6 @@
 #endif
 }
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
-	if (!pte_dirty(*ptep))
-		return 0;
-	return test_and_clear_bit(xlate_pabit(_PAGE_DIRTY_BIT), &pte_val(*ptep));
-#else
-	pte_t pte = *ptep;
-	if (!pte_dirty(pte))
-		return 0;
-	set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
-	return 1;
-#endif
-}
-
 extern spinlock_t pa_dbit_lock;
 
 struct mm_struct;
@@ -533,7 +514,6 @@
 #define HAVE_ARCH_UNMAPPED_AREA
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h
index 642be62..5350704 100644
--- a/include/asm-powerpc/cache.h
+++ b/include/asm-powerpc/cache.h
@@ -34,5 +34,9 @@
 extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
+#if !defined(__ASSEMBLY__)
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
diff --git a/include/asm-powerpc/compat.h b/include/asm-powerpc/compat.h
index aacaabd..64ab1dd 100644
--- a/include/asm-powerpc/compat.h
+++ b/include/asm-powerpc/compat.h
@@ -33,8 +33,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 82d595a..3dc8e2d 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -111,7 +111,7 @@
 /* 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_COHERENT_ICACHE		ASM_CONST(0x0000000000000001)
 #define CPU_FTR_L2CR			ASM_CONST(0x0000000000000002)
 #define CPU_FTR_SPEC7450		ASM_CONST(0x0000000000000004)
 #define CPU_FTR_ALTIVEC			ASM_CONST(0x0000000000000008)
@@ -135,6 +135,7 @@
 #define CPU_FTR_PPC_LE			ASM_CONST(0x0000000000200000)
 #define CPU_FTR_REAL_LE			ASM_CONST(0x0000000000400000)
 #define CPU_FTR_FPU_UNAVAILABLE		ASM_CONST(0x0000000000800000)
+#define CPU_FTR_UNIFIED_ID_CACHE	ASM_CONST(0x0000000001000000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -154,7 +155,6 @@
 #define CPU_FTR_MMCRA			LONG_ASM_CONST(0x0000004000000000)
 #define CPU_FTR_CTRL			LONG_ASM_CONST(0x0000008000000000)
 #define CPU_FTR_SMT			LONG_ASM_CONST(0x0000010000000000)
-#define CPU_FTR_COHERENT_ICACHE		LONG_ASM_CONST(0x0000020000000000)
 #define CPU_FTR_LOCKLESS_TLBIE		LONG_ASM_CONST(0x0000040000000000)
 #define CPU_FTR_CI_LARGE_PAGE		LONG_ASM_CONST(0x0000100000000000)
 #define CPU_FTR_PAUSE_ZERO		LONG_ASM_CONST(0x0000200000000000)
@@ -206,164 +206,149 @@
 		     !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
 		     !defined(CONFIG_BOOKE))
 
-#define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_603	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \
+	CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_603	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_604	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_604	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
 	    CPU_FTR_PPC_LE)
-#define CPU_FTRS_740_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740_NOTAU	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_740	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740	(CPU_FTR_COMMON | \
 	    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_PPC_LE)
-#define CPU_FTRS_750	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750	(CPU_FTR_COMMON | \
 	    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_PPC_LE)
-#define CPU_FTRS_750CL	(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_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define 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_FTR_PPC_LE)
-#define 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_FTR_PPC_LE)
-#define 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_FTR_PPC_LE)
-#define CPU_FTRS_750GX	(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_FTR_PPC_LE)
-#define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750CL	(CPU_FTRS_750 | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750FX1	(CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX2	(CPU_FTRS_750 | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX	(CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \
+		CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750GX	(CPU_FTRS_750FX)
+#define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7400	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7400	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7450_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_20	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7450_21	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_21	(CPU_FTR_COMMON | \
 	    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_PPC_LE)
-#define CPU_FTRS_7450_23	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_23	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7455_1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_1	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7455_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_20	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7455	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455	(CPU_FTR_COMMON | \
 	    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_PPC_LE)
-#define CPU_FTRS_7447_10	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447_10	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7447	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447	(CPU_FTR_COMMON | \
 	    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_PPC_LE)
-#define CPU_FTRS_7447A	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447A	(CPU_FTR_COMMON | \
 	    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_FTR_PPC_LE)
-#define CPU_FTRS_7448	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7448	(CPU_FTR_COMMON | \
 	    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_PPC_LE)
-#define CPU_FTRS_82XX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_82XX	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
-#define CPU_FTRS_G2_LE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_G2_LE	(CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
-#define CPU_FTRS_E300	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300	(CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_COMMON)
-#define CPU_FTRS_E300C2	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300C2	(CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
-#define CPU_FTRS_CLASSIC32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_CLASSIC32	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_8XX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
-#define CPU_FTRS_40X	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_44X	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E200	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500_2	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_8XX	(CPU_FTR_USE_TB)
+#define CPU_FTRS_40X	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_44X	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E200	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_E500	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500_2	(CPU_FTR_USE_TB | \
 	    CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
-#define CPU_FTRS_POWER3	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
 	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
-#define CPU_FTRS_POWER4	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA)
-#define CPU_FTRS_PPC970	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
-#define CPU_FTRS_POWER5	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR)
-#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR)
-#define CPU_FTRS_CELL	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
-#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
 	    CPU_FTR_PURR | CPU_FTR_REAL_LE)
-#define CPU_FTRS_COMPATIBLE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_COMPATIBLE	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
 
 #ifdef __powerpc64__
diff --git a/include/asm-powerpc/fb.h b/include/asm-powerpc/fb.h
new file mode 100644
index 0000000..411af8d
--- /dev/null
+++ b/include/asm-powerpc/fb.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
+						 vma->vm_end - vma->vm_start,
+						 vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index afa700d..34146f0 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -29,7 +29,7 @@
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
 
 #include <linux/pci.h>
-#include <asm/ppc-pci.h>	/* for ppc64_isabridge_dev */
+#include <asm/ppc-pci.h>	/* for isa_bridge_pcidev */
 
 #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
 
@@ -139,12 +139,12 @@
 	if (bus_addr 
 	    && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
 		/* different from last time -- unmap prev */
-		pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
+		pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir);
 		bus_addr = 0;
 	}
 
 	if (!bus_addr)	/* need to map it */
-		bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
+		bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir);
 
 	/* remember this one as prev */
 	prev_addr = addr;
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 62efd9d..bf6cd7c 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -206,6 +206,7 @@
 #define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
 #define H_QUERY_INT_STATE       0x1E4
 #define H_POLL_PENDING		0x1D8
+#define H_ILLAN_ATTRIBUTES	0x244
 #define H_JOIN			0x298
 #define H_VASI_STATE            0x2A4
 #define H_ENABLE_CRQ		0x2B0
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 350c9bd..bb8d965 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -607,9 +607,9 @@
  *
  * * iounmap undoes such a mapping and can be hooked
  *
- * * __ioremap_explicit (and the pending __iounmap_explicit) are low level
- *   functions to create hand-made mappings for use only by the PCI code
- *   and cannot currently be hooked.
+ * * __ioremap_at (and the pending __iounmap_at) are low level functions to
+ *   create hand-made mappings for use only by the PCI code and cannot
+ *   currently be hooked. Must be page aligned.
  *
  * * __ioremap is the low level implementation used by ioremap and
  *   ioremap_flags and cannot be hooked (but can be used by a hook on one
@@ -629,19 +629,9 @@
 			       unsigned long flags);
 extern void __iounmap(volatile void __iomem *addr);
 
-extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr,
-		     	      unsigned long size, unsigned long flags);
-extern int __iounmap_explicit(volatile void __iomem *start,
-			      unsigned long size);
-
-extern void __iomem * reserve_phb_iospace(unsigned long size);
-
-/* Those are more 32 bits only functions */
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
-			     unsigned int size, int flags);
-
+extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
+				   unsigned long size, unsigned long flags);
+extern void __iounmap_at(void *ea, unsigned long size);
 
 /*
  * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation
@@ -651,8 +641,8 @@
  */
 #define HAVE_ARCH_PIO_SIZE		1
 #define PIO_OFFSET			0x00000000UL
-#define PIO_MASK			0x3fffffffUL
-#define PIO_RESERVED			0x40000000UL
+#define PIO_MASK			(FULL_IO_SIZE - 1)
+#define PIO_RESERVED			(FULL_IO_SIZE)
 
 #define mmio_read16be(addr)		readw_be(addr)
 #define mmio_read32be(addr)		readl_be(addr)
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 05dd5a3..0485c53 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -223,6 +223,15 @@
 extern unsigned int irq_find_mapping(struct irq_host *host,
 				     irq_hw_number_t hwirq);
 
+/**
+ * irq_create_direct_mapping - Allocate a virq for direct mapping
+ * @host: host to allocate the virq for or NULL for default host
+ *
+ * This routine is used for irq controllers which can choose the hardware
+ * interrupt numbers they generate. In such a case it's simplest to use
+ * the linux virq as the hardware interrupt number.
+ */
+extern unsigned int irq_create_direct_mapping(struct irq_host *host);
 
 /**
  * irq_radix_revmap - Find a linux virq from a hw irq number.
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index b0e40ff..9537fda 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -65,10 +65,10 @@
 		} else if (name[0] != '.')				\
 			addr = *(kprobe_opcode_t **)addr;		\
 	} else {							\
-		char dot_name[KSYM_NAME_LEN+1];				\
+		char dot_name[KSYM_NAME_LEN];				\
 		dot_name[0] = '.';					\
 		dot_name[1] = '\0';					\
-		strncat(dot_name, name, KSYM_NAME_LEN);			\
+		strncat(dot_name, name, KSYM_NAME_LEN - 2);		\
 		addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
 	}								\
 }
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h
index 821ea0c..567ed92 100644
--- a/include/asm-powerpc/lppaca.h
+++ b/include/asm-powerpc/lppaca.h
@@ -98,7 +98,7 @@
 	u64	saved_gpr5;		// Saved GPR5                   x30-x37
 
 	u8	reserved4;		// Reserved			x38-x38
-	u8	cpuctls_task_attrs;	// Task attributes for cpuctls  x39-x39
+	u8	donate_dedicated_cpu;	// Donate dedicated CPU cycles  x39-x39
 	u8	fpregs_in_use;		// FP regs in use               x3A-x3A
 	u8	pmcregs_in_use;		// PMC regs in use              x3B-x3B
 	volatile u32 saved_decr;	// Saved Decr Value             x3C-x3F
diff --git a/include/asm-powerpc/lv1call.h b/include/asm-powerpc/lv1call.h
index f733bee..81713ac 100644
--- a/include/asm-powerpc/lv1call.h
+++ b/include/asm-powerpc/lv1call.h
@@ -238,6 +238,7 @@
 LV1_CALL(configure_irq_state_bitmap,                    3, 0,  11 )
 LV1_CALL(connect_irq_plug_ext,                          5, 0,  12 )
 LV1_CALL(release_memory,                                1, 0,  13 )
+LV1_CALL(put_iopte,                                     5, 0,  15 )
 LV1_CALL(disconnect_irq_plug_ext,                       3, 0,  17 )
 LV1_CALL(construct_event_receive_port,                  0, 1,  18 )
 LV1_CALL(destruct_event_receive_port,                   1, 0,  19 )
@@ -268,6 +269,8 @@
 LV1_CALL(read_htab_entries,                             2, 5,  95 )
 LV1_CALL(set_dabr,                                      2, 0,  96 )
 LV1_CALL(get_total_execution_time,                      2, 1, 103 )
+LV1_CALL(allocate_io_segment,                           3, 1, 116 )
+LV1_CALL(release_io_segment,                            2, 0, 117 )
 LV1_CALL(construct_io_irq_outlet,                       1, 1, 120 )
 LV1_CALL(destruct_io_irq_outlet,                        1, 0, 121 )
 LV1_CALL(map_htab,                                      1, 1, 122 )
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 6cf1a83..71c6e7e 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -218,7 +218,7 @@
 	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
 
 	/* Called in indirect_* to avoid touching devices */
-	int (*pci_exclude_device)(unsigned char, unsigned char);
+	int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
 
 	/* Called at then very end of pcibios_init() */
 	void (*pcibios_after_init)(void);
diff --git a/include/asm-powerpc/mmu-8xx.h b/include/asm-powerpc/mmu-8xx.h
new file mode 100644
index 0000000..952bd88
--- /dev/null
+++ b/include/asm-powerpc/mmu-8xx.h
@@ -0,0 +1,147 @@
+#ifndef _ASM_POWERPC_MMU_8XX_H_
+#define _ASM_POWERPC_MMU_8XX_H_
+/*
+ * PPC8xx support
+ */
+
+/* Control/status registers for the MPC8xx.
+ * A write operation to these registers causes serialized access.
+ * During software tablewalk, the registers used perform mask/shift-add
+ * operations when written/read.  A TLB entry is created when the Mx_RPN
+ * is written, and the contents of several registers are used to
+ * create the entry.
+ */
+#define SPRN_MI_CTR	784	/* Instruction TLB control register */
+#define MI_GPM		0x80000000	/* Set domain manager mode */
+#define MI_PPM		0x40000000	/* Set subpage protection */
+#define MI_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
+#define MI_RSV4I	0x08000000	/* Reserve 4 TLB entries */
+#define MI_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
+#define MI_IDXMASK	0x00001f00	/* TLB index to be loaded */
+#define MI_RESETVAL	0x00000000	/* Value of register at reset */
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MI_AP	786
+#define MI_Ks		0x80000000	/* Should not be set */
+#define MI_Kp		0x40000000	/* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MI_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MI_EPN	787
+#define MI_EPNMASK	0xfffff000	/* Effective page number for entry */
+#define MI_EVALID	0x00000200	/* Entry is valid */
+#define MI_ASIDMASK	0x0000000f	/* ASID match value */
+					/* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the instruction TLB, it contains bits that get loaded into the
+ * TLB entry when the MI_RPN is written.
+ */
+#define SPRN_MI_TWC	789
+#define MI_APG		0x000001e0	/* Access protection group (0) */
+#define MI_GUARDED	0x00000010	/* Guarded storage */
+#define MI_PSMASK	0x0000000c	/* Mask of page size bits */
+#define MI_PS8MEG	0x0000000c	/* 8M page size */
+#define MI_PS512K	0x00000004	/* 512K page size */
+#define MI_PS4K_16K	0x00000000	/* 4K or 16K page size */
+#define MI_SVALID	0x00000001	/* Segment entry is valid */
+					/* Reset value is undefined */
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the instruction TLB, using
+ * additional information from the MI_EPN, and MI_TWC registers.
+ */
+#define SPRN_MI_RPN	790
+
+/* Define an RPN value for mapping kernel memory to large virtual
+ * pages for boot initialization.  This has real page number of 0,
+ * large page size, shared page, cache enabled, and valid.
+ * Also mark all subpages valid and write access.
+ */
+#define MI_BOOTINIT	0x000001fd
+
+#define SPRN_MD_CTR	792	/* Data TLB control register */
+#define MD_GPM		0x80000000	/* Set domain manager mode */
+#define MD_PPM		0x40000000	/* Set subpage protection */
+#define MD_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
+#define MD_WTDEF	0x10000000	/* Set writethrough when MMU dis */
+#define MD_RSV4I	0x08000000	/* Reserve 4 TLB entries */
+#define MD_TWAM		0x04000000	/* Use 4K page hardware assist */
+#define MD_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
+#define MD_IDXMASK	0x00001f00	/* TLB index to be loaded */
+#define MD_RESETVAL	0x04000000	/* Value of register at reset */
+
+#define SPRN_M_CASID	793	/* Address space ID (context) to match */
+#define MC_ASIDMASK	0x0000000f	/* Bits used for ASID value */
+
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MD_AP	794
+#define MD_Ks		0x80000000	/* Should not be set */
+#define MD_Kp		0x40000000	/* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MD_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MD_EPN	795
+#define MD_EPNMASK	0xfffff000	/* Effective page number for entry */
+#define MD_EVALID	0x00000200	/* Entry is valid */
+#define MD_ASIDMASK	0x0000000f	/* ASID match value */
+					/* Reset value is undefined */
+
+/* The pointer to the base address of the first level page table.
+ * During a software tablewalk, reading this register provides the address
+ * of the entry associated with MD_EPN.
+ */
+#define SPRN_M_TWB	796
+#define	M_L1TB		0xfffff000	/* Level 1 table base address */
+#define M_L1INDX	0x00000ffc	/* Level 1 index, when read */
+					/* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the data TLB, it contains bits that get loaded into the TLB entry
+ * when the MD_RPN is written.  It is also provides the hardware assist
+ * for finding the PTE address during software tablewalk.
+ */
+#define SPRN_MD_TWC	797
+#define MD_L2TB		0xfffff000	/* Level 2 table base address */
+#define MD_L2INDX	0xfffffe00	/* Level 2 index (*pte), when read */
+#define MD_APG		0x000001e0	/* Access protection group (0) */
+#define MD_GUARDED	0x00000010	/* Guarded storage */
+#define MD_PSMASK	0x0000000c	/* Mask of page size bits */
+#define MD_PS8MEG	0x0000000c	/* 8M page size */
+#define MD_PS512K	0x00000004	/* 512K page size */
+#define MD_PS4K_16K	0x00000000	/* 4K or 16K page size */
+#define MD_WT		0x00000002	/* Use writethrough page attribute */
+#define MD_SVALID	0x00000001	/* Segment entry is valid */
+					/* Reset value is undefined */
+
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the data TLB, using
+ * additional information from the MD_EPN, and MD_TWC registers.
+ */
+#define SPRN_MD_RPN	798
+
+/* This is a temporary storage register that could be used to save
+ * a processor working register during a tablewalk.
+ */
+#define SPRN_M_TW	799
+
+#ifndef __ASSEMBLY__
+typedef unsigned long phys_addr_t;
+
+typedef struct {
+	unsigned long id;
+	unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_8XX_H_ */
diff --git a/include/asm-powerpc/mmu-fsl-booke.h b/include/asm-powerpc/mmu-fsl-booke.h
new file mode 100644
index 0000000..3758000
--- /dev/null
+++ b/include/asm-powerpc/mmu-fsl-booke.h
@@ -0,0 +1,88 @@
+#ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_
+#define _ASM_POWERPC_MMU_FSL_BOOKE_H_
+/*
+ * Freescale Book-E MMU support
+ */
+
+/* Book-E defined page sizes */
+#define BOOKE_PAGESZ_1K		0
+#define BOOKE_PAGESZ_4K		1
+#define BOOKE_PAGESZ_16K	2
+#define BOOKE_PAGESZ_64K	3
+#define BOOKE_PAGESZ_256K	4
+#define BOOKE_PAGESZ_1M		5
+#define BOOKE_PAGESZ_4M		6
+#define BOOKE_PAGESZ_16M	7
+#define BOOKE_PAGESZ_64M	8
+#define BOOKE_PAGESZ_256M	9
+#define BOOKE_PAGESZ_1GB	10
+#define BOOKE_PAGESZ_4GB	11
+#define BOOKE_PAGESZ_16GB	12
+#define BOOKE_PAGESZ_64GB	13
+#define BOOKE_PAGESZ_256GB	14
+#define BOOKE_PAGESZ_1TB	15
+
+#define MAS0_TLBSEL(x)	((x << 28) & 0x30000000)
+#define MAS0_ESEL(x)	((x << 16) & 0x0FFF0000)
+#define MAS0_NV(x)	((x) & 0x00000FFF)
+
+#define MAS1_VALID 	0x80000000
+#define MAS1_IPROT	0x40000000
+#define MAS1_TID(x)	((x << 16) & 0x3FFF0000)
+#define MAS1_TS		0x00001000
+#define MAS1_TSIZE(x)	((x << 8) & 0x00000F00)
+
+#define MAS2_EPN	0xFFFFF000
+#define MAS2_X0		0x00000040
+#define MAS2_X1		0x00000020
+#define MAS2_W		0x00000010
+#define MAS2_I		0x00000008
+#define MAS2_M		0x00000004
+#define MAS2_G		0x00000002
+#define MAS2_E		0x00000001
+
+#define MAS3_RPN	0xFFFFF000
+#define MAS3_U0		0x00000200
+#define MAS3_U1		0x00000100
+#define MAS3_U2		0x00000080
+#define MAS3_U3		0x00000040
+#define MAS3_UX		0x00000020
+#define MAS3_SX		0x00000010
+#define MAS3_UW		0x00000008
+#define MAS3_SW		0x00000004
+#define MAS3_UR		0x00000002
+#define MAS3_SR		0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_TIDDSEL	0x000F0000
+#define MAS4_TSIZED(x)	MAS1_TSIZE(x)
+#define MAS4_X0D	0x00000040
+#define MAS4_X1D	0x00000020
+#define MAS4_WD		0x00000010
+#define MAS4_ID		0x00000008
+#define MAS4_MD		0x00000004
+#define MAS4_GD		0x00000002
+#define MAS4_ED		0x00000001
+
+#define MAS6_SPID0	0x3FFF0000
+#define MAS6_SPID1	0x00007FFE
+#define MAS6_SAS	0x00000001
+#define MAS6_SPID	MAS6_SPID0
+
+#define MAS7_RPN	0xFFFFFFFF
+
+#ifndef __ASSEMBLY__
+
+#ifndef CONFIG_PHYS_64BIT
+typedef unsigned long phys_addr_t;
+#else
+typedef unsigned long long phys_addr_t;
+#endif
+
+typedef struct {
+	unsigned long id;
+	unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */
diff --git a/include/asm-powerpc/mmu-hash32.h b/include/asm-powerpc/mmu-hash32.h
new file mode 100644
index 0000000..4bd735b
--- /dev/null
+++ b/include/asm-powerpc/mmu-hash32.h
@@ -0,0 +1,91 @@
+#ifndef _ASM_POWERPC_MMU_HASH32_H_
+#define _ASM_POWERPC_MMU_HASH32_H_
+/*
+ * 32-bit hash table MMU support
+ */
+
+/*
+ * BATs
+ */
+
+/* Block size masks */
+#define BL_128K	0x000
+#define BL_256K 0x001
+#define BL_512K 0x003
+#define BL_1M   0x007
+#define BL_2M   0x00F
+#define BL_4M   0x01F
+#define BL_8M   0x03F
+#define BL_16M  0x07F
+#define BL_32M  0x0FF
+#define BL_64M  0x1FF
+#define BL_128M 0x3FF
+#define BL_256M 0x7FF
+
+/* BAT Access Protection */
+#define BPP_XX	0x00		/* No access */
+#define BPP_RX	0x01		/* Read only */
+#define BPP_RW	0x02		/* Read/write */
+
+#ifndef __ASSEMBLY__
+struct ppc_bat {
+	struct {
+		unsigned long bepi:15;	/* Effective page index (virtual address) */
+		unsigned long :4;	/* Unused */
+		unsigned long bl:11;	/* Block size mask */
+		unsigned long vs:1;	/* Supervisor valid */
+		unsigned long vp:1;	/* User valid */
+	} batu; 		/* Upper register */
+	struct {
+		unsigned long brpn:15;	/* Real page index (physical address) */
+		unsigned long :10;	/* Unused */
+		unsigned long w:1;	/* Write-thru cache */
+		unsigned long i:1;	/* Cache inhibit */
+		unsigned long m:1;	/* Memory coherence */
+		unsigned long g:1;	/* Guarded (MBZ in IBAT) */
+		unsigned long :1;	/* Unused */
+		unsigned long pp:2;	/* Page access protections */
+	} batl;			/* Lower register */
+};
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * Hash table
+ */
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX	0	/* Supervisor read/write, User none */
+#define PP_RWRX 1	/* Supervisor read/write, User read */
+#define PP_RWRW 2	/* Supervisor read/write, User read/write */
+#define PP_RXRX 3	/* Supervisor read,       User read */
+
+#ifndef __ASSEMBLY__
+
+/* Hardware Page Table Entry */
+struct hash_pte {
+	unsigned long v:1;	/* Entry is valid */
+	unsigned long vsid:24;	/* Virtual segment identifier */
+	unsigned long h:1;	/* Hash algorithm indicator */
+	unsigned long api:6;	/* Abbreviated page index */
+	unsigned long rpn:20;	/* Real (physical) page number */
+	unsigned long    :3;	/* Unused */
+	unsigned long r:1;	/* Referenced */
+	unsigned long c:1;	/* Changed */
+	unsigned long w:1;	/* Write-thru cache mode */
+	unsigned long i:1;	/* Cache inhibited */
+	unsigned long m:1;	/* Memory coherence */
+	unsigned long g:1;	/* Guarded */
+	unsigned long  :1;	/* Unused */
+	unsigned long pp:2;	/* Page protection */
+};
+
+typedef struct {
+	unsigned long id;
+	unsigned long vdso_base;
+} mm_context_t;
+
+typedef unsigned long phys_addr_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
index b8dca30..695962f 100644
--- a/include/asm-powerpc/mmu-hash64.h
+++ b/include/asm-powerpc/mmu-hash64.h
@@ -94,6 +94,9 @@
 #define HPTE_R_C		ASM_CONST(0x0000000000000080)
 #define HPTE_R_R		ASM_CONST(0x0000000000000100)
 
+#define HPTE_V_1TB_SEG		ASM_CONST(0x4000000000000000)
+#define HPTE_V_VRMA_MASK	ASM_CONST(0x4001ffffff000000)
+
 /* Values for PP (assumes Ks=0, Kp=1) */
 /* pp0 will always be 0 for linux     */
 #define PP_RWXX	0	/* Supervisor read/write, User none */
@@ -103,12 +106,12 @@
 
 #ifndef __ASSEMBLY__
 
-typedef struct {
+struct hash_pte {
 	unsigned long v;
 	unsigned long r;
-} hpte_t;
+};
 
-extern hpte_t *htab_address;
+extern struct hash_pte *htab_address;
 extern unsigned long htab_size_bytes;
 extern unsigned long htab_hash_mask;
 
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
index fe510ff..d44d211 100644
--- a/include/asm-powerpc/mmu.h
+++ b/include/asm-powerpc/mmu.h
@@ -5,13 +5,18 @@
 #ifdef CONFIG_PPC64
 /* 64-bit classic hash table MMU */
 #  include <asm/mmu-hash64.h>
+#elif defined(CONFIG_PPC_STD_MMU)
+/* 32-bit classic hash table MMU */
+#  include <asm/mmu-hash32.h>
 #elif defined(CONFIG_44x)
 /* 44x-style software loaded TLB */
 #  include <asm/mmu-44x.h>
-#else
-/* Other 32-bit.  FIXME: split up the other 32-bit MMU types, and
- * revise for arch/powerpc */
-#  include <asm-ppc/mmu.h>
+#elif defined(CONFIG_FSL_BOOKE)
+/* Freescale Book-E software loaded TLB */
+#  include <asm/mmu-fsl-booke.h>
+#elif defined (CONFIG_PPC_8xx)
+/* Motorola/Freescale 8xx software loaded TLB */
+#  include <asm/mmu-8xx.h>
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h
index 40c9e5a..f863ac2 100644
--- a/include/asm-powerpc/mmu_context.h
+++ b/include/asm-powerpc/mmu_context.h
@@ -2,16 +2,210 @@
 #define __ASM_POWERPC_MMU_CONTEXT_H
 #ifdef __KERNEL__
 
+#include <asm/mmu.h>	
+#include <asm/cputable.h>
+#include <asm-generic/mm_hooks.h>
+
 #ifndef CONFIG_PPC64
-#include <asm-ppc/mmu_context.h>
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+
+/*
+ * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
+ * (virtual segment identifiers) for each context.  Although the
+ * hardware supports 24-bit VSIDs, and thus >1 million contexts,
+ * we only use 32,768 of them.  That is ample, since there can be
+ * at most around 30,000 tasks in the system anyway, and it means
+ * that we can use a bitmap to indicate which contexts are in use.
+ * Using a bitmap means that we entirely avoid all of the problems
+ * that we used to have when the context number overflowed,
+ * particularly on SMP systems.
+ *  -- paulus.
+ */
+
+/*
+ * This function defines the mapping from contexts to VSIDs (virtual
+ * segment IDs).  We use a skew on both the context and the high 4 bits
+ * of the 32-bit virtual address (the "effective segment ID") in order
+ * to spread out the entries in the MMU hash table.  Note, if this
+ * function is changed then arch/ppc/mm/hashtable.S will have to be
+ * changed to correspond.
+ */
+#define CTX_TO_VSID(ctx, va)	(((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
+				 & 0xffffff)
+
+/*
+   The MPC8xx has only 16 contexts.  We rotate through them on each
+   task switch.  A better way would be to keep track of tasks that
+   own contexts, and implement an LRU usage.  That way very active
+   tasks don't always have to pay the TLB reload overhead.  The
+   kernel pages are mapped shared, so the kernel can run on behalf
+   of any task that makes a kernel entry.  Shared does not mean they
+   are not protected, just that the ASID comparison is not performed.
+        -- Dan
+
+   The IBM4xx has 256 contexts, so we can just rotate through these
+   as a way of "switching" contexts.  If the TID of the TLB is zero,
+   the PID/TID comparison is disabled, so we can use a TID of zero
+   to represent all kernel pages as shared among all contexts.
+   	-- Dan
+ */
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+#ifdef CONFIG_8xx
+#define NO_CONTEXT      	16
+#define LAST_CONTEXT    	15
+#define FIRST_CONTEXT    	0
+
+#elif defined(CONFIG_4xx)
+#define NO_CONTEXT      	256
+#define LAST_CONTEXT    	255
+#define FIRST_CONTEXT    	1
+
+#elif defined(CONFIG_E200) || defined(CONFIG_E500)
+#define NO_CONTEXT      	256
+#define LAST_CONTEXT    	255
+#define FIRST_CONTEXT    	1
+
+#else
+
+/* PPC 6xx, 7xx CPUs */
+#define NO_CONTEXT      	((unsigned long) -1)
+#define LAST_CONTEXT    	32767
+#define FIRST_CONTEXT    	1
+#endif
+
+/*
+ * Set the current MMU context.
+ * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by
+ * loading up the segment registers for the user part of the address space.
+ *
+ * Since the PGD is immediately available, it is much faster to simply
+ * pass this along as a second parameter, which is required for 8xx and
+ * can be used for debugging on all processors (if you happen to have
+ * an Abatron).
+ */
+extern void set_context(unsigned long contextid, pgd_t *pgd);
+
+/*
+ * Bitmap of contexts in use.
+ * The size of this bitmap is LAST_CONTEXT + 1 bits.
+ */
+extern unsigned long context_map[];
+
+/*
+ * This caches the next context number that we expect to be free.
+ * Its use is an optimization only, we can't rely on this context
+ * number to be free, but it usually will be.
+ */
+extern unsigned long next_mmu_context;
+
+/*
+ * If we don't have sufficient contexts to give one to every task
+ * that could be in the system, we need to be able to steal contexts.
+ * These variables support that.
+ */
+#if LAST_CONTEXT < 30000
+#define FEW_CONTEXTS	1
+extern atomic_t nr_free_contexts;
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
+extern void steal_context(void);
+#endif
+
+/*
+ * Get a new mmu context for the address space described by `mm'.
+ */
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+	unsigned long ctx;
+
+	if (mm->context.id != NO_CONTEXT)
+		return;
+#ifdef FEW_CONTEXTS
+	while (atomic_dec_if_positive(&nr_free_contexts) < 0)
+		steal_context();
+#endif
+	ctx = next_mmu_context;
+	while (test_and_set_bit(ctx, context_map)) {
+		ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
+		if (ctx > LAST_CONTEXT)
+			ctx = 0;
+	}
+	next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+	mm->context.id = ctx;
+#ifdef FEW_CONTEXTS
+	context_mm[ctx] = mm;
+#endif
+}
+
+/*
+ * Set up the context for a new address space.
+ */
+static inline int init_new_context(struct task_struct *t, struct mm_struct *mm)
+{
+	mm->context.id = NO_CONTEXT;
+	mm->context.vdso_base = 0;
+	return 0;
+}
+
+/*
+ * We're finished using the context for an address space.
+ */
+static inline void destroy_context(struct mm_struct *mm)
+{
+	preempt_disable();
+	if (mm->context.id != NO_CONTEXT) {
+		clear_bit(mm->context.id, context_map);
+		mm->context.id = NO_CONTEXT;
+#ifdef FEW_CONTEXTS
+		atomic_inc(&nr_free_contexts);
+#endif
+	}
+	preempt_enable();
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+#ifdef CONFIG_ALTIVEC
+	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
+	 : : );
+#endif /* CONFIG_ALTIVEC */
+
+	tsk->thread.pgdir = next->pgd;
+
+	/* No need to flush userspace segments if the mm doesnt change */
+	if (prev == next)
+		return;
+
+	/* Setup new userspace context */
+	get_mmu_context(next);
+	set_context(next->context.id, next->pgd);
+}
+
+#define deactivate_mm(tsk,mm)	do { } while (0)
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+#define activate_mm(active_mm, mm)   switch_mm(active_mm, mm, current)
+
+extern void mmu_context_init(void);
+
+
 #else
 
 #include <linux/kernel.h>	
 #include <linux/mm.h>	
 #include <linux/sched.h>
-#include <asm/mmu.h>	
-#include <asm/cputable.h>
-#include <asm-generic/mm_hooks.h>
 
 /*
  * Copyright (C) 2001 PPC 64 Team, IBM Corp
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
index b85df45..15f650f 100644
--- a/include/asm-powerpc/mpc86xx.h
+++ b/include/asm-powerpc/mpc86xx.h
@@ -19,12 +19,6 @@
 
 #ifdef CONFIG_PPC_86xx
 
-#define _IO_BASE        isa_io_base
-#define _ISA_MEM_BASE   isa_mem_base
-#ifdef CONFIG_PCI
-#define PCI_DRAM_OFFSET pci_dram_offset
-#endif
-
 #define CPU0_BOOT_RELEASE 0x01000000
 #define CPU1_BOOT_RELEASE 0x02000000
 #define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
diff --git a/include/asm-powerpc/mpc8xx.h b/include/asm-powerpc/mpc8xx.h
index 5803711..2be014b 100644
--- a/include/asm-powerpc/mpc8xx.h
+++ b/include/asm-powerpc/mpc8xx.h
@@ -23,6 +23,10 @@
 #include <platforms/8xx/mpc885ads.h>
 #endif
 
+#ifdef CONFIG_PCMCIA_M8XX
+extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
 #endif /* CONFIG_8xx */
 #endif /* __CONFIG_8xx_DEFS */
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index d9bf5ab..e72c2a6 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -2,12 +2,91 @@
 #define _ASM_POWERPC_PCI_BRIDGE_H
 #ifdef __KERNEL__
 
-#ifndef CONFIG_PPC64
-#include <asm-ppc/pci-bridge.h>
-#else
-
 #include <linux/pci.h>
 #include <linux/list.h>
+#include <linux/ioport.h>
+
+#ifndef CONFIG_PPC64
+
+struct device_node;
+struct pci_controller;
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+struct pci_controller {
+	struct pci_bus *bus;
+	char is_dynamic;
+	void *arch_data;
+	struct list_head list_node;
+	struct device *parent;
+
+	int first_busno;
+	int last_busno;
+	int self_busno;
+
+	void __iomem *io_base_virt;
+	resource_size_t io_base_phys;
+
+	/* Some machines (PReP) have a non 1:1 mapping of
+	 * the PCI memory space in the CPU bus space
+	 */
+	resource_size_t pci_mem_offset;
+
+	struct pci_ops *ops;
+	volatile unsigned int __iomem *cfg_addr;
+	volatile void __iomem *cfg_data;
+
+	/*
+	 * Used for variants of PCI indirect handling and possible quirks:
+	 *  SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
+	 *  EXT_REG - provides access to PCI-e extended registers
+	 *  SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS
+	 *   on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS
+	 *   to determine which bus number to match on when generating type0
+	 *   config cycles
+	 */
+#define PPC_INDIRECT_TYPE_SET_CFG_TYPE		(0x00000001)
+#define PPC_INDIRECT_TYPE_EXT_REG		(0x00000002)
+#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS	(0x00000004)
+	u32 indirect_type;
+
+	/* Currently, we limit ourselves to 1 IO range and 3 mem
+	 * ranges since the common pci_bus structure can't handle more
+	 */
+	struct resource	io_resource;
+	struct resource mem_resources[3];
+	int global_number;		/* PCI domain number */
+};
+
+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,
+			   int where, u8 *val);
+int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn,
+			   int where, u16 *val);
+int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u32 *val);
+int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u8 val);
+int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u16 val);
+int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+			     int where, u32 val);
+
+extern void setup_indirect_pci_nomap(struct pci_controller* hose,
+			       void __iomem *cfg_addr, void __iomem *cfg_data);
+extern void setup_indirect_pci(struct pci_controller* hose,
+			       u32 cfg_addr, u32 cfg_data);
+extern void setup_grackle(struct pci_controller *hose);
+
+#else
+
 
 /*
  * This program is free software; you can redistribute it and/or
@@ -31,6 +110,7 @@
 	int last_busno;
 
 	void __iomem *io_base_virt;
+	void *io_base_alloc;
 	resource_size_t io_base_phys;
 
 	/* Some machines have a non 1:1 mapping of
@@ -48,8 +128,7 @@
 	 */
 	struct resource io_resource;
 	struct resource mem_resources[3];
-	int global_number;		
-	int local_number;		
+	int global_number;
 	unsigned long buid;
 	unsigned long dma_window_base_cur;
 	unsigned long dma_window_size;
@@ -70,19 +149,22 @@
 	int	devfn;			/* pci device and function number */
 	int	class_code;		/* pci device class */
 
-#ifdef CONFIG_PPC_PSERIES
+	struct  pci_controller *phb;	/* for pci devices */
+	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 */
+
+	int	pci_ext_config_space;	/* for pci devices */
+
+#ifdef CONFIG_EEH
 	int	eeh_mode;		/* See eeh.h for possible EEH_MODEs */
 	int	eeh_config_addr;
 	int	eeh_pe_config_addr; /* new-style partition endpoint address */
 	int 	eeh_check_count;	/* # times driver ignored error */
 	int 	eeh_freeze_count;	/* # times this device froze up. */
-#endif
-	int	pci_ext_config_space;	/* for pci devices */
-	struct  pci_controller *phb;	/* for pci devices */
-	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 */
+	int 	eeh_false_positives;	/* # times this device reported #ff's */
 	u32	config_space[16];	/* saved PCI config space */
+#endif
 };
 
 /* Get the pointer to a device_node's pci_dn */
@@ -128,9 +210,6 @@
 /** Find the bus corresponding to the indicated device node */
 struct pci_bus * pcibios_find_pci_bus(struct device_node *dn);
 
-extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
-					 struct device_node *dev, int primary);
-
 /** Remove all of the PCI devices under this bus */
 void pcibios_remove_pci_devices(struct pci_bus *bus);
 
@@ -148,21 +227,12 @@
 	return PCI_DN(busdn)->phb;
 }
 
-extern struct pci_controller*
-pci_find_hose_for_OF_device(struct device_node* node);
-
-extern struct pci_controller *
-pcibios_alloc_controller(struct device_node *dev);
 extern void pcibios_free_controller(struct pci_controller *phb);
 
-#ifdef CONFIG_PCI
-extern unsigned long pci_address_to_pio(phys_addr_t address);
-#else
-static inline unsigned long pci_address_to_pio(phys_addr_t address)
-{
-	return (unsigned long)-1;
-}
-#endif
+extern void isa_bridge_find_early(struct pci_controller *hose);
+
+extern int pcibios_unmap_io_space(struct pci_bus *bus);
+extern int pcibios_map_io_space(struct pci_bus *bus);
 
 /* Return values for ppc_md.pci_probe_mode function */
 #define PCI_PROBE_NONE		-1	/* Don't look at this bus at all */
@@ -176,5 +246,29 @@
 #endif
 
 #endif /* CONFIG_PPC64 */
+
+/* Get the PCI host controller for an OF device */
+extern struct pci_controller*
+pci_find_hose_for_OF_device(struct device_node* node);
+
+/* Fill up host controller resources from the OF node */
+extern void
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+			   struct device_node *dev, int primary);
+
+/* Allocate a new PCI host bridge structure */
+extern struct pci_controller *
+pcibios_alloc_controller(struct device_node *dev);
+#ifdef CONFIG_PCI
+extern unsigned long pci_address_to_pio(phys_addr_t address);
+#else
+static inline unsigned long pci_address_to_pio(phys_addr_t address)
+{
+	return (unsigned long)-1;
+}
+#endif
+
+
+
 #endif /* __KERNEL__ */
 #endif
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index e16e7bc..7b11765 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -95,8 +95,6 @@
 #define get_pci_dma_ops()	NULL
 #endif
 
-extern int pci_domain_nr(struct pci_bus *bus);
-
 /* Decide whether to display the domain number in /proc */
 extern int pci_proc_domain(struct pci_bus *bus);
 
@@ -112,9 +110,6 @@
 }
 #endif
 
-/* Return the index of the PCI controller for device PDEV. */
-#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-
 /* Set the name of the bus as it appears in /proc/bus/pci */
 static inline int pci_proc_domain(struct pci_bus *bus)
 {
@@ -123,6 +118,8 @@
 
 #endif /* CONFIG_PPC64 */
 
+extern int pci_domain_nr(struct pci_bus *bus);
+
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
@@ -202,10 +199,6 @@
 	return root;
 }
 
-extern int unmap_bus_range(struct pci_bus *bus);
-
-extern int remap_bus_range(struct pci_bus *bus);
-
 extern void pcibios_fixup_device_resources(struct pci_dev *dev,
 			struct pci_bus *bus);
 
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index 7fb730c..86a54a4a 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -6,11 +6,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/sched.h>
 #include <linux/threads.h>
-#include <asm/processor.h>		/* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
 #include <asm/io.h>			/* For sub-arch specific PPC_PIN_SIZE */
-struct mm_struct;
 
 extern unsigned long va_to_phys(unsigned long address);
 extern pte_t *va_to_pte(unsigned long address);
@@ -488,14 +484,6 @@
 #define pfn_pte(pfn, prot)	__pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
 					pgprot_val(prot))
 #define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[1024];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-
 #endif /* __ASSEMBLY__ */
 
 #define pte_none(pte)		((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
@@ -512,9 +500,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
-static inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_EXEC; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
@@ -522,21 +508,13 @@
 static inline void pte_uncache(pte_t pte)       { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)         { pte_val(pte) &= ~_PAGE_NO_CACHE; }
 
-static inline pte_t pte_rdprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_EXEC; return pte; }
 static inline pte_t pte_mkclean(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
 static inline pte_t pte_mkold(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 
-static inline pte_t pte_mkread(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte) {
 	pte_val(pte) |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte) {
@@ -643,13 +621,6 @@
 #define ptep_test_and_clear_young(__vma, __addr, __ptep) \
 	__ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
 
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
-					    unsigned long addr, pte_t *ptep)
-{
-	return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
-}
-
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 				       pte_t *ptep)
@@ -734,10 +705,6 @@
 #define pte_unmap(pte)		kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte)	kunmap_atomic(pte, KM_PTE1)
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-extern void paging_init(void);
-
 /*
  * Encode and decode a swap entry.
  * Note that the bits we use in a PTE for representing a swap entry
@@ -755,40 +722,6 @@
 #define pte_to_pgoff(pte)	(pte_val(pte) >> 3)
 #define pgoff_to_pte(off)	((pte_t) { ((off) << 3) | _PAGE_FILE })
 
-/* CONFIG_APUS */
-/* For virtual address to physical address conversion */
-extern void cache_clear(__u32 addr, int length);
-extern void cache_push(__u32 addr, int length);
-extern int mm_end_of_chunk (unsigned long addr, int len);
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-
-/* Values for nocacheflag and cmode */
-/* These are not used by the APUS kernel_map, but prevents
-   compilation errors. */
-#define	KERNELMAP_FULL_CACHING		0
-#define	KERNELMAP_NOCACHE_SER		1
-#define	KERNELMAP_NOCACHE_NONSER	2
-#define	KERNELMAP_NO_COPYBACK		3
-
-/*
- * Map some physical address range into the kernel address space.
- */
-extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
-				int nocacheflag, unsigned long *memavailp );
-
-/*
- * Set cache mode of (kernel space) address range.
- */
-extern void kernel_set_cachemode (unsigned long address, unsigned long size,
-                                 unsigned int cmode);
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr)	(1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
-		remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 /*
  * No page table caches to initialise
  */
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index 3cfd98f..300f9a1 100644
--- a/include/asm-powerpc/pgtable-ppc64.h
+++ b/include/asm-powerpc/pgtable-ppc64.h
@@ -7,11 +7,7 @@
 
 #ifndef __ASSEMBLY__
 #include <linux/stddef.h>
-#include <asm/processor.h>		/* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
 #include <asm/tlbflush.h>
-struct mm_struct;
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_64K_PAGES
@@ -27,7 +23,7 @@
  */
 #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
                 	    PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
-#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
+#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
 
 #if TASK_SIZE_USER64 > PGTABLE_RANGE
 #error TASK_SIZE_USER64 exceeds pagetable range
@@ -37,19 +33,28 @@
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
 
+
 /*
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START ASM_CONST(0xD000000000000000)
-#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
+#define VMALLOC_SIZE  (PGTABLE_RANGE >> 1)
 #define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
 
 /*
- * Define the address range of the imalloc VM area.
+ * Define the address ranges for MMIO and IO space :
+ *
+ *  ISA_IO_BASE = VMALLOC_END, 64K reserved area
+ *  PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
+ * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
  */
-#define PHBS_IO_BASE	VMALLOC_END
-#define IMALLOC_BASE	(PHBS_IO_BASE + 0x80000000ul)	/* Reserve 2 gigs for PHBs */
-#define IMALLOC_END	(VMALLOC_START + PGTABLE_RANGE)
+#define FULL_IO_SIZE	0x80000000ul
+#define  ISA_IO_BASE	(VMALLOC_END)
+#define  ISA_IO_END	(VMALLOC_END + 0x10000ul)
+#define  PHB_IO_BASE	(ISA_IO_END)
+#define  PHB_IO_END	(VMALLOC_END + FULL_IO_SIZE)
+#define IOREMAP_BASE	(PHB_IO_END)
+#define IOREMAP_END	(VMALLOC_START + PGTABLE_RANGE)
 
 /*
  * Region IDs
@@ -134,16 +139,6 @@
 #define __S110	PAGE_SHARED_X
 #define __S111	PAGE_SHARED_X
 
-#ifndef __ASSEMBLY__
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-#endif /* __ASSEMBLY__ */
-
 #ifdef CONFIG_HUGETLB_PAGE
 
 #define HAVE_ARCH_UNMAPPED_AREA
@@ -232,9 +227,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER;}
 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
-static inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC;}
 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
 static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
@@ -242,20 +235,12 @@
 static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
 
-static inline pte_t pte_rdprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_EXEC; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_RW); return pte; }
 static inline pte_t pte_mkclean(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
 static inline pte_t pte_mkold(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte) {
 	pte_val(pte) |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte) {
@@ -307,29 +292,6 @@
 	__r;								   \
 })
 
-/*
- * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
- * moment we always flush but we need to fix hpte_update and test if the
- * optimisation is worth it.
- */
-static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm,
-					      unsigned long addr, pte_t *ptep)
-{
-	unsigned long old;
-
-       	if ((pte_val(*ptep) & _PAGE_DIRTY) == 0)
-		return 0;
-	old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0);
-	return (old & _PAGE_DIRTY) != 0;
-}
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __addr, __ptep)		   \
-({									   \
-	int __r;							   \
-	__r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
-	__r;								   \
-})
-
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
 				      pte_t *ptep)
@@ -357,14 +319,6 @@
 	__young;							\
 })
 
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep)		\
-({									\
-	int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
-						  __ptep); 		\
-	__dirty;							\
-})
-
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 				       unsigned long addr, pte_t *ptep)
@@ -442,10 +396,6 @@
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
-extern pgd_t swapper_pg_dir[];
-
-extern void paging_init(void);
-
 /* Encode and de-code a swap entry */
 #define __swp_type(entry)	(((entry).val >> 1) & 0x3f)
 #define __swp_offset(entry)	((entry).val >> 8)
@@ -456,17 +406,6 @@
 #define pgoff_to_pte(off)	((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
 #define PTE_FILE_MAX_BITS	(BITS_PER_LONG - PTE_RPN_SHIFT)
 
-/*
- * kern_addr_valid is intended to indicate whether an address is a valid
- * kernel address.  Most 32-bit archs define it as always true (like this)
- * but most 64-bit archs actually perform a test.  What should we do here?
- * The only use is in fs/ncpfs/dir.c
- */
-#define kern_addr_valid(addr)	(1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
-		remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 void pgtable_cache_init(void);
 
 /*
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h
index 78bf4ae..d18ffe7 100644
--- a/include/asm-powerpc/pgtable.h
+++ b/include/asm-powerpc/pgtable.h
@@ -2,6 +2,13 @@
 #define _ASM_POWERPC_PGTABLE_H
 #ifdef __KERNEL__
 
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>		/* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+struct mm_struct;
+#endif /* !__ASSEMBLY__ */
+
 #if defined(CONFIG_PPC64)
 #  include <asm/pgtable-ppc64.h>
 #else
@@ -9,6 +16,27 @@
 #endif
 
 #ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern pgd_t swapper_pg_dir[];
+
+extern void paging_init(void);
+
+/*
+ * kern_addr_valid is intended to indicate whether an address is a valid
+ * kernel address.  Most 32-bit archs define it as always true (like this)
+ * but most 64-bit archs actually perform a test.  What should we do here?
+ */
+#define kern_addr_valid(addr)	(1)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+		remap_pfn_range(vma, vaddr, pfn, size, prot)
+
 #include <asm-generic/pgtable.h>
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index 8e20051..b847aa1 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -26,7 +26,7 @@
 
 extern void find_and_init_phbs(void);
 
-extern struct pci_dev *ppc64_isabridge_dev;	/* may be NULL if no ISA bus */
+extern struct pci_dev *isa_bridge_pcidev;	/* may be NULL if no ISA bus */
 
 /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
 #define BUID_HI(buid) ((buid) >> 32)
@@ -47,8 +47,8 @@
 extern unsigned long get_phb_buid (struct device_node *);
 extern int rtas_setup_phb(struct pci_controller *phb);
 
-/* From pSeries_pci.h */
-extern void pSeries_final_fixup(void);
+/* From iSeries PCI */
+extern void iSeries_pcibios_init(void);
 
 extern unsigned long pci_probe_only;
 
@@ -139,6 +139,9 @@
  */
 struct device_node * find_device_pe(struct device_node *dn);
 
+void eeh_sysfs_add_device(struct pci_dev *pdev);
+void eeh_sysfs_remove_device(struct pci_dev *pdev);
+
 #endif /* CONFIG_EEH */
 
 #else /* CONFIG_PCI */
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index d947b16..e28b108 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -43,14 +43,6 @@
 /* what kind of prep workstation we are */
 extern int _prep_type;
 
-/*
- * This is used to identify the board type from a given PReP board
- * vendor. Board revision is also made available. This will be moved
- * elsewhere soon
- */
-extern unsigned char ucBoardRev;
-extern unsigned char ucBoardRevMaj, ucBoardRevMin;
-
 #endif /* CONFIG_PPC_PREP */
 
 #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 6845af9..1632baa 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -98,10 +98,19 @@
 extern struct device_node *of_chosen;
 
 /* flag descriptions */
-#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+#define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
+#define OF_DETACHED	2 /* node has been detached from the device tree */
 
-#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
-#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
+static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
+{
+	return test_bit(flag, &n->_flags);
+}
+
+static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
+{
+	set_bit(flag, &n->_flags);
+}
+
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
@@ -124,6 +133,9 @@
 	     dn = of_find_node_by_type(dn, type))
 extern struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compat);
+#define for_each_compatible_node(dn, type, compatible) \
+	for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
+	     dn = of_find_compatible_node(dn, type, compatible))
 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);
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 1e04651..a6f3f5e 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -35,7 +35,8 @@
 	};
 };
 
-int ps3_get_firmware_version(union ps3_firmware_version *v);
+void ps3_get_firmware_version(union ps3_firmware_version *v);
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev);
 
 /* 'Other OS' area */
 
@@ -48,18 +49,6 @@
 
 enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void);
 
-/**
- * struct ps3_device_id - HV bus device identifier from the system repository
- * @bus_id: HV bus id, {1..} (zero invalid)
- * @dev_id: HV device id, {0..}
- */
-
-struct ps3_device_id {
-	unsigned int bus_id;
-	unsigned int dev_id;
-};
-
-
 /* dma routines */
 
 enum ps3_dma_page_size {
@@ -74,6 +63,8 @@
 	PS3_DMA_INTERNAL = 2,
 };
 
+struct ps3_dma_region_ops;
+
 /**
  * struct ps3_dma_region - A per device dma state variables structure
  * @did: The HV device id.
@@ -81,21 +72,42 @@
  * @region_type: The HV region type.
  * @bus_addr: The 'translated' bus address of the region.
  * @len: The length in bytes of the region.
+ * @offset: The offset from the start of memory of the region.
+ * @ioid: The IOID of the device who owns this region
  * @chunk_list: Opaque variable used by the ioc page manager.
+ * @region_ops: struct ps3_dma_region_ops - dma region operations
  */
 
 struct ps3_dma_region {
-	struct ps3_device_id did;
+	struct ps3_system_bus_device *dev;
+	/* device variables */
+	const struct ps3_dma_region_ops *region_ops;
+	unsigned char ioid;
 	enum ps3_dma_page_size page_size;
 	enum ps3_dma_region_type region_type;
-	unsigned long bus_addr;
 	unsigned long len;
+	unsigned long offset;
+
+	/* driver variables  (set by ps3_dma_region_create) */
+	unsigned long bus_addr;
 	struct {
 		spinlock_t lock;
 		struct list_head head;
 	} chunk_list;
 };
 
+struct ps3_dma_region_ops {
+	int (*create)(struct ps3_dma_region *);
+	int (*free)(struct ps3_dma_region *);
+	int (*map)(struct ps3_dma_region *,
+		   unsigned long virt_addr,
+		   unsigned long len,
+		   unsigned long *bus_addr,
+		   u64 iopte_pp);
+	int (*unmap)(struct ps3_dma_region *,
+		     unsigned long bus_addr,
+		     unsigned long len);
+};
 /**
  * struct ps3_dma_region_init - Helper to initialize structure variables
  *
@@ -103,18 +115,16 @@
  * ps3_system_bus_device_register.
  */
 
-static inline void ps3_dma_region_init(struct ps3_dma_region *r,
-	const struct ps3_device_id* did, enum ps3_dma_page_size page_size,
-	enum ps3_dma_region_type region_type)
-{
-	r->did = *did;
-	r->page_size = page_size;
-	r->region_type = region_type;
-}
+struct ps3_system_bus_device;
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+	enum ps3_dma_region_type region_type, void *addr, unsigned long len);
 int ps3_dma_region_create(struct ps3_dma_region *r);
 int ps3_dma_region_free(struct ps3_dma_region *r);
 int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
-	unsigned long len, unsigned long *bus_addr);
+	unsigned long len, unsigned long *bus_addr,
+	u64 iopte_pp);
 int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
 	unsigned long len);
 
@@ -125,6 +135,7 @@
 	PS3_MMIO_64K = 16U
 };
 
+struct ps3_mmio_region_ops;
 /**
  * struct ps3_mmio_region - a per device mmio state variables structure
  *
@@ -132,13 +143,18 @@
  */
 
 struct ps3_mmio_region {
-	struct ps3_device_id did;
+	struct ps3_system_bus_device *dev;
+	const struct ps3_mmio_region_ops *mmio_ops;
 	unsigned long bus_addr;
 	unsigned long len;
 	enum ps3_mmio_page_size page_size;
 	unsigned long lpar_addr;
 };
 
+struct ps3_mmio_region_ops {
+	int (*create)(struct ps3_mmio_region *);
+	int (*free)(struct ps3_mmio_region *);
+};
 /**
  * struct ps3_mmio_region_init - Helper to initialize structure variables
  *
@@ -146,15 +162,9 @@
  * ps3_system_bus_device_register.
  */
 
-static inline void ps3_mmio_region_init(struct ps3_mmio_region *r,
-	const struct ps3_device_id* did, unsigned long bus_addr,
-	unsigned long len, enum ps3_mmio_page_size page_size)
-{
-	r->did = *did;
-	r->bus_addr = bus_addr;
-	r->len = len;
-	r->page_size = page_size;
-}
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+	enum ps3_mmio_page_size page_size);
 int ps3_mmio_region_create(struct ps3_mmio_region *r);
 int ps3_free_mmio_region(struct ps3_mmio_region *r);
 unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr);
@@ -187,11 +197,10 @@
 	unsigned int class, unsigned int *virq);
 int ps3_spe_irq_destroy(unsigned int virq);
 
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
-	const struct ps3_device_id *did, unsigned int interrupt_id,
-	unsigned int *virq);
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
-	unsigned int interrupt_id, unsigned int virq);
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+	enum ps3_cpu_binding cpu, unsigned int *virq);
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+	unsigned int virq);
 
 /* lv1 result codes */
 
@@ -289,11 +298,33 @@
 /* system bus routines */
 
 enum ps3_match_id {
-	PS3_MATCH_ID_EHCI = 1,
-	PS3_MATCH_ID_OHCI,
-	PS3_MATCH_ID_GELIC,
-	PS3_MATCH_ID_AV_SETTINGS,
-	PS3_MATCH_ID_SYSTEM_MANAGER,
+	PS3_MATCH_ID_EHCI           = 1,
+	PS3_MATCH_ID_OHCI           = 2,
+	PS3_MATCH_ID_GELIC          = 3,
+	PS3_MATCH_ID_AV_SETTINGS    = 4,
+	PS3_MATCH_ID_SYSTEM_MANAGER = 5,
+	PS3_MATCH_ID_STOR_DISK      = 6,
+	PS3_MATCH_ID_STOR_ROM       = 7,
+	PS3_MATCH_ID_STOR_FLASH     = 8,
+	PS3_MATCH_ID_SOUND          = 9,
+	PS3_MATCH_ID_GRAPHICS       = 10,
+};
+
+#define PS3_MODULE_ALIAS_EHCI           "ps3:1"
+#define PS3_MODULE_ALIAS_OHCI           "ps3:2"
+#define PS3_MODULE_ALIAS_GELIC          "ps3:3"
+#define PS3_MODULE_ALIAS_AV_SETTINGS    "ps3:4"
+#define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5"
+#define PS3_MODULE_ALIAS_STOR_DISK      "ps3:6"
+#define PS3_MODULE_ALIAS_STOR_ROM       "ps3:7"
+#define PS3_MODULE_ALIAS_STOR_FLASH     "ps3:8"
+#define PS3_MODULE_ALIAS_SOUND          "ps3:9"
+#define PS3_MODULE_ALIAS_GRAPHICS       "ps3:10"
+
+enum ps3_system_bus_device_type {
+	PS3_DEVICE_TYPE_IOC0 = 1,
+	PS3_DEVICE_TYPE_SB,
+	PS3_DEVICE_TYPE_VUART,
 };
 
 /**
@@ -302,14 +333,23 @@
 
 struct ps3_system_bus_device {
 	enum ps3_match_id match_id;
-	struct ps3_device_id did;
-	unsigned int interrupt_id;
-/*	struct iommu_table *iommu_table; -- waiting for Ben's cleanups */
-	struct ps3_dma_region *d_region;
-	struct ps3_mmio_region *m_region;
+	enum ps3_system_bus_device_type dev_type;
+
+	unsigned int bus_id;              /* SB */
+	unsigned int dev_id;              /* SB */
+	unsigned int interrupt_id;        /* SB */
+	struct ps3_dma_region *d_region;  /* SB, IOC0 */
+	struct ps3_mmio_region *m_region; /* SB, IOC0*/
+	unsigned int port_number;         /* VUART */
+
+/*	struct iommu_table *iommu_table; -- waiting for BenH's cleanups */
 	struct device core;
+	void *driver_priv; /* private driver variables */
 };
 
+int ps3_open_hv_device(struct ps3_system_bus_device *dev);
+int ps3_close_hv_device(struct ps3_system_bus_device *dev);
+
 /**
  * struct ps3_system_bus_driver - a driver for a device on the system bus
  */
@@ -319,6 +359,7 @@
 	struct device_driver core;
 	int (*probe)(struct ps3_system_bus_device *);
 	int (*remove)(struct ps3_system_bus_device *);
+	int (*shutdown)(struct ps3_system_bus_device *);
 /*	int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
 /*	int (*resume)(struct ps3_system_bus_device *); */
 };
@@ -326,16 +367,24 @@
 int ps3_system_bus_device_register(struct ps3_system_bus_device *dev);
 int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv);
 void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv);
-static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver(
+
+static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv(
 	struct device_driver *_drv)
 {
 	return container_of(_drv, struct ps3_system_bus_driver, core);
 }
-static inline struct ps3_system_bus_device *to_ps3_system_bus_device(
+static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev(
 	struct device *_dev)
 {
 	return container_of(_dev, struct ps3_system_bus_device, core);
 }
+static inline struct ps3_system_bus_driver *
+	ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev)
+{
+	BUG_ON(!_dev);
+	BUG_ON(!_dev->core.driver);
+	return ps3_drv_to_system_bus_drv(_dev->core.driver);
+}
 
 /**
  * ps3_system_bus_set_drvdata -
@@ -358,32 +407,17 @@
 
 extern struct bus_type ps3_system_bus_type;
 
-/* vuart routines */
-
-struct ps3_vuart_port_priv;
-
-/**
- * struct ps3_vuart_port_device - a device on a vuart port
- */
-
-struct ps3_vuart_port_device {
-	enum ps3_match_id match_id;
-	struct device core;
-	struct ps3_vuart_port_priv* priv; /* private driver variables */
-
-};
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
-
 /* system manager */
 
-#ifdef CONFIG_PS3_SYS_MANAGER
-void ps3_sys_manager_restart(void);
+struct ps3_sys_manager_ops {
+	struct ps3_system_bus_device *dev;
+	void (*power_off)(struct ps3_system_bus_device *dev);
+	void (*restart)(struct ps3_system_bus_device *dev);
+};
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
 void ps3_sys_manager_power_off(void);
-#else
-static inline void ps3_sys_manager_restart(void) {}
-static inline void ps3_sys_manager_power_off(void) {}
-#endif
+void ps3_sys_manager_restart(void);
 
 struct ps3_prealloc {
     const char *name;
@@ -393,5 +427,7 @@
 };
 
 extern struct ps3_prealloc ps3fb_videomemory;
+extern struct ps3_prealloc ps3flash_bounce_buffer;
+
 
 #endif
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
index 9efc40f..7df4250 100644
--- a/include/asm-powerpc/ps3av.h
+++ b/include/asm-powerpc/ps3av.h
@@ -1,20 +1,23 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend 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; version 2 of the License.
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
  *
- * 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.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  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_POWERPC_PS3AV_H_
 #define _ASM_POWERPC_PS3AV_H_
 
@@ -159,6 +162,9 @@
 #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
 /* video_out_format */
 #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
+/* video_cl_cnv */
+#define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT		0x0000
+#define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT		0x0010
 /* video_sync */
 #define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
 #define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
@@ -311,6 +317,8 @@
 #define PS3AV_MODE_MASK				0x000F
 #define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
 #define PS3AV_MODE_DITHER			0x0800
+#define PS3AV_MODE_COLOR			0x0400
+#define PS3AV_MODE_WHITE			0x0200
 #define PS3AV_MODE_FULL				0x0080
 #define PS3AV_MODE_DVI				0x0040
 #define PS3AV_MODE_RGB				0x0020
@@ -529,9 +537,9 @@
 	u32 video_out_format;	/* in: out format */
 	u32 video_format;	/* in: input frame buffer format */
 	u8 reserved3;
-	u8 reserved4;
+	u8 video_cl_cnv;	/* in: color conversion */
 	u16 video_order;	/* in: input RGB order */
-	u32 reserved5;
+	u32 reserved4;
 };
 
 /* video: format */
@@ -539,7 +547,8 @@
 	struct ps3av_send_hdr send_hdr;
 	u32 video_head;		/* in: head */
 	u32 video_format;	/* in: frame buffer format */
-	u16 reserved;
+	u8 reserved;
+	u8 video_cl_cnv;	/* in: color conversion */
 	u16 video_order;	/* in: input RGB order */
 };
 
@@ -698,12 +707,6 @@
 extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
 					    u32);
 
-struct ps3_vuart_port_device;
-extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
-			     const void *buf, unsigned long size);
-extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-			    unsigned long size, int timeout);
-
 extern int ps3av_set_video_mode(u32, int);
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
 extern int ps3av_get_auto_mode(int);
@@ -716,5 +719,8 @@
 extern int ps3av_audio_mute(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
+extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+				    void *flip_data);
+extern void ps3av_flip_ctl(int on);
 
 #endif	/* _ASM_POWERPC_PS3AV_H_ */
diff --git a/include/asm-powerpc/ps3fb.h b/include/asm-powerpc/ps3fb.h
index ad81cf4..3f121fe 100644
--- a/include/asm-powerpc/ps3fb.h
+++ b/include/asm-powerpc/ps3fb.h
@@ -41,16 +41,4 @@
 	__u32 num_frames; /* num of frame buffers */
 };
 
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FB_PS3
-extern void ps3fb_flip_ctl(int on);
-extern void ps3fb_cleanup(void);
-#else
-static inline void ps3fb_flip_ctl(int on) {}
-static inline void ps3fb_cleanup(void) {}
-#endif
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_POWERPC_PS3FB_H_ */
diff --git a/include/asm-powerpc/ps3stor.h b/include/asm-powerpc/ps3stor.h
new file mode 100644
index 0000000..6fcaf71
--- /dev/null
+++ b/include/asm-powerpc/ps3stor.h
@@ -0,0 +1,71 @@
+/*
+ * PS3 Storage Devices
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _ASM_POWERPC_PS3STOR_H_
+#define _ASM_POWERPC_PS3STOR_H_
+
+#include <linux/interrupt.h>
+
+#include <asm/ps3.h>
+
+
+struct ps3_storage_region {
+	unsigned int id;
+	u64 start;
+	u64 size;
+};
+
+struct ps3_storage_device {
+	struct ps3_system_bus_device sbd;
+
+	struct ps3_dma_region dma_region;
+	unsigned int irq;
+	u64 blk_size;
+
+	u64 tag;
+	u64 lv1_status;
+	struct completion done;
+
+	unsigned long bounce_size;
+	void *bounce_buf;
+	u64 bounce_lpar;
+	dma_addr_t bounce_dma;
+
+	unsigned int num_regions;
+	unsigned long accessible_regions;
+	unsigned int region_idx;		/* first accessible region */
+	struct ps3_storage_region regions[0];	/* Must be last */
+};
+
+static inline struct ps3_storage_device *to_ps3_storage_device(struct device *dev)
+{
+	return container_of(dev, struct ps3_storage_device, sbd.core);
+}
+
+extern int ps3stor_setup(struct ps3_storage_device *dev,
+			 irq_handler_t handler);
+extern void ps3stor_teardown(struct ps3_storage_device *dev);
+extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+				      u64 start_sector, u64 sectors,
+				      int write);
+extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd,
+				u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+
+#endif /* _ASM_POWERPC_PS3STOR_H_ */
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
index 4ad77a1..13fccc5 100644
--- a/include/asm-powerpc/ptrace.h
+++ b/include/asm-powerpc/ptrace.h
@@ -92,6 +92,11 @@
 		set_thread_flag(TIF_NOERROR); \
 	} while(0)
 
+struct task_struct;
+extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
+extern int ptrace_put_reg(struct task_struct *task, int regno,
+			  unsigned long data);
+
 /*
  * We use the least-significant bit of the trap field to indicate
  * whether we have saved the full set of registers, or only a
@@ -158,9 +163,7 @@
 
 #define PT_NIP	32
 #define PT_MSR	33
-#ifdef __KERNEL__
 #define PT_ORIG_R3 34
-#endif
 #define PT_CTR	35
 #define PT_LNK	36
 #define PT_XER	37
@@ -169,11 +172,12 @@
 #define PT_MQ	39
 #else
 #define PT_SOFTE 39
+#endif
 #define PT_TRAP	40
 #define PT_DAR	41
 #define PT_DSISR 42
 #define PT_RESULT 43
-#endif
+#define PT_REGS_COUNT 44
 
 #define PT_FPR0	48	/* each FP reg occupies 2 slots in this space */
 
@@ -229,7 +233,17 @@
 #define PTRACE_GET_DEBUGREG	25
 #define PTRACE_SET_DEBUGREG	26
 
-/* Additional PTRACE requests implemented on PowerPC. */
+/* (new) PTRACE requests using the same numbers as x86 and the same
+ * argument ordering. Additionally, they support more registers too
+ */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_GETREGS64	  22
+#define PTRACE_SETREGS64	  23
+
+/* (old) PTRACE requests with inverted arguments */
 #define PPC_PTRACE_GETREGS	0x99	/* Get GPRs 0 - 31 */
 #define PPC_PTRACE_SETREGS	0x98	/* Set GPRs 0 - 31 */
 #define PPC_PTRACE_GETFPREGS	0x97	/* Get FPRs 0 - 31 */
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 749c7f9..281011e 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -453,6 +453,8 @@
 #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_SLOT	0x07000000UL /* SLOT bits (37-39) */
+#define   MMCRA_SLOT_SHIFT	24
 #define   MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
 #define   POWER6_MMCRA_SIHV   0x0000040000000000ULL
 #define   POWER6_MMCRA_SIPR   0x0000020000000000ULL
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 31d5054..eedc828 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -106,6 +106,14 @@
 struct spu_runqueue;
 struct device_node;
 
+enum spu_utilization_state {
+	SPU_UTIL_SYSTEM,
+	SPU_UTIL_USER,
+	SPU_UTIL_IOWAIT,
+	SPU_UTIL_IDLE,
+	SPU_UTIL_MAX
+};
+
 struct spu {
 	const char *name;
 	unsigned long local_store_phys;
@@ -156,6 +164,21 @@
 	u64 shadow_int_mask_RW[3];
 
 	struct sys_device sysdev;
+
+	struct {
+		/* protected by interrupt reentrancy */
+		enum spu_utilization_state utilization_state;
+		unsigned long tstamp;		/* time of last ctx switch */
+		unsigned long times[SPU_UTIL_MAX];
+		unsigned long long vol_ctx_switch;
+		unsigned long long invol_ctx_switch;
+		unsigned long long min_flt;
+		unsigned long long maj_flt;
+		unsigned long long hash_flt;
+		unsigned long long slb_flt;
+		unsigned long long class2_intr;
+		unsigned long long libassist;
+	} stats;
 };
 
 struct spu *spu_alloc(void);
@@ -448,6 +471,7 @@
 #define MFC_STATE1_PROBLEM_STATE_MASK		0x08ull
 #define MFC_STATE1_RELOCATE_MASK		0x10ull
 #define MFC_STATE1_MASTER_RUN_CONTROL_MASK	0x20ull
+#define MFC_STATE1_TABLE_SEARCH_MASK		0x40ull
 	u64 mfc_lpid_RW;					/* 0x008 */
 	u64 spu_idr_RW;						/* 0x010 */
 	u64 mfc_vr_RO;						/* 0x018 */
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h
index c2fe79d..b3ca41f 100644
--- a/include/asm-powerpc/syscalls.h
+++ b/include/asm-powerpc/syscalls.h
@@ -43,16 +43,9 @@
 
 asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
 		size_t sigsetsize);
-
-#ifndef __powerpc64__
-asmlinkage long sys_sigaltstack(const stack_t __user *uss,
-		stack_t __user *uoss, int r5, int r6, int r7, int r8,
-		struct pt_regs *regs);
-#else /* __powerpc64__ */
 asmlinkage long sys_sigaltstack(const stack_t __user *uss,
 		stack_t __user *uoss, unsigned long r5, unsigned long r6,
 		unsigned long r7, unsigned long r8, struct pt_regs *regs);
-#endif /* __powerpc64__ */
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_POWERPC_SYSCALLS_H */
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 09621f6..32aa42b 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -43,7 +43,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()	barrier()
@@ -559,5 +559,7 @@
 extern void account_system_vtime(struct task_struct *);
 #endif
 
+extern struct dentry *powerpc_debugfs_root;
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SYSTEM_H */
diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h
index 5e79198..6698188 100644
--- a/include/asm-powerpc/termbits.h
+++ b/include/asm-powerpc/termbits.h
@@ -152,6 +152,10 @@
 #define B3000000  00034
 #define B3500000  00035
 #define B4000000  00036
+#define   BOTHER  00037
+
+#define CIBAUD	077600000
+#define IBSHIFT	16		/* Shift from CBAUD to CIBAUD */
 
 #define CSIZE	00001400
 #define   CS5	00000000
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 3f32ca8..9d9aeca 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -113,8 +113,8 @@
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_32BIT		5	/* 32 bit binary */
-#define TIF_RUNLATCH		6	/* Is the runlatch enabled? */
-#define TIF_ABI_PENDING		7	/* 32/64 bit switch needed */
+#define TIF_PERFMON_WORK	6	/* work for pfm_handle_work() */
+#define TIF_PERFMON_CTXSW	7	/* perfmon needs ctxsw calls */
 #define TIF_SYSCALL_AUDIT	8	/* syscall auditing active */
 #define TIF_SINGLESTEP		9	/* singlestepping active */
 #define TIF_MEMDIE		10
@@ -123,6 +123,8 @@
 #define TIF_NOERROR		14	/* Force successful syscall return */
 #define TIF_RESTORE_SIGMASK	15	/* Restore signal mask in do_signal */
 #define TIF_FREEZE		16	/* Freezing for suspend */
+#define TIF_RUNLATCH		17	/* Is the runlatch enabled? */
+#define TIF_ABI_PENDING		18	/* 32/64 bit switch needed */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -131,8 +133,8 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_32BIT		(1<<TIF_32BIT)
-#define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
-#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+#define _TIF_PERFMON_WORK	(1<<TIF_PERFMON_WORK)
+#define _TIF_PERFMON_CTXSW	(1<<TIF_PERFMON_CTXSW)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
@@ -140,6 +142,8 @@
 #define _TIF_NOERROR		(1<<TIF_NOERROR)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
+#define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
+#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index 3fd57c0..d7f5ddf 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -232,7 +232,7 @@
 #define account_process_vtime(tsk)		do { } while (0)
 #endif
 
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING)
 extern void calculate_steal_time(void);
 extern void snapshot_timebases(void);
 #else
@@ -240,5 +240,7 @@
 #define snapshot_timebases()			do { } while (0)
 #endif
 
+extern void iSeries_time_init_early(void);
+
 #endif /* __KERNEL__ */
 #endif /* __POWERPC_TIME_H */
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index 86e6266..99a0439 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -155,6 +155,11 @@
 {
 }
 
+/* Private function for use by PCI IO mapping code */
+extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+				     unsigned long end);
+
+
 #endif
 
 /*
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 9d0ce9f..c159315 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -533,9 +533,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
-static inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_EXEC; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
@@ -543,21 +541,13 @@
 static inline void pte_uncache(pte_t pte)       { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)         { pte_val(pte) &= ~_PAGE_NO_CACHE; }
 
-static inline pte_t pte_rdprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_EXEC; return pte; }
 static inline pte_t pte_mkclean(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
 static inline pte_t pte_mkold(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 
-static inline pte_t pte_mkread(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte) {
 	pte_val(pte) |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte) {
@@ -664,13 +654,6 @@
 #define ptep_test_and_clear_young(__vma, __addr, __ptep) \
 	__ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
 
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
-					    unsigned long addr, pte_t *ptep)
-{
-	return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
-}
-
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 				       pte_t *ptep)
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
index 296f4f1..7f4ad62 100644
--- a/include/asm-s390/compat.h
+++ b/include/asm-s390/compat.h
@@ -60,8 +60,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-s390/dma-mapping.h b/include/asm-s390/dma-mapping.h
deleted file mode 100644
index 3f8c12f..0000000
--- a/include/asm-s390/dma-mapping.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- *  include/asm-s390/dma-mapping.h
- *
- *  S390 version
- *
- *  This file exists so that #include <dma-mapping.h> doesn't break anything.
- */
-
-#ifndef _ASM_DMA_MAPPING_H
-#define _ASM_DMA_MAPPING_H
-
-#endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-s390/fb.h b/include/asm-s390/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-s390/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 05ea6f1..f326451 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -64,7 +64,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 0a307bb2..3208dc6 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -530,14 +530,6 @@
 	return 0;
 }
 
-static inline int pte_read(pte_t pte)
-{
-	/* All pages are readable since we don't use the fetch
-	 * protection bit in the storage key.
-	 */
-	return 1;
-}
-
 /*
  * pgd/pmd/pte modification functions
  */
@@ -677,19 +669,6 @@
 	return ptep_test_and_clear_young(vma, address, ptep);
 }
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	return 0;
-}
-
-static inline int
-ptep_clear_flush_dirty(struct vm_area_struct *vma,
-			unsigned long address, pte_t *ptep)
-{
-	/* No need to flush TLB; bits are in storage key */
-	return ptep_test_and_clear_dirty(vma, address, ptep);
-}
-
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t pte = *ptep;
@@ -715,16 +694,19 @@
 	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
 }
 
-static inline pte_t
-ptep_clear_flush(struct vm_area_struct *vma,
-		 unsigned long address, pte_t *ptep)
+static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
+{
+	__ptep_ipte(address, ptep);
+	ptep = get_shadow_pte(ptep);
+	if (ptep)
+		__ptep_ipte(address, ptep);
+}
+
+static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
+				     unsigned long address, pte_t *ptep)
 {
 	pte_t pte = *ptep;
-	pte_t *shadow_pte = get_shadow_pte(ptep);
-
-	__ptep_ipte(address, ptep);
-	if (shadow_pte)
-		__ptep_ipte(address, shadow_pte);
+	ptep_invalidate(address, ptep);
 	return pte;
 }
 
@@ -734,21 +716,14 @@
 	set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
 }
 
-static inline void
-ptep_establish(struct vm_area_struct *vma, 
-	       unsigned long address, pte_t *ptep,
-	       pte_t entry)
-{
-	ptep_clear_flush(vma, address, ptep);
-	set_pte(ptep, entry);
-}
-
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-({									  \
-	int __changed = !pte_same(*(__ptep), __entry);			  \
-	if (__changed)							  \
-		ptep_establish(__vma, __address, __ptep, __entry);	  \
-	__changed;							  \
+#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty)	\
+({									\
+	int __changed = !pte_same(*(__ptep), __entry);			\
+	if (__changed) {						\
+		ptep_invalidate(__addr, __ptep);			\
+		set_pte_at((__vma)->vm_mm, __addr, __ptep, __entry);	\
+	}								\
+	__changed;							\
 })
 
 /*
@@ -948,12 +923,9 @@
 #define __HAVE_ARCH_MEMMAP_INIT
 extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
 
-#define __HAVE_ARCH_PTEP_ESTABLISH
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
index 5a117ec..aeee8da 100644
--- a/include/asm-sh/bugs.h
+++ b/include/asm-sh/bugs.h
@@ -22,7 +22,7 @@
 	current_cpu_data.loops_per_jiffy = loops_per_jiffy;
 
 	switch (current_cpu_data.type) {
-	case CPU_SH7604 ... CPU_SH7619:
+	case CPU_SH7619:
 		*p++ = '2';
 		break;
 	case CPU_SH7206:
@@ -35,7 +35,7 @@
 	case CPU_SH7750 ... CPU_SH4_501:
 		*p++ = '4';
 		break;
-	case CPU_SH7770 ... CPU_SH7785:
+	case CPU_SH7770 ... CPU_SHX3:
 		*p++ = '4';
 		*p++ = 'a';
 		break;
diff --git a/include/asm-sh/cache.h b/include/asm-sh/cache.h
index 9a3cb6b..7a18649 100644
--- a/include/asm-sh/cache.h
+++ b/include/asm-sh/cache.h
@@ -9,6 +9,7 @@
 #define __ASM_SH_CACHE_H
 #ifdef __KERNEL__
 
+#include <linux/init.h>
 #include <asm/cpu/cache.h>
 
 #define SH_CACHE_VALID		1
@@ -48,6 +49,9 @@
 
 	unsigned long flags;
 };
+
+int __init detect_cpu_and_cache_system(void);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHE_H */
diff --git a/include/asm-sh/cpu-sh2/cache.h b/include/asm-sh/cpu-sh2/cache.h
index 20b9796..f02ba7a 100644
--- a/include/asm-sh/cpu-sh2/cache.h
+++ b/include/asm-sh/cpu-sh2/cache.h
@@ -12,23 +12,7 @@
 
 #define L1_CACHE_SHIFT	4
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7604)
-#define CCR		0xfffffe92	/* Address of Cache Control Register */
-
-#define CCR_CACHE_CE	0x01	/* Cache enable */
-#define CCR_CACHE_ID	0x02	/* Instruction Replacement disable */
-#define CCR_CACHE_OD	0x04	/* Data Replacement disable */
-#define CCR_CACHE_TW	0x08	/* Two-way mode */
-#define CCR_CACHE_CP	0x10	/* Cache purge */
-
-#define CACHE_OC_ADDRESS_ARRAY	0x60000000
-
-#define CCR_CACHE_ENABLE	CCR_CACHE_CE
-#define CCR_CACHE_INVALIDATE	CCR_CACHE_CP
-#define CCR_CACHE_ORA		CCR_CACHE_TW
-#define CCR_CACHE_WT		0x00	/* SH-2 is _always_ write-through */
-
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
 #define CCR1		0xffffffec
 #define CCR		CCR1
 
@@ -49,5 +33,5 @@
 #define CCR_CACHE_ENABLE	CCR_CACHE_CE
 #define CCR_CACHE_INVALIDATE	CCR_CACHE_CF
 #endif
-#endif /* __ASM_CPU_SH2_CACHE_H */
 
+#endif /* __ASM_CPU_SH2_CACHE_H */
diff --git a/include/asm-sh/cpu-sh3/timer.h b/include/asm-sh/cpu-sh3/timer.h
index b2394cf..4928b08 100644
--- a/include/asm-sh/cpu-sh3/timer.h
+++ b/include/asm-sh/cpu-sh3/timer.h
@@ -29,7 +29,7 @@
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
-#define TMU_TSTR	0xa412fe92	/* Byte access */
+#define TMU_012_TSTR	0xa412fe92	/* Byte access */
 
 #define TMU0_TCOR	0xa412fe94	/* Long access */
 #define TMU0_TCNT	0xa412fe98	/* Long access */
@@ -44,7 +44,7 @@
 #define TMU2_TCR	0xa412feb4	/* Word access */
 
 #else
-#define TMU_TSTR	0xfffffe92	/* Byte access */
+#define TMU_012_TSTR	0xfffffe92	/* Byte access */
 
 #define TMU0_TCOR	0xfffffe94	/* Long access */
 #define TMU0_TCNT	0xfffffe98	/* Long access */
diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
index 39f41fc..026025b 100644
--- a/include/asm-sh/cpu-sh4/freq.h
+++ b/include/asm-sh/cpu-sh4/freq.h
@@ -22,6 +22,8 @@
 #define FRQCR0			0xffc80000
 #define FRQCR1			0xffc80004
 #define FRQMR1			0xffc80014
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+#define FRQCR			0xffc00014
 #else
 #define FRQCR			0xffc00000
 #define FRQCR_PSTBY		0x0200
diff --git a/include/asm-sh/cpu-sh4/timer.h b/include/asm-sh/cpu-sh4/timer.h
index 8a4af12..d1e796b 100644
--- a/include/asm-sh/cpu-sh4/timer.h
+++ b/include/asm-sh/cpu-sh4/timer.h
@@ -1,7 +1,7 @@
 /*
  * include/asm-sh/cpu-sh4/timer.h
  *
- * Copyright (C) 2004 Lineo Solutions, Inc. 
+ * Copyright (C) 2004 Lineo Solutions, Inc.
  *
  * 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
@@ -16,36 +16,45 @@
  *	SH7750S/SH7750R
  *	SH7751/SH7751R
  *	SH7760
+ *	SH-X3
  * ---------------------------------------------------------------------------
  */
-
-#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define TMU_TOCR        0xffd80000      /* Byte access */
+#ifdef CONFIG_CPU_SUBTYPE_SHX3
+#define TMU_012_BASE	0xffc10000
+#define TMU_345_BASE	0xffc20000
+#else
+#define TMU_012_BASE	0xffd80000
+#define TMU_345_BASE	0xfe100000
 #endif
-#define TMU_TSTR        0xffd80004      /* Byte access */
 
-#define TMU0_TCOR       0xffd80008      /* Long access */
-#define TMU0_TCNT       0xffd8000c      /* Long access */
-#define TMU0_TCR        0xffd80010      /* Word access */
+#define TMU_TOCR	TMU_012_BASE	/* Not supported on all CPUs */
 
-#define TMU1_TCOR       0xffd80014      /* Long access */
-#define TMU1_TCNT       0xffd80018      /* Long access */
-#define TMU1_TCR        0xffd8001c      /* Word access */
+#define TMU_012_TSTR	(TMU_012_BASE + 0x04)
+#define TMU_345_TSTR	(TMU_345_BASE + 0x04)
 
-#define TMU2_TCOR       0xffd80020      /* Long access */
-#define TMU2_TCNT       0xffd80024      /* Long access */
-#define TMU2_TCR        0xffd80028      /* Word access */
-#define TMU2_TCPR	0xffd8002c	/* Long access */
+#define TMU0_TCOR	(TMU_012_BASE + 0x08)
+#define TMU0_TCNT	(TMU_012_BASE + 0x0c)
+#define TMU0_TCR	(TMU_012_BASE + 0x10)
 
-#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define TMU3_TCOR       0xfe100008      /* Long access */
-#define TMU3_TCNT       0xfe10000c      /* Long access */
-#define TMU3_TCR        0xfe100010      /* Word access */
+#define TMU1_TCOR       (TMU_012_BASE + 0x14)
+#define TMU1_TCNT       (TMU_012_BASE + 0x18)
+#define TMU1_TCR        (TMU_012_BASE + 0x1c)
 
-#define TMU4_TCOR       0xfe100014      /* Long access */
-#define TMU4_TCNT       0xfe100018      /* Long access */
-#define TMU4_TCR        0xfe10001c      /* Word access */
-#endif
+#define TMU2_TCOR       (TMU_012_BASE + 0x20)
+#define TMU2_TCNT       (TMU_012_BASE + 0x24)
+#define TMU2_TCR	(TMU_012_BASE + 0x28)
+#define TMU2_TCPR	(TMU_012_BASE + 0x2c)
+
+#define TMU3_TCOR	(TMU_345_BASE + 0x08)
+#define TMU3_TCNT	(TMU_345_BASE + 0x0c)
+#define TMU3_TCR	(TMU_345_BASE + 0x10)
+
+#define TMU4_TCOR	(TMU_345_BASE + 0x14)
+#define TMU4_TCNT	(TMU_345_BASE + 0x18)
+#define TMU4_TCR	(TMU_345_BASE + 0x1c)
+
+#define TMU5_TCOR	(TMU_345_BASE + 0x20)
+#define TMU5_TCNT	(TMU_345_BASE + 0x24)
+#define TMU5_TCR	(TMU_345_BASE + 0x28)
 
 #endif /* __ASM_CPU_SH4_TIMER_H */
-
diff --git a/include/asm-sh/fb.h b/include/asm-sh/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-sh/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sh/futex-irq.h b/include/asm-sh/futex-irq.h
new file mode 100644
index 0000000..a9f16a7
--- /dev/null
+++ b/include/asm-sh/futex-irq.h
@@ -0,0 +1,111 @@
+#ifndef __ASM_SH_FUTEX_IRQ_H
+#define __ASM_SH_FUTEX_IRQ_H
+
+#include <asm/system.h>
+
+static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval + oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+					  int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval | oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval & oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval ^ oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
+						   int oldval, int newval)
+{
+	unsigned long flags;
+	int ret, prev = 0;
+
+	local_irq_save(flags);
+
+	ret = get_user(prev, uaddr);
+	if (!ret && oldval == prev)
+		ret = put_user(newval, uaddr);
+
+	local_irq_restore(flags);
+
+	if (ret)
+		return ret;
+
+	return prev;
+}
+
+#endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h
index 6a332a9..74ed368 100644
--- a/include/asm-sh/futex.h
+++ b/include/asm-sh/futex.h
@@ -1,6 +1,77 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef __ASM_SH_FUTEX_H
+#define __ASM_SH_FUTEX_H
 
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
 
-#endif
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+/* XXX: UP variants, fix for SH-4A and SMP.. */
+#include <asm/futex-irq.h>
+
+static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret;
+
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	pagefault_disable();
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_ADD:
+		ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_OR:
+		ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_ANDN:
+		ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_XOR:
+		ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
+	pagefault_enable();
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+		default: ret = -ENOSYS;
+		}
+	}
+
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_FUTEX_H */
diff --git a/include/asm-sh/hd64461.h b/include/asm-sh/hd64461.h
index 27e5c34..4dd8592 100644
--- a/include/asm-sh/hd64461.h
+++ b/include/asm-sh/hd64461.h
@@ -1,200 +1,241 @@
 #ifndef __ASM_SH_HD64461
 #define __ASM_SH_HD64461
 /*
- *	$Id: hd64461.h,v 1.5 2004/03/16 00:07:51 lethal Exp $
+ *	Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
+ *	Copyright (C) 2004 Paul Mundt
  *	Copyright (C) 2000 YAEGASHI Takeshi
- *	Hitachi HD64461 companion chip support
+ *
+ *		Hitachi HD64461 companion chip support
+ *	(please note manual reference 0x10000000 = 0xb0000000)
  */
 
 /* Constants for PCMCIA mappings */
-#define HD64461_PCC_WINDOW	0x01000000
+#define	HD64461_PCC_WINDOW	0x01000000
 
-#define HD64461_PCC0_BASE	0xb8000000	/* area 6 */
-#define HD64461_PCC0_ATTR	(HD64461_PCC0_BASE)
-#define HD64461_PCC0_COMM	(HD64461_PCC0_BASE+HD64461_PCC_WINDOW)
-#define HD64461_PCC0_IO		(HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)
+/* Area 6 - Slot 0 - memory and/or IO card */
+#define	HD64461_PCC0_BASE	(CONFIG_HD64461_IOBASE + 0x8000000)
+#define	HD64461_PCC0_ATTR	(HD64461_PCC0_BASE)				/* 0xb80000000 */
+#define	HD64461_PCC0_COMM	(HD64461_PCC0_BASE+HD64461_PCC_WINDOW)		/* 0xb90000000 */
+#define	HD64461_PCC0_IO		(HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)	/* 0xba0000000 */
 
-#define HD64461_PCC1_BASE	0xb4000000	/* area 5 */
-#define HD64461_PCC1_ATTR	(HD64461_PCC1_BASE)
-#define HD64461_PCC1_COMM	(HD64461_PCC1_BASE+HD64461_PCC_WINDOW)
+/* Area 5 - Slot 1 - memory card only */
+#define	HD64461_PCC1_BASE	(CONFIG_HD64461_IOBASE + 0x4000000)
+#define	HD64461_PCC1_ATTR	(HD64461_PCC1_BASE)				/* 0xb4000000 */
+#define	HD64461_PCC1_COMM	(HD64461_PCC1_BASE+HD64461_PCC_WINDOW)		/* 0xb5000000 */
 
-#define HD64461_STBCR	0x10000
-#define HD64461_STBCR_CKIO_STBY			0x2000
-#define HD64461_STBCR_SAFECKE_IST		0x1000
-#define HD64461_STBCR_SLCKE_IST			0x0800
-#define HD64461_STBCR_SAFECKE_OST		0x0400
-#define HD64461_STBCR_SLCKE_OST			0x0200
-#define HD64461_STBCR_SMIAST			0x0100
-#define HD64461_STBCR_SLCDST			0x0080
-#define HD64461_STBCR_SPC0ST			0x0040
-#define HD64461_STBCR_SPC1ST			0x0020
-#define HD64461_STBCR_SAFEST			0x0010
-#define HD64461_STBCR_STM0ST			0x0008
-#define HD64461_STBCR_STM1ST			0x0004
-#define HD64461_STBCR_SIRST				0x0002
-#define HD64461_STBCR_SURTST			0x0001
+/* Standby Control Register for HD64461 */
+#define	HD64461_STBCR			CONFIG_HD64461_IOBASE
+#define	HD64461_STBCR_CKIO_STBY		0x2000
+#define	HD64461_STBCR_SAFECKE_IST	0x1000
+#define	HD64461_STBCR_SLCKE_IST		0x0800
+#define	HD64461_STBCR_SAFECKE_OST	0x0400
+#define	HD64461_STBCR_SLCKE_OST		0x0200
+#define	HD64461_STBCR_SMIAST		0x0100
+#define	HD64461_STBCR_SLCDST		0x0080
+#define	HD64461_STBCR_SPC0ST		0x0040
+#define	HD64461_STBCR_SPC1ST		0x0020
+#define	HD64461_STBCR_SAFEST		0x0010
+#define	HD64461_STBCR_STM0ST		0x0008
+#define	HD64461_STBCR_STM1ST		0x0004
+#define	HD64461_STBCR_SIRST		0x0002
+#define	HD64461_STBCR_SURTST		0x0001
 
-#define HD64461_SYSCR	0x10002
-#define HD64461_SCPUCR	0x10004
+/* System Configuration Register */
+#define	HD64461_SYSCR		(CONFIG_HD64461_IOBASE + 0x02)
 
-#define HD64461_LCDCBAR		0x11000
-#define HD64461_LCDCLOR		0x11002
-#define HD64461_LCDCCR		0x11004
-#define HD64461_LCDCCR_STBACK	0x0400
-#define HD64461_LCDCCR_STREQ	0x0100
-#define HD64461_LCDCCR_MOFF	0x0080
-#define HD64461_LCDCCR_REFSEL	0x0040
-#define HD64461_LCDCCR_EPON	0x0020
-#define HD64461_LCDCCR_SPON	0x0010
+/* CPU Data Bus Control Register */
+#define	HD64461_SCPUCR		(CONFIG_HD64461_IOBASE + 0x04)
 
-#define	HD64461_LDR1		0x11010
-#define	HD64461_LDR1_DON	0x01
-#define	HD64461_LDR1_DINV	0x80
+/* Base Adress Register */
+#define	HD64461_LCDCBAR		(CONFIG_HD64461_IOBASE + 0x1000)
 
-#define	HD64461_LDR2		0x11012
-#define	HD64461_LDHNCR		0x11014
-#define	HD64461_LDHNSR		0x11016
-#define HD64461_LDVNTR		0x11018
-#define HD64461_LDVNDR		0x1101a
-#define HD64461_LDVSPR		0x1101c
-#define HD64461_LDR3		0x1101e
+/* Line increment adress */
+#define	HD64461_LCDCLOR		(CONFIG_HD64461_IOBASE + 0x1002)
 
-#define HD64461_CPTWAR		0x11030
-#define HD64461_CPTWDR		0x11032
-#define HD64461_CPTRAR		0x11034
-#define HD64461_CPTRDR		0x11036
+/* Controls LCD controller */
+#define	HD64461_LCDCCR		(CONFIG_HD64461_IOBASE + 0x1004)
 
-#define HD64461_GRDOR		0x11040
-#define HD64461_GRSCR		0x11042
-#define HD64461_GRCFGR		0x11044
-#define HD64461_GRCFGR_ACCSTATUS		0x10
-#define HD64461_GRCFGR_ACCRESET			0x08
-#define HD64461_GRCFGR_ACCSTART_BITBLT	0x06
-#define HD64461_GRCFGR_ACCSTART_LINE	0x04
-#define HD64461_GRCFGR_COLORDEPTH16		0x01
+/* LCCDR control bits */
+#define	HD64461_LCDCCR_STBACK	0x0400	/* Standby Back */
+#define	HD64461_LCDCCR_STREQ	0x0100	/* Standby Request */
+#define	HD64461_LCDCCR_MOFF	0x0080	/* Memory Off */
+#define	HD64461_LCDCCR_REFSEL	0x0040	/* Refresh Select */
+#define	HD64461_LCDCCR_EPON	0x0020	/* End Power On */
+#define	HD64461_LCDCCR_SPON	0x0010	/* Start Power On */
 
-#define HD64461_LNSARH		0x11046
-#define HD64461_LNSARL		0x11048
-#define HD64461_LNAXLR		0x1104a
-#define HD64461_LNDGR		0x1104c
-#define HD64461_LNAXR		0x1104e
-#define HD64461_LNERTR		0x11050
-#define HD64461_LNMDR		0x11052
-#define HD64461_BBTSSARH	0x11054
-#define HD64461_BBTSSARL	0x11056
-#define HD64461_BBTDSARH	0x11058
-#define HD64461_BBTDSARL	0x1105a
-#define HD64461_BBTDWR		0x1105c
-#define HD64461_BBTDHR		0x1105e
-#define HD64461_BBTPARH		0x11060
-#define HD64461_BBTPARL		0x11062
-#define HD64461_BBTMARH		0x11064
-#define HD64461_BBTMARL		0x11066
-#define HD64461_BBTROPR		0x11068
-#define HD64461_BBTMDR		0x1106a
+/* Controls LCD (1) */
+#define	HD64461_LDR1		(CONFIG_HD64461_IOBASE + 0x1010)
+#define	HD64461_LDR1_DON	0x01	/* Display On */
+#define	HD64461_LDR1_DINV	0x80	/* Display Invert */
+
+/* Controls LCD (2) */
+#define	HD64461_LDR2		(CONFIG_HD64461_IOBASE + 0x1012)
+#define	HD64461_LDHNCR		(CONFIG_HD64461_IOBASE + 0x1014)	/* Number of horizontal characters */
+#define	HD64461_LDHNSR		(CONFIG_HD64461_IOBASE + 0x1016)	/* Specify output start position + width of CL1 */
+#define	HD64461_LDVNTR		(CONFIG_HD64461_IOBASE + 0x1018)	/* Specify total vertical lines */
+#define	HD64461_LDVNDR		(CONFIG_HD64461_IOBASE + 0x101a)	/* specify number of display vertical lines */
+#define	HD64461_LDVSPR		(CONFIG_HD64461_IOBASE + 0x101c)	/* specify vertical synchronization pos and AC nr */
+
+/* Controls LCD (3) */
+#define	HD64461_LDR3		(CONFIG_HD64461_IOBASE + 0x101e)
+
+/* Palette Registers */
+#define	HD64461_CPTWAR		(CONFIG_HD64461_IOBASE + 0x1030)	/* Color Palette Write Adress Register */
+#define	HD64461_CPTWDR		(CONFIG_HD64461_IOBASE + 0x1032)	/* Color Palette Write Data Register */
+#define	HD64461_CPTRAR		(CONFIG_HD64461_IOBASE + 0x1034)	/* Color Palette Read Adress Register */
+#define	HD64461_CPTRDR		(CONFIG_HD64461_IOBASE + 0x1036)	/* Color Palette Read Data Register */
+
+#define	HD64461_GRDOR		(CONFIG_HD64461_IOBASE + 0x1040)	/* Display Resolution Offset Register */
+#define	HD64461_GRSCR		(CONFIG_HD64461_IOBASE + 0x1042)	/* Solid Color Register */
+#define	HD64461_GRCFGR		(CONFIG_HD64461_IOBASE + 0x1044)	/* Accelerator Configuration Register */
+
+#define	HD64461_GRCFGR_ACCSTATUS	0x10	/* Accelerator Status */
+#define	HD64461_GRCFGR_ACCRESET		0x08	/* Accelerator Reset */
+#define	HD64461_GRCFGR_ACCSTART_BITBLT	0x06	/* Accelerator Start BITBLT */
+#define	HD64461_GRCFGR_ACCSTART_LINE	0x04	/* Accelerator Start Line Drawing */
+#define	HD64461_GRCFGR_COLORDEPTH16	0x01	/* Sets Colordepth 16 for Accelerator */
+#define	HD64461_GRCFGR_COLORDEPTH8	0x01	/* Sets Colordepth 8 for Accelerator */
+
+/* Line Drawing Registers */
+#define	HD64461_LNSARH		(CONFIG_HD64461_IOBASE + 0x1046)	/* Line Start Adress Register (H) */
+#define	HD64461_LNSARL		(CONFIG_HD64461_IOBASE + 0x1048)	/* Line Start Adress Register (L) */
+#define	HD64461_LNAXLR		(CONFIG_HD64461_IOBASE + 0x104a)	/* Axis Pixel Length Register */
+#define	HD64461_LNDGR		(CONFIG_HD64461_IOBASE + 0x104c)	/* Diagonal Register */
+#define	HD64461_LNAXR		(CONFIG_HD64461_IOBASE + 0x104e)	/* Axial Register */
+#define	HD64461_LNERTR		(CONFIG_HD64461_IOBASE + 0x1050)	/* Start Error Term Register */
+#define	HD64461_LNMDR		(CONFIG_HD64461_IOBASE + 0x1052)	/* Line Mode Register */
+
+/* BitBLT Registers */
+#define	HD64461_BBTSSARH	(CONFIG_HD64461_IOBASE + 0x1054)	/* Source Start Adress Register (H) */
+#define	HD64461_BBTSSARL	(CONFIG_HD64461_IOBASE + 0x1056)	/* Source Start Adress Register (L) */
+#define	HD64461_BBTDSARH	(CONFIG_HD64461_IOBASE + 0x1058)	/* Destination Start Adress Register (H) */
+#define	HD64461_BBTDSARL	(CONFIG_HD64461_IOBASE + 0x105a)	/* Destination Start Adress Register (L) */
+#define	HD64461_BBTDWR		(CONFIG_HD64461_IOBASE + 0x105c)	/* Destination Block Width Register */
+#define	HD64461_BBTDHR		(CONFIG_HD64461_IOBASE + 0x105e)	/* Destination Block Height Register */
+#define	HD64461_BBTPARH		(CONFIG_HD64461_IOBASE + 0x1060)	/* Pattern Start Adress Register (H) */
+#define	HD64461_BBTPARL		(CONFIG_HD64461_IOBASE + 0x1062)	/* Pattern Start Adress Register (L) */
+#define	HD64461_BBTMARH		(CONFIG_HD64461_IOBASE + 0x1064)	/* Mask Start Adress Register (H) */
+#define	HD64461_BBTMARL		(CONFIG_HD64461_IOBASE + 0x1066)	/* Mask Start Adress Register (L) */
+#define	HD64461_BBTROPR		(CONFIG_HD64461_IOBASE + 0x1068)	/* ROP Register */
+#define	HD64461_BBTMDR		(CONFIG_HD64461_IOBASE + 0x106a)	/* BitBLT Mode Register */
 
 /* PC Card Controller Registers */
-#define HD64461_PCC0ISR         0x12000 /* socket 0 interface status */
-#define HD64461_PCC0GCR         0x12002 /* socket 0 general control */
-#define HD64461_PCC0CSCR        0x12004 /* socket 0 card status change */
-#define HD64461_PCC0CSCIER      0x12006 /* socket 0 card status change interrupt enable */
-#define HD64461_PCC0SCR         0x12008 /* socket 0 software control */
-#define HD64461_PCC1ISR         0x12010 /* socket 1 interface status */
-#define HD64461_PCC1GCR         0x12012 /* socket 1 general control */
-#define HD64461_PCC1CSCR        0x12014 /* socket 1 card status change */
-#define HD64461_PCC1CSCIER      0x12016 /* socket 1 card status change interrupt enable */
-#define HD64461_PCC1SCR         0x12018 /* socket 1 software control */
+/* Maps to Physical Area 6 */
+#define	HD64461_PCC0ISR		(CONFIG_HD64461_IOBASE + 0x2000)	/* socket 0 interface status */
+#define	HD64461_PCC0GCR		(CONFIG_HD64461_IOBASE + 0x2002)	/* socket 0 general control */
+#define	HD64461_PCC0CSCR	(CONFIG_HD64461_IOBASE + 0x2004)	/* socket 0 card status change */
+#define	HD64461_PCC0CSCIER	(CONFIG_HD64461_IOBASE + 0x2006)	/* socket 0 card status change interrupt enable */
+#define	HD64461_PCC0SCR		(CONFIG_HD64461_IOBASE + 0x2008)	/* socket 0 software control */
+/* Maps to Physical Area 5 */
+#define	HD64461_PCC1ISR		(CONFIG_HD64461_IOBASE + 0x2010)	/* socket 1 interface status */
+#define	HD64461_PCC1GCR		(CONFIG_HD64461_IOBASE + 0x2012)	/* socket 1 general control */
+#define	HD64461_PCC1CSCR	(CONFIG_HD64461_IOBASE + 0x2014)	/* socket 1 card status change */
+#define	HD64461_PCC1CSCIER	(CONFIG_HD64461_IOBASE + 0x2016)	/* socket 1 card status change interrupt enable */
+#define	HD64461_PCC1SCR		(CONFIG_HD64461_IOBASE + 0x2018)	/* socket 1 software control */
 
 /* PCC Interface Status Register */
-#define HD64461_PCCISR_READY		0x80	/* card ready */
-#define HD64461_PCCISR_MWP		0x40	/* card write-protected */
-#define HD64461_PCCISR_VS2		0x20	/* voltage select pin 2 */
-#define HD64461_PCCISR_VS1		0x10	/* voltage select pin 1 */
-#define HD64461_PCCISR_CD2		0x08	/* card detect 2 */
-#define HD64461_PCCISR_CD1		0x04	/* card detect 1 */
-#define HD64461_PCCISR_BVD2		0x02	/* battery 1 */
-#define HD64461_PCCISR_BVD1		0x01	/* battery 1 */
+#define	HD64461_PCCISR_READY		0x80	/* card ready */
+#define	HD64461_PCCISR_MWP		0x40	/* card write-protected */
+#define	HD64461_PCCISR_VS2		0x20	/* voltage select pin 2 */
+#define	HD64461_PCCISR_VS1		0x10	/* voltage select pin 1 */
+#define	HD64461_PCCISR_CD2		0x08	/* card detect 2 */
+#define	HD64461_PCCISR_CD1		0x04	/* card detect 1 */
+#define	HD64461_PCCISR_BVD2		0x02	/* battery 1 */
+#define	HD64461_PCCISR_BVD1		0x01	/* battery 1 */
 
-#define HD64461_PCCISR_PCD_MASK		0x0c    /* card detect */
-#define HD64461_PCCISR_BVD_MASK		0x03    /* battery voltage */
-#define HD64461_PCCISR_BVD_BATGOOD	0x03    /* battery good */
-#define HD64461_PCCISR_BVD_BATWARN	0x01    /* battery low warning */
-#define HD64461_PCCISR_BVD_BATDEAD1	0x02    /* battery dead */
-#define HD64461_PCCISR_BVD_BATDEAD2	0x00    /* battery dead */
+#define	HD64461_PCCISR_PCD_MASK		0x0c	/* card detect */
+#define	HD64461_PCCISR_BVD_MASK		0x03	/* battery voltage */
+#define	HD64461_PCCISR_BVD_BATGOOD	0x03	/* battery good */
+#define	HD64461_PCCISR_BVD_BATWARN	0x01	/* battery low warning */
+#define	HD64461_PCCISR_BVD_BATDEAD1	0x02	/* battery dead */
+#define	HD64461_PCCISR_BVD_BATDEAD2	0x00	/* battery dead */
 
 /* PCC General Control Register */
-#define HD64461_PCCGCR_DRVE		0x80    /* output drive */
-#define HD64461_PCCGCR_PCCR		0x40    /* PC card reset */
-#define HD64461_PCCGCR_PCCT		0x20    /* PC card type, 1=IO&mem, 0=mem */
-#define HD64461_PCCGCR_VCC0		0x10    /* voltage control pin VCC0SEL0 */
-#define HD64461_PCCGCR_PMMOD		0x08    /* memory mode */
-#define HD64461_PCCGCR_PA25		0x04    /* pin A25 */
-#define HD64461_PCCGCR_PA24		0x02    /* pin A24 */
-#define HD64461_PCCGCR_REG		0x01    /* pin PCC0REG# */
+#define	HD64461_PCCGCR_DRVE		0x80	/* output drive */
+#define	HD64461_PCCGCR_PCCR		0x40	/* PC card reset */
+#define	HD64461_PCCGCR_PCCT		0x20	/* PC card type, 1=IO&mem, 0=mem */
+#define	HD64461_PCCGCR_VCC0		0x10	/* voltage control pin VCC0SEL0 */
+#define	HD64461_PCCGCR_PMMOD		0x08	/* memory mode */
+#define	HD64461_PCCGCR_PA25		0x04	/* pin A25 */
+#define	HD64461_PCCGCR_PA24		0x02	/* pin A24 */
+#define	HD64461_PCCGCR_REG		0x01	/* pin PCC0REG# */
 
 /* PCC Card Status Change Register */
-#define HD64461_PCCCSCR_SCDI		0x80    /* sw card detect intr */
-#define HD64461_PCCCSCR_SRV1		0x40    /* reserved */
-#define HD64461_PCCCSCR_IREQ		0x20    /* IREQ intr req */
-#define HD64461_PCCCSCR_SC		0x10    /* STSCHG (status change) pin */
-#define HD64461_PCCCSCR_CDC		0x08    /* CD (card detect) change */
-#define HD64461_PCCCSCR_RC		0x04    /* READY change */
-#define HD64461_PCCCSCR_BW		0x02    /* battery warning change */
-#define HD64461_PCCCSCR_BD		0x01    /* battery dead change */
+#define	HD64461_PCCCSCR_SCDI		0x80	/* sw card detect intr */
+#define	HD64461_PCCCSCR_SRV1		0x40	/* reserved */
+#define	HD64461_PCCCSCR_IREQ		0x20	/* IREQ intr req */
+#define	HD64461_PCCCSCR_SC		0x10	/* STSCHG (status change) pin */
+#define	HD64461_PCCCSCR_CDC		0x08	/* CD (card detect) change */
+#define	HD64461_PCCCSCR_RC		0x04	/* READY change */
+#define	HD64461_PCCCSCR_BW		0x02	/* battery warning change */
+#define	HD64461_PCCCSCR_BD		0x01	/* battery dead change */
 
 /* PCC Card Status Change Interrupt Enable Register */
-#define HD64461_PCCCSCIER_CRE		0x80    /* change reset enable */
-#define HD64461_PCCCSCIER_IREQE_MASK	0x60   /* IREQ enable */
-#define HD64461_PCCCSCIER_IREQE_DISABLED	0x00   /* IREQ disabled */
-#define HD64461_PCCCSCIER_IREQE_LEVEL	0x20   /* IREQ level-triggered */
-#define HD64461_PCCCSCIER_IREQE_FALLING	0x40   /* IREQ falling-edge-trig */
-#define HD64461_PCCCSCIER_IREQE_RISING	0x60   /* IREQ rising-edge-trig */
+#define	HD64461_PCCCSCIER_CRE		0x80	/* change reset enable */
+#define	HD64461_PCCCSCIER_IREQE_MASK	0x60	/* IREQ enable */
+#define	HD64461_PCCCSCIER_IREQE_DISABLED 0x00	/* IREQ disabled */
+#define	HD64461_PCCCSCIER_IREQE_LEVEL	0x20	/* IREQ level-triggered */
+#define	HD64461_PCCCSCIER_IREQE_FALLING	0x40	/* IREQ falling-edge-trig */
+#define	HD64461_PCCCSCIER_IREQE_RISING	0x60	/* IREQ rising-edge-trig */
 
-#define HD64461_PCCCSCIER_SCE		0x10    /* status change enable */
-#define HD64461_PCCCSCIER_CDE		0x08    /* card detect change enable */
-#define HD64461_PCCCSCIER_RE		0x04    /* ready change enable */
-#define HD64461_PCCCSCIER_BWE		0x02    /* battery warn change enable */
-#define HD64461_PCCCSCIER_BDE		0x01    /* battery dead change enable*/
+#define	HD64461_PCCCSCIER_SCE		0x10	/* status change enable */
+#define	HD64461_PCCCSCIER_CDE		0x08	/* card detect change enable */
+#define	HD64461_PCCCSCIER_RE		0x04	/* ready change enable */
+#define	HD64461_PCCCSCIER_BWE		0x02	/* battery warn change enable */
+#define	HD64461_PCCCSCIER_BDE		0x01	/* battery dead change enable*/
 
 /* PCC Software Control Register */
-#define HD64461_PCCSCR_VCC1		0x02	/* voltage control pin 1 */
-#define HD64461_PCCSCR_SWP		0x01    /* write protect */
+#define	HD64461_PCCSCR_VCC1		0x02	/* voltage control pin 1 */
+#define	HD64461_PCCSCR_SWP		0x01	/* write protect */
 
-#define HD64461_P0OCR           0x1202a
-#define HD64461_P1OCR           0x1202c
-#define HD64461_PGCR            0x1202e
+/* PCC0 Output Pins Control Register */
+#define	HD64461_P0OCR		(CONFIG_HD64461_IOBASE + 0x202a)
 
-#define HD64461_GPACR		0x14000
-#define HD64461_GPBCR		0x14002
-#define HD64461_GPCCR		0x14004
-#define HD64461_GPDCR		0x14006
-#define HD64461_GPADR		0x14010
-#define HD64461_GPBDR		0x14012
-#define HD64461_GPCDR		0x14014
-#define HD64461_GPDDR		0x14016
-#define HD64461_GPAICR		0x14020
-#define HD64461_GPBICR		0x14022
-#define HD64461_GPCICR		0x14024
-#define HD64461_GPDICR		0x14026
-#define HD64461_GPAISR		0x14040
-#define HD64461_GPBISR		0x14042
-#define HD64461_GPCISR		0x14044
-#define HD64461_GPDISR		0x14046
+/* PCC1 Output Pins Control Register */
+#define	HD64461_P1OCR		(CONFIG_HD64461_IOBASE + 0x202c)
 
-#define HD64461_NIRR		0x15000
-#define HD64461_NIMR		0x15002
+/* PC Card General Control Register */
+#define	HD64461_PGCR		(CONFIG_HD64461_IOBASE + 0x202e)
 
-#define HD64461_IRQBASE		OFFCHIP_IRQ_BASE
-#define HD64461_IRQ_NUM		16
+/* Port Control Registers */
+#define	HD64461_GPACR		(CONFIG_HD64461_IOBASE + 0x4000)	/* Port A - Handles IRDA/TIMER */
+#define	HD64461_GPBCR		(CONFIG_HD64461_IOBASE + 0x4002)	/* Port B - Handles UART */
+#define	HD64461_GPCCR		(CONFIG_HD64461_IOBASE + 0x4004)	/* Port C - Handles PCMCIA 1 */
+#define	HD64461_GPDCR		(CONFIG_HD64461_IOBASE + 0x4006)	/* Port D - Handles PCMCIA 1 */
 
-#define HD64461_IRQ_UART	(HD64461_IRQBASE+5)
-#define HD64461_IRQ_IRDA	(HD64461_IRQBASE+6)
-#define HD64461_IRQ_TMU1	(HD64461_IRQBASE+9)
-#define HD64461_IRQ_TMU0	(HD64461_IRQBASE+10)
-#define HD64461_IRQ_GPIO	(HD64461_IRQBASE+11)
-#define HD64461_IRQ_AFE		(HD64461_IRQBASE+12)
-#define HD64461_IRQ_PCC1	(HD64461_IRQBASE+13)
-#define HD64461_IRQ_PCC0	(HD64461_IRQBASE+14)
+/* Port Control Data Registers */
+#define	HD64461_GPADR		(CONFIG_HD64461_IOBASE + 0x4010)	/* A */
+#define	HD64461_GPBDR		(CONFIG_HD64461_IOBASE + 0x4012)	/* B */
+#define	HD64461_GPCDR		(CONFIG_HD64461_IOBASE + 0x4014)	/* C */
+#define	HD64461_GPDDR		(CONFIG_HD64461_IOBASE + 0x4016)	/* D */
+
+/* Interrupt Control Registers */
+#define	HD64461_GPAICR		(CONFIG_HD64461_IOBASE + 0x4020)	/* A */
+#define	HD64461_GPBICR		(CONFIG_HD64461_IOBASE + 0x4022)	/* B */
+#define	HD64461_GPCICR		(CONFIG_HD64461_IOBASE + 0x4024)	/* C */
+#define	HD64461_GPDICR		(CONFIG_HD64461_IOBASE + 0x4026)	/* D */
+
+/* Interrupt Status Registers */
+#define	HD64461_GPAISR		(CONFIG_HD64461_IOBASE + 0x4040)	/* A */
+#define	HD64461_GPBISR		(CONFIG_HD64461_IOBASE + 0x4042)	/* B */
+#define	HD64461_GPCISR		(CONFIG_HD64461_IOBASE + 0x4044)	/* C */
+#define	HD64461_GPDISR		(CONFIG_HD64461_IOBASE + 0x4046)	/* D */
+
+/* Interrupt Request Register & Interrupt Mask Register */
+#define	HD64461_NIRR		(CONFIG_HD64461_IOBASE + 0x5000)
+#define	HD64461_NIMR		(CONFIG_HD64461_IOBASE + 0x5002)
+
+#define	HD64461_IRQBASE		OFFCHIP_IRQ_BASE
+#define	HD64461_IRQ_NUM		16
+
+#define	HD64461_IRQ_UART	(HD64461_IRQBASE+5)
+#define	HD64461_IRQ_IRDA	(HD64461_IRQBASE+6)
+#define	HD64461_IRQ_TMU1	(HD64461_IRQBASE+9)
+#define	HD64461_IRQ_TMU0	(HD64461_IRQBASE+10)
+#define	HD64461_IRQ_GPIO	(HD64461_IRQBASE+11)
+#define	HD64461_IRQ_AFE		(HD64461_IRQBASE+12)
+#define	HD64461_IRQ_PCC1	(HD64461_IRQBASE+13)
+#define	HD64461_IRQ_PCC0	(HD64461_IRQBASE+14)
 
 #define __IO_PREFIX	hd64461
 #include <asm/io_generic.h>
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index 80ee1cd..4ca3f76 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -5,4 +5,46 @@
 
 extern atomic_t irq_err_count;
 
+struct intc2_data {
+	unsigned short irq;
+	unsigned char ipr_offset, ipr_shift;
+	unsigned char msk_offset, msk_shift;
+	unsigned char priority;
+};
+
+struct intc2_desc {
+	unsigned long prio_base;
+	unsigned long msk_base;
+	unsigned long mskclr_base;
+	struct intc2_data *intc2_data;
+	unsigned int nr_irqs;
+	struct irq_chip chip;
+};
+
+void register_intc2_controller(struct intc2_desc *);
+void init_IRQ_intc2(void);
+
+struct ipr_data {
+	unsigned char irq;
+	unsigned char ipr_idx;		/* Index for the IPR registered */
+	unsigned char shift;		/* Number of bits to shift the data */
+	unsigned char priority;		/* The priority */
+};
+
+struct ipr_desc {
+	unsigned long *ipr_offsets;
+	unsigned int nr_offsets;
+	struct ipr_data *ipr_data;
+	unsigned int nr_irqs;
+	struct irq_chip chip;
+};
+
+void register_ipr_controller(struct ipr_desc *);
+void init_IRQ_ipr(void);
+
+/*
+ * Enable individual interrupt mode for external IPR IRQs.
+ */
+void ipr_irq_enable_irlm(void);
+
 #endif /* __ASM_SH_HW_IRQ_H */
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index e81bf21..c61d902 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -31,47 +31,7 @@
  * PINT IRQs
  */
 void init_IRQ_pint(void);
-
-/*
- * The shift value is now the number of bits to shift, not the number of
- * bits/4. This is to make it easier to read the value directly from the
- * datasheets. The IPR address, addr, will be set from ipr_idx via the
- * map_ipridx_to_addr function.
- */
-struct ipr_data {
-	unsigned int irq;
-	int ipr_idx;		/* Index for the IPR registered */
-	int shift;		/* Number of bits to shift the data */
-	int priority;		/* The priority */
-	unsigned int addr;	/* Address of Interrupt Priority Register */
-};
-
-/*
- * Given an IPR IDX, map the value to an IPR register address.
- */
-unsigned int map_ipridx_to_addr(int idx);
-
-/*
- * Enable individual interrupt mode for external IPR IRQs.
- */
-void ipr_irq_enable_irlm(void);
-
-/*
- * Function for "on chip support modules".
- */
-void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
 void make_imask_irq(unsigned int irq);
-void init_IRQ_ipr(void);
-
-struct intc2_data {
-	unsigned short irq;
-	unsigned char ipr_offset, ipr_shift;
-	unsigned char msk_offset, msk_shift;
-	unsigned char priority;
-};
-
-void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs);
-void init_IRQ_intc2(void);
 
 static inline int generic_irq_demux(int irq)
 {
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h
index 70389b7..088698b 100644
--- a/include/asm-sh/machvec.h
+++ b/include/asm-sh/machvec.h
@@ -13,7 +13,6 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <asm/machtypes.h>
-#include <asm/machvec_init.h>
 
 struct device;
 
@@ -68,4 +67,7 @@
 
 #define get_system_type()	sh_mv.mv_name
 
+#define __initmv \
+	__attribute_used__ __attribute__((__section__ (".machvec.init")))
+
 #endif /* _ASM_SH_MACHVEC_H */
diff --git a/include/asm-sh/machvec_init.h b/include/asm-sh/machvec_init.h
deleted file mode 100644
index e397798..0000000
--- a/include/asm-sh/machvec_init.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * include/asm-sh/machvec_init.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file has goodies to help simplify instantiation of machine vectors.
- */
-
-#ifndef __SH_MACHVEC_INIT_H
-#define __SH_MACHVEC_INIT_H
-
-
-/*
- * In a GENERIC kernel, we have lots of these vectors floating about,
- * all but one of which we want to go away.  In a non-GENERIC kernel,
- * we want only one, ever.
- *
- * Accomplish this in the GENERIC kernel by puting all of the vectors
- * in the .init.data section where they'll go away.  We'll copy the
- * one we want to the real alpha_mv vector in setup_arch.
- *
- * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
- * one of the vectors, which will not reside in .init.data.  We then
- * alias this one vector to alpha_mv, so no copy is needed.
- *
- * Upshot: set __initdata to nothing for non-GENERIC kernels.
- *
- * Note we do the same thing for the UNKNOWN kernel, as we need to write
- * to the machine vector while setting it up.
- */
-
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
-#define __initmv __attribute__((unused,__section__ (".machvec.init")))
-#define ALIAS_MV(x)
-#else
-#define __initmv
-
-/* GCC actually has a syntax for defining aliases, but is under some
-   delusion that you shouldn't be able to declare it extern somewhere
-   else beforehand.  Fine.  We'll do it ourselves.  */
-#if 0
-#define ALIAS_MV(system) \
-  struct sh_machine_vector sh_mv __attribute__((alias("mv_"#system)));
-#else
-#define ALIAS_MV(system) \
-  asm(".global sh_mv\nsh_mv = mv_"#system );
-#endif
-#endif /* GENERIC */
-
-#endif /* __SH_MACHVEC_INIT_H */
diff --git a/include/asm-sh/mmzone.h b/include/asm-sh/mmzone.h
new file mode 100644
index 0000000..7969f38
--- /dev/null
+++ b/include/asm-sh/mmzone.h
@@ -0,0 +1,46 @@
+#ifndef __ASM_SH_MMZONE_H
+#define __ASM_SH_MMZONE_H
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid)		(node_data[nid])
+
+#define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
+#define node_end_pfn(nid)	(NODE_DATA(nid)->node_start_pfn + \
+				 NODE_DATA(nid)->node_spanned_pages)
+
+static inline int pfn_to_nid(unsigned long pfn)
+{
+	int nid;
+
+	for (nid = 0; nid < MAX_NUMNODES; nid++)
+		if (pfn >= node_start_pfn(nid) && pfn <= node_end_pfn(nid))
+			break;
+
+	return nid;
+}
+
+static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+	return NODE_DATA(pfn_to_nid(pfn));
+}
+
+/* arch/sh/mm/numa.c */
+void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end);
+#else
+static inline void
+setup_bootmem_node(int nid, unsigned long start, unsigned long end)
+{
+}
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+/* Platform specific mem init */
+void __init plat_mem_setup(void);
+
+/* arch/sh/kernel/setup.c */
+void __init setup_bootmem_allocator(unsigned long start_pfn);
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_MMZONE_H */
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 7464de4..6bc9bba 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -60,6 +60,7 @@
 
 extern unsigned long shm_align_mask;
 extern unsigned long max_low_pfn, min_low_pfn;
+extern unsigned long memory_start, memory_end;
 
 #ifdef CONFIG_MMU
 extern void clear_page_slow(void *to);
@@ -134,7 +135,9 @@
 #define PFN_START		(__MEMORY_START >> PAGE_SHIFT)
 #define ARCH_PFN_OFFSET		(PFN_START)
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#ifdef CONFIG_FLATMEM
 #define pfn_valid(pfn)		((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
+#endif
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
@@ -148,5 +151,12 @@
 #define __HAVE_ARCH_GATE_AREA
 #endif
 
+/*
+ * Slub defaults to 8-byte alignment, we're only interested in 4.
+ * Slab defaults to BYTES_PER_WORD, which ends up being the same anyways.
+ */
+#define ARCH_KMALLOC_MINALIGN	4
+#define ARCH_SLAB_MINALIGN	4
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PAGE_H */
diff --git a/include/asm-sh/parport.h b/include/asm-sh/parport.h
new file mode 100644
index 0000000..f67ba60
--- /dev/null
+++ b/include/asm-sh/parport.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ */
+#ifndef __ASM_SH_PARPORT_H
+#define __ASM_SH_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_SH_PARPORT_H */
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index 5b523c7..22efffe 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -402,12 +402,8 @@
 #define pte_file(pte)		(pte_val(pte) & _PAGE_FILE)
 
 #ifdef CONFIG_X2TLB
-#define pte_read(pte)		((pte).pte_high & _PAGE_EXT_USER_READ)
-#define pte_exec(pte)		((pte).pte_high & _PAGE_EXT_USER_EXEC)
 #define pte_write(pte)		((pte).pte_high & _PAGE_EXT_USER_WRITE)
 #else
-#define pte_read(pte)		(pte_val(pte) & _PAGE_USER)
-#define pte_exec(pte)		(pte_val(pte) & _PAGE_USER)
 #define pte_write(pte)		(pte_val(pte) & _PAGE_RW)
 #endif
 
@@ -420,20 +416,12 @@
  * individually toggled (and user permissions are entirely decoupled from
  * kernel permissions), we attempt to couple them a bit more sanely here.
  */
-PTE_BIT_FUNC(high, rdprotect, &= ~_PAGE_EXT_USER_READ);
-PTE_BIT_FUNC(high, mkread, |= _PAGE_EXT_USER_READ | _PAGE_EXT_KERN_READ);
 PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE);
 PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
-PTE_BIT_FUNC(high, exprotect, &= ~_PAGE_EXT_USER_EXEC);
-PTE_BIT_FUNC(high, mkexec, |= _PAGE_EXT_USER_EXEC | _PAGE_EXT_KERN_EXEC);
 PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE);
 #else
-PTE_BIT_FUNC(low, rdprotect, &= ~_PAGE_USER);
-PTE_BIT_FUNC(low, mkread, |= _PAGE_USER);
 PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW);
 PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW);
-PTE_BIT_FUNC(low, exprotect, &= ~_PAGE_USER);
-PTE_BIT_FUNC(low, mkexec, |= _PAGE_USER);
 PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE);
 #endif
 
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index d42f68e..2252e75 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -36,7 +36,7 @@
  */
 enum cpu_type {
 	/* SH-2 types */
-	CPU_SH7604, CPU_SH7619,
+	CPU_SH7619,
 
 	/* SH-2A types */
 	CPU_SH7206,
@@ -52,7 +52,7 @@
 	CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
 
 	/* SH-4A types */
-	CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
+	CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3,
 
 	/* SH4AL-DSP types */
 	CPU_SH73180, CPU_SH7343, CPU_SH7722,
@@ -228,11 +228,7 @@
 	regs->sr &= ~SR_FD;
 }
 
-#ifdef CONFIG_CPU_SH4
 extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs);
-#else
-#define save_fpu(tsk)	do { } while (0)
-#endif
 
 #define unlazy_fpu(tsk, regs) do {			\
 	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {	\
diff --git a/include/asm-sh/rwsem.h b/include/asm-sh/rwsem.h
index 4931ba8..1987f3e 100644
--- a/include/asm-sh/rwsem.h
+++ b/include/asm-sh/rwsem.h
@@ -1,11 +1,15 @@
 /*
- * include/asm-ppc/rwsem.h: R/W semaphores for SH using the stuff
+ * include/asm-sh/rwsem.h: R/W semaphores for SH using the stuff
  * in lib/rwsem.c.
  */
 
 #ifndef _ASM_SH_RWSEM_H
 #define _ASM_SH_RWSEM_H
 
+#ifndef _LINUX_RWSEM_H
+#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
+#endif
+
 #ifdef __KERNEL__
 #include <linux/list.h>
 #include <linux/spinlock.h>
diff --git a/include/asm-sh/saturn/io.h b/include/asm-sh/saturn/io.h
deleted file mode 100644
index f1b9b5d..0000000
--- a/include/asm-sh/saturn/io.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * include/asm-sh/saturn/io.h
- *
- * I/O functions for use on the Sega Saturn.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#ifndef __ASM_SH_SATURN_IO_H
-#define __ASM_SH_SATURN_IO_H
-
-/* arch/sh/boards/saturn/io.c */
-extern unsigned long saturn_isa_port2addr(unsigned long offset);
-extern void *saturn_ioremap(unsigned long offset, unsigned long size);
-extern void saturn_iounmap(void *addr);
-
-#endif /* __ASM_SH_SATURN_IO_H */
-
diff --git a/include/asm-sh/saturn/smpc.h b/include/asm-sh/saturn/smpc.h
deleted file mode 100644
index 5de5c12..0000000
--- a/include/asm-sh/saturn/smpc.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * include/asm-sh/saturn/smpc.h
- *
- * System Manager / Peripheral Control definitions.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#ifndef __ASM_SH_SATURN_SMPC_H
-#define __ASM_SH_SATURN_SMPC_H
-
-#include <asm/io.h>
-
-#define SMPC_COMMAND	0x2010001f	/* SMPC command register */
-#define SMPC_RESULT	0x2010005f	/* SMPC result register */
-#define SMPC_STATUS	0x20100063	/* SMPC status register */
-
-#define SMPC_CMD_MSHON	0x0001		/* Master SH On */
-#define SMPC_CMD_SSHON	0x0002		/* Slave SH On */
-#define SMPC_CMD_SSHOFF	0x0003		/* Slave SH Off */
-#define SMPC_CMD_SNDON	0x0004		/* Sound On */
-#define SMPC_CMD_SNDOFF	0x0005		/* Sound Off */
-#define SMPC_CMD_CDON	0x0006		/* CD On */
-#define SMPC_CMD_CDOFF	0x0007		/* CD Off */
-
-static inline void smpc_barrier(void)
-{
-	while ((ctrl_inb(SMPC_STATUS) & 0x0001) == 0x0001)
-		;
-}
-
-#endif /* __ASM_SH_SATURN_SMPC_H */
-
diff --git a/include/asm-sh/sections.h b/include/asm-sh/sections.h
index 57abd70..2a696b8 100644
--- a/include/asm-sh/sections.h
+++ b/include/asm-sh/sections.h
@@ -3,7 +3,7 @@
 
 #include <asm-generic/sections.h>
 
-extern char _end[];
+extern long __machvec_start, __machvec_end;
 
 #endif /* __ASM_SH_SECTIONS_H */
 
diff --git a/include/asm-sh/setup.h b/include/asm-sh/setup.h
index 1583c6b..586a971 100644
--- a/include/asm-sh/setup.h
+++ b/include/asm-sh/setup.h
@@ -6,6 +6,7 @@
 #ifdef __KERNEL__
 
 int setup_early_printk(char *);
+void sh_mv_setup(void);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-sh/sh03/io.h b/include/asm-sh/sh03/io.h
index df3b187..4ff1eb9 100644
--- a/include/asm-sh/sh03/io.h
+++ b/include/asm-sh/sh03/io.h
@@ -14,22 +14,18 @@
 #define INTC_IPRD	0xffd00010UL
 
 #define IRL0_IRQ	2
-#define IRL0_IPR_ADDR	INTC_IPRD
 #define IRL0_IPR_POS	3
 #define IRL0_PRIORITY	13
 
 #define IRL1_IRQ	5
-#define IRL1_IPR_ADDR	INTC_IPRD
 #define IRL1_IPR_POS	2
 #define IRL1_PRIORITY	10
 
 #define IRL2_IRQ	8
-#define IRL2_IPR_ADDR	INTC_IPRD
 #define IRL2_IPR_POS	1
 #define IRL2_PRIORITY	7
 
 #define IRL3_IRQ	11
-#define IRL3_IPR_ADDR	INTC_IPRD
 #define IRL3_IPR_POS	0
 #define IRL3_PRIORITY	4
 
diff --git a/include/asm-sh/smp.h b/include/asm-sh/smp.h
index caa7b93..b99ca78 100644
--- a/include/asm-sh/smp.h
+++ b/include/asm-sh/smp.h
@@ -39,4 +39,6 @@
 
 #endif /* CONFIG_SMP */
 
+#define hard_smp_processor_id()	(0)
+
 #endif /* __ASM_SH_SMP_H */
diff --git a/include/asm-sh/snapgear.h b/include/asm-sh/snapgear.h
index 2d712e7..3554e3a 100644
--- a/include/asm-sh/snapgear.h
+++ b/include/asm-sh/snapgear.h
@@ -20,22 +20,18 @@
  */
 
 #define IRL0_IRQ		2
-#define IRL0_IPR_ADDR	INTC_IPRD
 #define IRL0_IPR_POS	3
 #define IRL0_PRIORITY	13
 
 #define IRL1_IRQ		5
-#define IRL1_IPR_ADDR	INTC_IPRD
 #define IRL1_IPR_POS	2
 #define IRL1_PRIORITY	10
 
 #define IRL2_IRQ		8
-#define IRL2_IPR_ADDR	INTC_IPRD
 #define IRL2_IPR_POS	1
 #define IRL2_PRIORITY	7
 
 #define IRL3_IRQ		11
-#define IRL3_IPR_ADDR	INTC_IPRD
 #define IRL3_IPR_POS	0
 #define IRL3_PRIORITY	4
 #endif
diff --git a/include/asm-sh/sparsemem.h b/include/asm-sh/sparsemem.h
new file mode 100644
index 0000000..547a540
--- /dev/null
+++ b/include/asm-sh/sparsemem.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_SH_SPARSEMEM_H
+#define __ASM_SH_SPARSEMEM_H
+
+#ifdef __KERNEL__
+/*
+ * SECTION_SIZE_BITS		2^N: how big each section will be
+ * MAX_PHYSADDR_BITS		2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS		2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS	26
+#define MAX_PHYSADDR_BITS	32
+#define MAX_PHYSMEM_BITS	32
+
+#endif
+
+#endif /* __ASM_SH_SPARSEMEM_H */
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 82f3e22..7c75045 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -8,9 +8,13 @@
 
 #include <linux/irqflags.h>
 #include <linux/compiler.h>
+#include <linux/linkage.h>
 #include <asm/types.h>
 #include <asm/ptrace.h>
 
+struct task_struct *__switch_to(struct task_struct *prev,
+				struct task_struct *next);
+
 /*
  *	switch_to() should switch tasks to task nr n, first
  */
@@ -122,7 +126,7 @@
 #define smp_read_barrier_depends()	do { } while(0)
 #endif
 
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
 
 /*
  * Jump to P2 area.
@@ -271,6 +275,16 @@
 void disable_hlt(void);
 void enable_hlt(void);
 
+void default_idle(void);
+
+asmlinkage void break_point_trap(void);
+asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
+				   unsigned long r6, unsigned long r7,
+				   struct pt_regs __regs);
+asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
+				 unsigned long r6, unsigned long r7,
+				 struct pt_regs __regs);
+
 #define arch_align_stack(x) (x)
 
 #endif
diff --git a/include/asm-sh/topology.h b/include/asm-sh/topology.h
index cff001c..f402a3b 100644
--- a/include/asm-sh/topology.h
+++ b/include/asm-sh/topology.h
@@ -1,6 +1,36 @@
 #ifndef _ASM_SH_TOPOLOGY_H
 #define _ASM_SH_TOPOLOGY_H
 
+#ifdef CONFIG_NUMA
+
+/* sched_domains SD_NODE_INIT for sh machines */
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.child			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 8,			\
+	.max_interval		= 32,			\
+	.busy_factor		= 32,			\
+	.imbalance_pct		= 125,			\
+	.cache_nice_tries	= 2,			\
+	.busy_idx		= 3,			\
+	.idle_idx		= 2,			\
+	.newidle_idx		= 0,			\
+	.wake_idx		= 1,			\
+	.forkexec_idx		= 1,			\
+	.flags			= SD_LOAD_BALANCE	\
+				| SD_BALANCE_FORK	\
+				| SD_BALANCE_EXEC	\
+				| SD_SERIALIZE		\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+
+#endif
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_SH_TOPOLOGY_H */
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
index 5c49ed6..f18a1a5 100644
--- a/include/asm-sh/uaccess.h
+++ b/include/asm-sh/uaccess.h
@@ -61,8 +61,6 @@
  */
 static inline int __access_ok(unsigned long addr, unsigned long size)
 {
-	extern unsigned long memory_start, memory_end;
-
 	return ((addr >= memory_start) && ((addr + size) < memory_end));
 }
 #else /* CONFIG_MMU */
@@ -76,7 +74,7 @@
  * __access_ok: Check if address with size is OK or not.
  *
  * We do three checks:
- * (1) is it user space? 
+ * (1) is it user space?
  * (2) addr + size --> carry?
  * (3) addr + size >= 0x80000000  (PAGE_OFFSET)
  *
@@ -142,11 +140,12 @@
   __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))
 
 #define __get_user_size(x,ptr,size,retval)			\
 do {								\
 	retval = 0;						\
+	__chk_user_ptr(ptr);					\
 	switch (size) {						\
 	case 1:							\
 		__get_user_asm(x, ptr, retval, "b");		\
@@ -175,6 +174,7 @@
 #define __get_user_check(x,ptr,size)				\
 ({								\
 	long __gu_err, __gu_val;				\
+	__chk_user_ptr(ptr);					\
 	switch (size) {						\
 	case 1:							\
 		__get_user_1(__gu_val, (ptr), __gu_err);	\
@@ -300,6 +300,7 @@
 #define __put_user_size(x,ptr,size,retval)		\
 do {							\
 	retval = 0;					\
+	__chk_user_ptr(ptr);				\
 	switch (size) {					\
 	case 1:						\
 		__put_user_asm(x, ptr, retval, "b");	\
@@ -328,7 +329,7 @@
 #define __put_user_check(x,ptr,size)				\
 ({								\
 	long __pu_err = -EFAULT;				\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
+	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
 								\
 	if (__access_ok((unsigned long)__pu_addr,size))		\
 		__put_user_size((x),__pu_addr,(size),__pu_err);	\
@@ -406,10 +407,10 @@
 #endif
 
 extern void __put_user_unknown(void);
-
+
 /* Generic arbitrary sized copy.  */
 /* Return the number of bytes NOT copied */
-extern __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
 
 #define copy_to_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
@@ -420,14 +421,6 @@
 } else __copy_res = __copy_size; \
 __copy_res; })
 
-#define __copy_to_user(to,from,n)		\
-	__copy_user((void *)(to),		\
-		    (void *)(from), n)
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-
 #define copy_from_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
 void *__copy_from = (void *) (from); \
@@ -438,9 +431,20 @@
 } else __copy_res = __copy_size; \
 __copy_res; })
 
-#define __copy_from_user(to,from,n)		\
-	__copy_user((void *)(to),		\
-		    (void *)(from), n)
+static __always_inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	return __copy_user(to, (__force void *)from, n);
+}
+
+static __always_inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	return __copy_user((__force void *)to, from, n);
+}
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 /*
  * Clear the area and return remaining number of bytes
diff --git a/include/asm-sh/ubc.h b/include/asm-sh/ubc.h
index ae9bbde..38d46e0 100644
--- a/include/asm-sh/ubc.h
+++ b/include/asm-sh/ubc.h
@@ -51,9 +51,14 @@
 #define BRCR_UBDE		(1 << 0)
 
 #ifndef __ASSEMBLY__
-/* arch/sh/kernel/ubc.S */
-extern void ubc_wakeup(void);
+/* arch/sh/kernel/cpu/ubc.S */
 extern void ubc_sleep(void);
+
+#ifdef CONFIG_UBC_WAKEUP
+extern void ubc_wakeup(void);
+#else
+#define ubc_wakeup()	do { } while (0)
+#endif
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-sh64/fb.h b/include/asm-sh64/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-sh64/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index b875482..3488fe3 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -415,22 +415,15 @@
 /*
  * The following have defined behavior only work if pte_present() is true.
  */
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXECUTE; }
 static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_READ)); return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
-
-static inline pte_t pte_mkread(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_READ)); return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_mkhuge(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
diff --git a/include/asm-sparc/fb.h b/include/asm-sparc/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-sparc/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index 59229ae..a55f4c3 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -151,7 +151,6 @@
 BTFIXUPDEF_SETHI(none_mask)
 BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t)
 BTFIXUPDEF_CALL(void, pte_clear, pte_t *)
-BTFIXUPDEF_CALL(int, pte_read, pte_t)
 
 static inline int pte_none(pte_t pte)
 {
@@ -160,7 +159,6 @@
 
 #define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
 #define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
-#define pte_read(pte) BTFIXUP_CALL(pte_read)(pte)
 
 BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
 BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
index bf39d86..11ade68 100644
--- a/include/asm-sparc64/bugs.h
+++ b/include/asm-sparc64/bugs.h
@@ -4,12 +4,7 @@
  */
 #include <asm/sstate.h>
 
-extern unsigned long loops_per_jiffy;
-
 static void __init check_bugs(void)
 {
-#ifndef CONFIG_SMP
-	cpu_data(0).udelay_val = loops_per_jiffy;
-#endif
 	sstate_running();
 }
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index 36511ca..01fe668 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -31,8 +31,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index 445026f..98a6e60 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -19,7 +19,7 @@
 	unsigned int	__softirq_pending; /* must be 1st, see rtrap.S */
 	unsigned int	__pad0;
 	unsigned long	clock_tick;	/* %tick's per second */
-	unsigned long	udelay_val;
+	unsigned long	__pad;
 	unsigned int	__pad1;
 	unsigned int	__pad2;
 
@@ -80,7 +80,8 @@
 	unsigned int		dev_mondo_qmask;
 	unsigned int		resum_qmask;
 	unsigned int		nonresum_qmask;
-	unsigned int		__pad2[3];
+	unsigned int		__pad2[1];
+	void			*hdesc;
 } __attribute__((aligned(64)));
 extern struct trap_per_cpu trap_block[NR_CPUS];
 extern void init_cur_cpu_trap(struct thread_info *);
diff --git a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
index a4aae6f..a77aa62 100644
--- a/include/asm-sparc64/delay.h
+++ b/include/asm-sparc64/delay.h
@@ -1,37 +1,17 @@
 /* delay.h: Linux delay routines on sparc64.
  *
- * Copyright (C) 1996, 2004 David S. Miller (davem@davemloft.net).
- *
- * Based heavily upon x86 variant which is:
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/sparc64/lib/delay.c
+ * Copyright (C) 1996, 2004, 2007 David S. Miller (davem@davemloft.net).
  */
 
-#ifndef __SPARC64_DELAY_H
-#define __SPARC64_DELAY_H
-
-#include <linux/param.h>
-#include <asm/cpudata.h>
+#ifndef _SPARC64_DELAY_H
+#define _SPARC64_DELAY_H
 
 #ifndef __ASSEMBLY__
 
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
-	__udelay(n))
-	
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
+extern void udelay(unsigned long usecs);
+#define mdelay(n)	udelay((n) * 1000)
 
 #endif /* !__ASSEMBLY__ */
 
-#endif /* defined(__SPARC64_DELAY_H) */
+#endif /* _SPARC64_DELAY_H */
diff --git a/include/asm-sparc64/fb.h b/include/asm-sparc64/fb.h
new file mode 100644
index 0000000..d6cd3a1
--- /dev/null
+++ b/include/asm-sparc64/fb.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sparc64/hvtramp.h b/include/asm-sparc64/hvtramp.h
new file mode 100644
index 0000000..c7dd6ad
--- /dev/null
+++ b/include/asm-sparc64/hvtramp.h
@@ -0,0 +1,37 @@
+#ifndef _SPARC64_HVTRAP_H
+#define _SPARC64_HVTRAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct hvtramp_mapping {
+	__u64		vaddr;
+	__u64		tte;
+};
+
+struct hvtramp_descr {
+	__u32			cpu;
+	__u32			num_mappings;
+	__u64			fault_info_va;
+	__u64			fault_info_pa;
+	__u64			thread_reg;
+	struct hvtramp_mapping	maps[2];
+};
+
+extern void hv_cpu_startup(unsigned long hvdescr_pa);
+
+#endif
+
+#define HVTRAMP_DESCR_CPU		0x00
+#define HVTRAMP_DESCR_NUM_MAPPINGS	0x04
+#define HVTRAMP_DESCR_FAULT_INFO_VA	0x08
+#define HVTRAMP_DESCR_FAULT_INFO_PA	0x10
+#define HVTRAMP_DESCR_THREAD_REG	0x18
+#define HVTRAMP_DESCR_MAPS		0x20
+
+#define HVTRAMP_MAPPING_VADDR		0x00
+#define HVTRAMP_MAPPING_TTE		0x08
+#define HVTRAMP_MAPPING_SIZE		0x10
+
+#endif /* _SPARC64_HVTRAP_H */
diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h
index db2130a..524d498 100644
--- a/include/asm-sparc64/hypervisor.h
+++ b/include/asm-sparc64/hypervisor.h
@@ -98,7 +98,7 @@
 #define HV_FAST_MACH_EXIT		0x00
 
 #ifndef __ASSEMBLY__
-extern void sun4v_mach_exit(unsigned long exit_core);
+extern void sun4v_mach_exit(unsigned long exit_code);
 #endif
 
 /* Domain services.  */
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 90781e3..e6c436e 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -53,6 +53,8 @@
 extern void sun4v_destroy_msi(unsigned int virt_irq);
 extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
 
+extern void fixup_irqs(void);
+
 static __inline__ void set_softint(unsigned long bits)
 {
 	__asm__ __volatile__("wr	%0, 0x0, %%set_softint"
diff --git a/include/asm-sparc64/ldc.h b/include/asm-sparc64/ldc.h
new file mode 100644
index 0000000..bdb524a
--- /dev/null
+++ b/include/asm-sparc64/ldc.h
@@ -0,0 +1,138 @@
+#ifndef _SPARC64_LDC_H
+#define _SPARC64_LDC_H
+
+#include <asm/hypervisor.h>
+
+extern int ldom_domaining_enabled;
+extern void ldom_set_var(const char *var, const char *value);
+extern void ldom_reboot(const char *boot_command);
+extern void ldom_power_off(void);
+
+/* The event handler will be evoked when link state changes
+ * or data becomes available on the receive side.
+ *
+ * For non-RAW links, if the LDC_EVENT_RESET event arrives the
+ * driver should reset all of it's internal state and reinvoke
+ * ldc_connect() to try and bring the link up again.
+ *
+ * For RAW links, ldc_connect() is not used.  Instead the driver
+ * just waits for the LDC_EVENT_UP event.
+ */
+struct ldc_channel_config {
+	void (*event)(void *arg, int event);
+
+	u32			mtu;
+	unsigned int		rx_irq;
+	unsigned int		tx_irq;
+	u8			mode;
+#define LDC_MODE_RAW		0x00
+#define LDC_MODE_UNRELIABLE	0x01
+#define LDC_MODE_RESERVED	0x02
+#define LDC_MODE_STREAM		0x03
+
+	u8			debug;
+#define LDC_DEBUG_HS		0x01
+#define LDC_DEBUG_STATE		0x02
+#define LDC_DEBUG_RX		0x04
+#define LDC_DEBUG_TX		0x08
+#define LDC_DEBUG_DATA		0x10
+};
+
+#define LDC_EVENT_RESET		0x01
+#define LDC_EVENT_UP		0x02
+#define LDC_EVENT_DATA_READY	0x04
+
+#define LDC_STATE_INVALID	0x00
+#define LDC_STATE_INIT		0x01
+#define LDC_STATE_BOUND		0x02
+#define LDC_STATE_READY		0x03
+#define LDC_STATE_CONNECTED	0x04
+
+struct ldc_channel;
+
+/* Allocate state for a channel.  */
+extern struct ldc_channel *ldc_alloc(unsigned long id,
+				     const struct ldc_channel_config *cfgp,
+				     void *event_arg);
+
+/* Shut down and free state for a channel.  */
+extern void ldc_free(struct ldc_channel *lp);
+
+/* Register TX and RX queues of the link with the hypervisor.  */
+extern int ldc_bind(struct ldc_channel *lp, const char *name);
+
+/* For non-RAW protocols we need to complete a handshake before
+ * communication can proceed.  ldc_connect() does that, if the
+ * handshake completes successfully, an LDC_EVENT_UP event will
+ * be sent up to the driver.
+ */
+extern int ldc_connect(struct ldc_channel *lp);
+extern int ldc_disconnect(struct ldc_channel *lp);
+
+extern int ldc_state(struct ldc_channel *lp);
+
+/* Read and write operations.  Only valid when the link is up.  */
+extern int ldc_write(struct ldc_channel *lp, const void *buf,
+		     unsigned int size);
+extern int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size);
+
+#define LDC_MAP_SHADOW	0x01
+#define LDC_MAP_DIRECT	0x02
+#define LDC_MAP_IO	0x04
+#define LDC_MAP_R	0x08
+#define LDC_MAP_W	0x10
+#define LDC_MAP_X	0x20
+#define LDC_MAP_RW	(LDC_MAP_R | LDC_MAP_W)
+#define LDC_MAP_RWX	(LDC_MAP_R | LDC_MAP_W | LDC_MAP_X)
+#define LDC_MAP_ALL	0x03f
+
+struct ldc_trans_cookie {
+	u64			cookie_addr;
+	u64			cookie_size;
+};
+
+struct scatterlist;
+extern int ldc_map_sg(struct ldc_channel *lp,
+		      struct scatterlist *sg, int num_sg,
+		      struct ldc_trans_cookie *cookies, int ncookies,
+		      unsigned int map_perm);
+
+extern int ldc_map_single(struct ldc_channel *lp,
+			  void *buf, unsigned int len,
+			  struct ldc_trans_cookie *cookies, int ncookies,
+			  unsigned int map_perm);
+
+extern void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+		      int ncookies);
+
+extern int ldc_copy(struct ldc_channel *lp, int copy_dir,
+		    void *buf, unsigned int len, unsigned long offset,
+		    struct ldc_trans_cookie *cookies, int ncookies);
+
+static inline int ldc_get_dring_entry(struct ldc_channel *lp,
+				      void *buf, unsigned int len,
+				      unsigned long offset,
+				      struct ldc_trans_cookie *cookies,
+				      int ncookies)
+{
+	return ldc_copy(lp, LDC_COPY_IN, buf, len, offset, cookies, ncookies);
+}
+
+static inline int ldc_put_dring_entry(struct ldc_channel *lp,
+				      void *buf, unsigned int len,
+				      unsigned long offset,
+				      struct ldc_trans_cookie *cookies,
+				      int ncookies)
+{
+	return ldc_copy(lp, LDC_COPY_OUT, buf, len, offset, cookies, ncookies);
+}
+
+extern void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+				 struct ldc_trans_cookie *cookies,
+				 int *ncookies, unsigned int map_perm);
+
+extern void ldc_free_exp_dring(struct ldc_channel *lp, void *buf,
+			       unsigned int len,
+			       struct ldc_trans_cookie *cookies, int ncookies);
+
+#endif /* _SPARC64_LDC_H */
diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h
index c638398..e97c431 100644
--- a/include/asm-sparc64/mdesc.h
+++ b/include/asm-sparc64/mdesc.h
@@ -2,38 +2,66 @@
 #define _SPARC64_MDESC_H
 
 #include <linux/types.h>
+#include <linux/cpumask.h>
 #include <asm/prom.h>
 
-struct mdesc_node;
-struct mdesc_arc {
-	const char		*name;
-	struct mdesc_node	*arc;
-};
+struct mdesc_handle;
 
-struct mdesc_node {
-	const char		*name;
-	u64			node;
-	unsigned int		unique_id;
-	unsigned int		num_arcs;
-	unsigned int		irqs[2];
-	struct property		*properties;
-	struct mdesc_node	*hash_next;
-	struct mdesc_node	*allnodes_next;
-	struct mdesc_arc	arcs[0];
-};
+/* Machine description operations are to be surrounded by grab and
+ * release calls.  The mdesc_handle returned from the grab is
+ * the first argument to all of the operational calls that work
+ * on mdescs.
+ */
+extern struct mdesc_handle *mdesc_grab(void);
+extern void mdesc_release(struct mdesc_handle *);
 
-extern struct mdesc_node *md_find_node_by_name(struct mdesc_node *from,
-					       const char *name);
-#define md_for_each_node_by_name(__mn, __name) \
-	for (__mn = md_find_node_by_name(NULL, __name); __mn; \
-	     __mn = md_find_node_by_name(__mn, __name))
+#define MDESC_NODE_NULL		(~(u64)0)
 
-extern struct property *md_find_property(const struct mdesc_node *mp,
-					 const char *name,
-					 int *lenp);
-extern const void *md_get_property(const struct mdesc_node *mp,
-				   const char *name,
-				   int *lenp);
+extern u64 mdesc_node_by_name(struct mdesc_handle *handle,
+			      u64 from_node, const char *name);
+#define mdesc_for_each_node_by_name(__hdl, __node, __name) \
+	for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
+	     (__node) != MDESC_NODE_NULL; \
+	     __node = mdesc_node_by_name(__hdl, __node, __name))
+
+/* Access to property values returned from mdesc_get_property() are
+ * only valid inside of a mdesc_grab()/mdesc_release() sequence.
+ * Once mdesc_release() is called, the memory backed up by these
+ * pointers may reference freed up memory.
+ *
+ * Therefore callers must make copies of any property values
+ * they need.
+ *
+ * These same rules apply to mdesc_node_name().
+ */
+extern const void *mdesc_get_property(struct mdesc_handle *handle,
+				      u64 node, const char *name, int *lenp);
+extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
+
+/* MD arc iteration, the standard sequence is:
+ *
+ *	unsigned long arc;
+ *	mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
+ *		unsigned long target = mdesc_arc_target(handle, arc);
+ *		...
+ *	}
+ */
+
+#define MDESC_ARC_TYPE_FWD	"fwd"
+#define MDESC_ARC_TYPE_BACK	"back"
+
+extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
+			  const char *arc_type);
+#define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
+	for (__arc = mdesc_next_arc(__hdl, __node, __type); \
+	     (__arc) != MDESC_NODE_NULL; \
+	     __arc = mdesc_next_arc(__hdl, __arc, __type))
+
+extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
+
+extern void mdesc_update(void);
+
+extern void mdesc_fill_in_cpu_data(cpumask_t mask);
 
 extern void sun4v_mdesc_init(void);
 
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
index 8d12903..9fc225e 100644
--- a/include/asm-sparc64/mmu_context.h
+++ b/include/asm-sparc64/mmu_context.h
@@ -76,6 +76,9 @@
 	unsigned long ctx_valid, flags;
 	int cpu;
 
+	if (unlikely(mm == &init_mm))
+		return;
+
 	spin_lock_irqsave(&mm->context.lock, flags);
 	ctx_valid = CTX_VALID(mm->context);
 	if (!ctx_valid)
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 9e80ad4..0393380 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -573,24 +573,6 @@
 	return (pte_val(pte) & mask);
 }
 
-static inline unsigned long pte_read(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_READ_4U), "i" (_PAGE_READ_4V));
-
-	return (pte_val(pte) & mask);
-}
-
 static inline unsigned long pte_file(pte_t pte)
 {
 	unsigned long val = pte_val(pte);
diff --git a/include/asm-sparc64/power.h b/include/asm-sparc64/power.h
new file mode 100644
index 0000000..94495c1
--- /dev/null
+++ b/include/asm-sparc64/power.h
@@ -0,0 +1,7 @@
+#ifndef _SPARC64_POWER_H
+#define _SPARC64_POWER_H
+
+extern void wake_up_powerd(void);
+extern int start_powerd(void);
+
+#endif /* !(_SPARC64_POWER_H) */
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index 4fb8c4b..e8a96a3 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -29,9 +29,6 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-extern cpumask_t phys_cpu_present_map;
-#define cpu_possible_map phys_cpu_present_map
-
 extern cpumask_t cpu_sibling_map[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
 extern int sparc64_multi_core;
@@ -44,7 +41,12 @@
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern void smp_fill_in_sib_core_maps(void);
-extern unsigned char boot_cpu_id;
+extern void cpu_play_dead(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+#endif
 
 #endif /* !(__ASSEMBLY__) */
 
@@ -52,7 +54,6 @@
 
 #define hard_smp_processor_id()		0
 #define smp_fill_in_sib_core_maps() do { } while (0)
-#define boot_cpu_id	(0)
 
 #endif /* !(CONFIG_SMP) */
 
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
new file mode 100644
index 0000000..83c9642
--- /dev/null
+++ b/include/asm-sparc64/vio.h
@@ -0,0 +1,404 @@
+#ifndef _SPARC64_VIO_H
+#define _SPARC64_VIO_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+struct vio_msg_tag {
+	u8			type;
+#define VIO_TYPE_CTRL		0x01
+#define VIO_TYPE_DATA		0x02
+#define VIO_TYPE_ERR		0x04
+
+	u8			stype;
+#define VIO_SUBTYPE_INFO	0x01
+#define VIO_SUBTYPE_ACK		0x02
+#define VIO_SUBTYPE_NACK	0x04
+
+	u16			stype_env;
+#define VIO_VER_INFO		0x0001
+#define VIO_ATTR_INFO		0x0002
+#define VIO_DRING_REG		0x0003
+#define VIO_DRING_UNREG		0x0004
+#define VIO_RDX			0x0005
+#define VIO_PKT_DATA		0x0040
+#define VIO_DESC_DATA		0x0041
+#define VIO_DRING_DATA		0x0042
+#define VNET_MCAST_INFO		0x0101
+
+	u32		sid;
+};
+
+struct vio_rdx {
+	struct vio_msg_tag	tag;
+	u64			resv[6];
+};
+
+struct vio_ver_info {
+	struct vio_msg_tag	tag;
+	u16			major;
+	u16			minor;
+	u8			dev_class;
+#define VDEV_NETWORK		0x01
+#define VDEV_NETWORK_SWITCH	0x02
+#define VDEV_DISK		0x03
+#define VDEV_DISK_SERVER	0x04
+
+	u8			resv1[3];
+	u64			resv2[5];
+};
+
+struct vio_dring_register {
+	struct vio_msg_tag	tag;
+	u64			dring_ident;
+	u32			num_descr;
+	u32			descr_size;
+	u16			options;
+#define VIO_TX_DRING		0x0001
+#define VIO_RX_DRING		0x0002
+	u16			resv;
+	u32			num_cookies;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+struct vio_dring_unregister {
+	struct vio_msg_tag	tag;
+	u64			dring_ident;
+	u64			resv[5];
+};
+
+/* Data transfer modes */
+#define VIO_PKT_MODE		0x01 /* Packet based transfer	*/
+#define VIO_DESC_MODE		0x02 /* In-band descriptors	*/
+#define VIO_DRING_MODE		0x03 /* Descriptor rings	*/
+
+struct vio_dring_data {
+	struct vio_msg_tag	tag;
+	u64			seq;
+	u64			dring_ident;
+	u32			start_idx;
+	u32			end_idx;
+	u8			state;
+#define VIO_DRING_ACTIVE	0x01
+#define VIO_DRING_STOPPED	0x02
+
+	u8			__pad1;
+	u16			__pad2;
+	u32			__pad3;
+	u64			__par4[2];
+};
+
+struct vio_dring_hdr {
+	u8			state;
+#define VIO_DESC_FREE		0x01
+#define VIO_DESC_READY		0x02
+#define VIO_DESC_ACCEPTED	0x03
+#define VIO_DESC_DONE		0x04
+	u8			ack;
+#define VIO_ACK_ENABLE		0x01
+#define VIO_ACK_DISABLE		0x00
+
+	u16			__pad1;
+	u32			__pad2;
+};
+
+/* VIO disk specific structures and defines */
+struct vio_disk_attr_info {
+	struct vio_msg_tag	tag;
+	u8			xfer_mode;
+	u8			vdisk_type;
+#define VD_DISK_TYPE_SLICE	0x01 /* Slice in block device	*/
+#define VD_DISK_TYPE_DISK	0x02 /* Entire block device	*/
+	u16			resv1;
+	u32			vdisk_block_size;
+	u64			operations;
+	u64			vdisk_size;
+	u64			max_xfer_size;
+	u64			resv2[2];
+};
+
+struct vio_disk_desc {
+	struct vio_dring_hdr	hdr;
+	u64			req_id;
+	u8			operation;
+#define VD_OP_BREAD		0x01 /* Block read			*/
+#define VD_OP_BWRITE		0x02 /* Block write			*/
+#define VD_OP_FLUSH		0x03 /* Flush disk contents		*/
+#define VD_OP_GET_WCE		0x04 /* Get write-cache status		*/
+#define VD_OP_SET_WCE		0x05 /* Enable/disable write-cache	*/
+#define VD_OP_GET_VTOC		0x06 /* Get VTOC			*/
+#define VD_OP_SET_VTOC		0x07 /* Set VTOC			*/
+#define VD_OP_GET_DISKGEOM	0x08 /* Get disk geometry		*/
+#define VD_OP_SET_DISKGEOM	0x09 /* Set disk geometry		*/
+#define VD_OP_SCSICMD		0x0a /* SCSI control command		*/
+#define VD_OP_GET_DEVID		0x0b /* Get device ID			*/
+#define VD_OP_GET_EFI		0x0c /* Get EFI				*/
+#define VD_OP_SET_EFI		0x0d /* Set EFI				*/
+	u8			slice;
+	u16			resv1;
+	u32			status;
+	u64			offset;
+	u64			size;
+	u32			ncookies;
+	u32			resv2;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+#define VIO_DISK_VNAME_LEN	8
+#define VIO_DISK_ALABEL_LEN	128
+#define VIO_DISK_NUM_PART	8
+
+struct vio_disk_vtoc {
+	u8			volume_name[VIO_DISK_VNAME_LEN];
+	u16			sector_size;
+	u16			num_partitions;
+	u8			ascii_label[VIO_DISK_ALABEL_LEN];
+	struct {
+		u16		id;
+		u16		perm_flags;
+		u32		resv;
+		u64		start_block;
+		u64		num_blocks;
+	} partitions[VIO_DISK_NUM_PART];
+};
+
+struct vio_disk_geom {
+	u16			num_cyl; /* Num data cylinders		*/
+	u16			alt_cyl; /* Num alternate cylinders	*/
+	u16			beg_cyl; /* Cyl off of fixed head area	*/
+	u16			num_hd;  /* Num heads			*/
+	u16			num_sec; /* Num sectors			*/
+	u16			ifact;   /* Interleave factor		*/
+	u16			apc;     /* Alts per cylinder (SCSI)	*/
+	u16			rpm;	 /* Revolutions per minute	*/
+	u16			phy_cyl; /* Num physical cylinders	*/
+	u16			wr_skip; /* Num sects to skip, writes	*/
+	u16			rd_skip; /* Num sects to skip, writes	*/
+};
+
+struct vio_disk_devid {
+	u16			resv;
+	u16			type;
+	u32			len;
+	char			id[0];
+};
+
+struct vio_disk_efi {
+	u64			lba;
+	u64			len;
+	char			data[0];
+};
+
+/* VIO net specific structures and defines */
+struct vio_net_attr_info {
+	struct vio_msg_tag	tag;
+	u8			xfer_mode;
+	u8			addr_type;
+#define VNET_ADDR_ETHERMAC	0x01
+	u16			ack_freq;
+	u32			resv1;
+	u64			addr;
+	u64			mtu;
+	u64			resv2[3];
+};
+
+#define VNET_NUM_MCAST		7
+
+struct vio_net_mcast_info {
+	struct vio_msg_tag	tag;
+	u8			set;
+	u8			count;
+	u8			mcast_addr[VNET_NUM_MCAST * 6];
+	u32			resv;
+};
+
+struct vio_net_desc {
+	struct vio_dring_hdr	hdr;
+	u32			size;
+	u32			ncookies;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+#define VIO_MAX_RING_COOKIES	24
+
+struct vio_dring_state {
+	u64			ident;
+	void			*base;
+	u64			snd_nxt;
+	u64			rcv_nxt;
+	u32			entry_size;
+	u32			num_entries;
+	u32			prod;
+	u32			cons;
+	u32			pending;
+	int			ncookies;
+	struct ldc_trans_cookie	cookies[VIO_MAX_RING_COOKIES];
+};
+
+static inline void *vio_dring_cur(struct vio_dring_state *dr)
+{
+	return dr->base + (dr->entry_size * dr->prod);
+}
+
+static inline void *vio_dring_entry(struct vio_dring_state *dr,
+				    unsigned int index)
+{
+	return dr->base + (dr->entry_size * index);
+}
+
+static inline u32 vio_dring_avail(struct vio_dring_state *dr,
+				  unsigned int ring_size)
+{
+	/* Ensure build-time power-of-2.  */
+	BUILD_BUG_ON(ring_size & (ring_size - 1));
+
+	return (dr->pending -
+		((dr->prod - dr->cons) & (ring_size - 1)));
+}
+
+#define VIO_MAX_TYPE_LEN	64
+#define VIO_MAX_COMPAT_LEN	64
+
+struct vio_dev {
+	u64			mp;
+	struct device_node	*dp;
+
+	char			type[VIO_MAX_TYPE_LEN];
+	char			compat[VIO_MAX_COMPAT_LEN];
+	int			compat_len;
+
+	unsigned long		channel_id;
+
+	unsigned int		tx_irq;
+	unsigned int		rx_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_version {
+	u16		major;
+	u16		minor;
+};
+
+struct vio_driver_state;
+struct vio_driver_ops {
+	int	(*send_attr)(struct vio_driver_state *vio);
+	int	(*handle_attr)(struct vio_driver_state *vio, void *pkt);
+	void	(*handshake_complete)(struct vio_driver_state *vio);
+};
+
+struct vio_completion {
+	struct completion	com;
+	int			err;
+	int			waiting_for;
+};
+
+struct vio_driver_state {
+	/* Protects VIO handshake and, optionally, driver private state.  */
+	spinlock_t		lock;
+
+	struct ldc_channel	*lp;
+
+	u32			_peer_sid;
+	u32			_local_sid;
+	struct vio_dring_state	drings[2];
+#define VIO_DRIVER_TX_RING	0
+#define VIO_DRIVER_RX_RING	1
+
+	u8			hs_state;
+#define VIO_HS_INVALID		0x00
+#define VIO_HS_GOTVERS		0x01
+#define VIO_HS_GOT_ATTR		0x04
+#define VIO_HS_SENT_DREG	0x08
+#define VIO_HS_SENT_RDX		0x10
+#define VIO_HS_GOT_RDX_ACK	0x20
+#define VIO_HS_GOT_RDX		0x40
+#define VIO_HS_SENT_RDX_ACK	0x80
+#define VIO_HS_COMPLETE		(VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
+
+	u8			dev_class;
+
+	u8			dr_state;
+#define VIO_DR_STATE_TXREG	0x01
+#define VIO_DR_STATE_RXREG	0x02
+#define VIO_DR_STATE_TXREQ	0x10
+#define VIO_DR_STATE_RXREQ	0x20
+
+	u8			debug;
+#define VIO_DEBUG_HS		0x01
+#define VIO_DEBUG_DATA		0x02
+
+	void			*desc_buf;
+	unsigned int		desc_buf_len;
+
+	struct vio_completion	*cmp;
+
+	struct vio_dev		*vdev;
+
+	struct timer_list	timer;
+
+	struct vio_version	ver;
+
+	struct vio_version	*ver_table;
+	int			ver_table_entries;
+
+	char			*name;
+
+	struct vio_driver_ops	*ops;
+};
+
+#define viodbg(TYPE, f, a...) \
+do {	if (vio->debug & VIO_DEBUG_##TYPE) \
+		printk(KERN_INFO "vio: ID[%lu] " f, \
+		       vio->vdev->channel_id, ## a); \
+} while (0)
+
+extern int vio_register_driver(struct vio_driver *drv);
+extern void vio_unregister_driver(struct vio_driver *drv);
+
+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);
+}
+
+extern int vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
+extern void vio_link_state_change(struct vio_driver_state *vio, int event);
+extern void vio_conn_reset(struct vio_driver_state *vio);
+extern int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
+extern int vio_validate_sid(struct vio_driver_state *vio,
+			    struct vio_msg_tag *tp);
+extern u32 vio_send_sid(struct vio_driver_state *vio);
+extern int vio_ldc_alloc(struct vio_driver_state *vio,
+			 struct ldc_channel_config *base_cfg, void *event_arg);
+extern void vio_ldc_free(struct vio_driver_state *vio);
+extern int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+			   u8 dev_class, struct vio_version *ver_table,
+			   int ver_table_size, struct vio_driver_ops *ops,
+			   char *name);
+
+extern void vio_port_up(struct vio_driver_state *vio);
+
+#endif /* _SPARC64_VIO_H */
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 1b1090a..830fc6e 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -175,12 +175,6 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_user(pte_t pte)
-{
-	return((pte_get_bits(pte, _PAGE_USER)) &&
-	       !(pte_get_bits(pte, _PAGE_PROTNONE)));
-}
-
 static inline int pte_read(pte_t pte)
 { 
 	return((pte_get_bits(pte, _PAGE_USER)) &&
@@ -238,18 +232,6 @@
 	return(pte);
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{ 
-	pte_clear_bits(pte, _PAGE_USER);
-	return(pte_mknewprot(pte));
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{ 
-	pte_clear_bits(pte, _PAGE_USER);
-	return(pte_mknewprot(pte));
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_clear_bits(pte, _PAGE_DIRTY);
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 18a13ba..6e5fd5c 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -52,10 +52,21 @@
 	return ti;
 }
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+
+#define alloc_thread_info(tsk) \
+	((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
+						 CONFIG_KERNEL_STACK_ORDER))
+#else
+
 /* thread information allocation */
 #define alloc_thread_info(tsk) \
-	((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
-#define free_thread_info(ti) kfree(ti)
+	((struct thread_info *) __get_free_pages(GFP_KERNEL, \
+						 CONFIG_KERNEL_STACK_ORDER))
+#endif
+
+#define free_thread_info(ti) \
+	free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
 
 #endif
 
diff --git a/include/asm-v850/fb.h b/include/asm-v850/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-v850/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-v850/ioctls.h b/include/asm-v850/ioctls.h
index 05c0dc9..5313abd 100644
--- a/include/asm-v850/ioctls.h
+++ b/include/asm-v850/ioctls.h
@@ -46,6 +46,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
index 35412f7..295d7bf 100644
--- a/include/asm-v850/termbits.h
+++ b/include/asm-v850/termbits.h
@@ -141,6 +141,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -156,10 +157,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define	IBSHIFT	16		/* Shifr from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-v850/termios.h b/include/asm-v850/termios.h
index c2c2b1d..fcd1718 100644
--- a/include/asm-v850/termios.h
+++ b/include/asm-v850/termios.h
@@ -80,8 +80,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h
index b37ab82..53cb96b 100644
--- a/include/asm-x86_64/compat.h
+++ b/include/asm-x86_64/compat.h
@@ -33,8 +33,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64 __attribute__((aligned(4))) compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64 __attribute__((aligned(4))) compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-x86_64/fb.h b/include/asm-x86_64/fb.h
new file mode 100644
index 0000000..60548e6
--- /dev/null
+++ b/include/asm-x86_64/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (boot_cpu_data.x86 > 3)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index e90e167..2acb9b7 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,8 @@
 	VSYSCALL_LAST_PAGE,
 	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
 	VSYSCALL_HPET,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 	FIX_HPET_BASE,
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 	FIX_IO_APIC_BASE_0,
@@ -84,7 +86,7 @@
 	if (idx >= __end_of_fixed_addresses)
 		__this_fixmap_does_not_exist();
 
-        return __fix_to_virt(idx);
+	return __fix_to_virt(idx);
 }
 
 #endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index de2cd9a..7475095 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -144,6 +144,7 @@
  */
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap(volatile void __iomem *addr);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index e327c83..88adf1a 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -48,7 +48,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 /*
  * These are used to make use of C type-checking..
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 0a71e0b..3ba5309 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -266,21 +266,15 @@
  * Undefined behaviour if not..
  */
 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
-static inline int pte_user(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
-static inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
-static inline int pte_exec(pte_t pte)		{ return !(pte_val(pte) & _PAGE_NX); }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_huge(pte_t pte)		{ return pte_val(pte) & _PAGE_PSE; }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
 static inline pte_t pte_mkexec(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX)); return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
@@ -290,13 +284,6 @@
 
 struct vm_area_struct;
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	if (!pte_dirty(*ptep))
-		return 0;
-	return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte);
-}
-
 static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	if (!pte_young(*ptep))
@@ -433,7 +420,6 @@
    (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
diff --git a/include/asm-xtensa/fb.h b/include/asm-xtensa/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-xtensa/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index 2d4b5db..06850f3 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -197,16 +197,13 @@
 
 /* Note: We use the _PAGE_USER bit to indicate write-protect kernel memory */
 
-static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER; }
 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)  { return pte_val(pte) & _PAGE_FILE; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~(_PAGE_RW | _PAGE_WRENABLE); return pte; }
-static inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_RW; return pte; }
@@ -270,17 +267,6 @@
 	return 1;
 }
 
-static inline int
-ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
-   			  pte_t *ptep)
-{
-	pte_t pte = *ptep;
-	if (!pte_dirty(pte))
-		return 0;
-	update_pte(ptep, pte_mkclean(pte));
-	return 1;
-}
-
 static inline pte_t
 ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -421,7 +407,6 @@
 #endif /* !defined (__ASSEMBLY__) */
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTEP_MKDIRTY
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 127d2d1..bcf875e 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -247,7 +247,6 @@
 unifdef-y += isdnif.h
 unifdef-y += isdn_divertif.h
 unifdef-y += isdn_ppp.h
-unifdef-y += isicom.h
 unifdef-y += jbd.h
 unifdef-y += joystick.h
 unifdef-y += kdev_t.h
diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
index 93bfb0b..8ff2749 100644
--- a/include/linux/attribute_container.h
+++ b/include/linux/attribute_container.h
@@ -12,7 +12,6 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/klist.h>
-#include <linux/spinlock.h>
 
 struct attribute_container {
 	struct list_head	node;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index fccc6e5..8ca7ca0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -63,9 +63,12 @@
 #define AUDIT_ADD_RULE		1011	/* Add syscall filtering rule */
 #define AUDIT_DEL_RULE		1012	/* Delete syscall filtering rule */
 #define AUDIT_LIST_RULES	1013	/* List syscall filtering rules */
+#define AUDIT_TTY_GET		1014	/* Get TTY auditing status */
+#define AUDIT_TTY_SET		1015	/* Set TTY auditing status */
 
 #define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages mostly uninteresting to kernel */
 #define AUDIT_USER_AVC		1107	/* We filter this differently */
+#define AUDIT_USER_TTY		1124	/* Non-ICANON TTY input meaning */
 #define AUDIT_LAST_USER_MSG	1199
 #define AUDIT_FIRST_USER_MSG2	2100	/* More user space messages */
 #define AUDIT_LAST_USER_MSG2	2999
@@ -92,6 +95,7 @@
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
 #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
 #define AUDIT_OBJ_PID		1318	/* ptrace target */
+#define AUDIT_TTY		1319	/* Input on an administrative TTY */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -289,6 +293,10 @@
 	__u32		backlog;	/* messages waiting in queue */
 };
 
+struct audit_tty_status {
+	__u32		enabled; /* 1 = enabled, 0 = disabled */
+};
+
 /* audit_rule_data supports filter rules with both integer and string
  * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
  * AUDIT_LIST_RULES requests.
@@ -515,11 +523,13 @@
 					     const char *prefix,
 					     struct dentry *dentry,
 					     struct vfsmount *vfsmnt);
+extern void		    audit_log_lost(const char *message);
 				/* Private API (for audit.c only) */
 extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
 			 void *data, size_t datasz, uid_t loginuid, u32 sid);
+extern int audit_enabled;
 #else
 #define audit_log(c,g,t,f,...) do { ; } while (0)
 #define audit_log_start(c,g,t) ({ NULL; })
@@ -530,6 +540,7 @@
 #define audit_log_untrustedstring(a,s) do { ; } while (0)
 #define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
 #define audit_log_d_path(b,p,d,v) do { ; } while (0)
+#define audit_enabled 0
 #endif
 #endif
 #endif
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index f2542c2..7011d625 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -93,7 +93,6 @@
 void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
 void set_bdi_congested(struct backing_dev_info *bdi, int rw);
 long congestion_wait(int rw, long timeout);
-long congestion_wait_interruptible(int rw, long timeout);
 void congestion_end(int rw);
 
 #define bdi_cap_writeback_dirty(bdi) \
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index fae138b..f78965f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -14,6 +14,7 @@
 #include <linux/bio.h>
 #include <linux/module.h>
 #include <linux/stringify.h>
+#include <linux/bsg.h>
 
 #include <asm/scatterlist.h>
 
@@ -41,6 +42,8 @@
 typedef struct elevator_queue elevator_t;
 struct request_pm_state;
 struct blk_trace;
+struct request;
+struct sg_io_hdr;
 
 #define BLKDEV_MIN_RQ	4
 #define BLKDEV_MAX_RQ	128	/* Default maximum */
@@ -314,6 +317,9 @@
 	 */
 	rq_end_io_fn *end_io;
 	void *end_io_data;
+
+	/* for bidi */
+	struct request *next_rq;
 };
 
 /*
@@ -468,6 +474,10 @@
 	unsigned int		bi_size;
 
 	struct mutex		sysfs_lock;
+
+#if defined(CONFIG_BLK_DEV_BSG)
+	struct bsg_class_device bsg_dev;
+#endif
 };
 
 #define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */
@@ -479,6 +489,7 @@
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
 #define QUEUE_FLAG_ELVSWITCH	8	/* don't use elevator, just do FIFO */
+#define QUEUE_FLAG_BIDI		9	/* queue supports bidi requests */
 
 enum {
 	/*
@@ -543,6 +554,7 @@
 #define blk_sorted_rq(rq)	((rq)->cmd_flags & REQ_SORTED)
 #define blk_barrier_rq(rq)	((rq)->cmd_flags & REQ_HARDBARRIER)
 #define blk_fua_rq(rq)		((rq)->cmd_flags & REQ_FUA)
+#define blk_bidi_rq(rq)		((rq)->next_rq != NULL)
 
 #define list_entry_rq(ptr)	list_entry((ptr), struct request, queuelist)
 
@@ -607,7 +619,12 @@
 #define BLK_BOUNCE_ANY		((u64)blk_max_pfn << PAGE_SHIFT)
 #define BLK_BOUNCE_ISA		(ISA_DMA_THRESHOLD)
 
-#ifdef CONFIG_MMU
+/*
+ * default timeout for SG_IO if none specified
+ */
+#define BLK_DEFAULT_SG_TIMEOUT	(60 * HZ)
+
+#ifdef CONFIG_BOUNCE
 extern int init_emergency_isa_pool(void);
 extern void blk_queue_bounce(request_queue_t *q, struct bio **bio);
 #else
@@ -637,7 +654,8 @@
 extern void blk_plug_device(request_queue_t *);
 extern int blk_remove_plug(request_queue_t *);
 extern void blk_recount_segments(request_queue_t *, struct bio *);
-extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
+extern int scsi_cmd_ioctl(struct file *, struct request_queue *,
+			  struct gendisk *, unsigned int, void __user *);
 extern int sg_scsi_ioctl(struct file *, struct request_queue *,
 		struct gendisk *, struct scsi_ioctl_command __user *);
 
@@ -680,6 +698,12 @@
 			  struct request *, int);
 extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
 				  struct request *, int, rq_end_io_fn *);
+extern int blk_fill_sghdr_rq(request_queue_t *, struct request *,
+		      struct sg_io_hdr *, int);
+extern int blk_unmap_sghdr_rq(struct request *, struct sg_io_hdr *);
+extern int blk_complete_sghdr_rq(struct request *, struct sg_io_hdr *,
+			  struct bio *);
+extern int blk_verify_command(unsigned char *, int);
 
 static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
 {
diff --git a/include/linux/bsg.h b/include/linux/bsg.h
new file mode 100644
index 0000000..bd998ca
--- /dev/null
+++ b/include/linux/bsg.h
@@ -0,0 +1,70 @@
+#ifndef BSG_H
+#define BSG_H
+
+#define BSG_PROTOCOL_SCSI		0
+
+#define BSG_SUB_PROTOCOL_SCSI_CMD	0
+#define BSG_SUB_PROTOCOL_SCSI_TMF	1
+#define BSG_SUB_PROTOCOL_SCSI_TRANSPORT	2
+
+struct sg_io_v4 {
+	__s32 guard;		/* [i] 'Q' to differentiate from v3 */
+	__u32 protocol;		/* [i] 0 -> SCSI , .... */
+	__u32 subprotocol;	/* [i] 0 -> SCSI command, 1 -> SCSI task
+				   management function, .... */
+
+	__u32 request_len;	/* [i] in bytes */
+	__u64 request;		/* [i], [*i] {SCSI: cdb} */
+	__u32 request_attr;	/* [i] {SCSI: task attribute} */
+	__u32 request_tag;	/* [i] {SCSI: task tag (only if flagged)} */
+	__u32 request_priority;	/* [i] {SCSI: task priority} */
+	__u32 max_response_len;	/* [i] in bytes */
+	__u64 response;		/* [i], [*o] {SCSI: (auto)sense data} */
+
+	/* "din_" for data in (from device); "dout_" for data out (to device) */
+	__u32 dout_xfer_len;	/* [i] bytes to be transferred to device */
+	__u32 din_xfer_len;	/* [i] bytes to be transferred from device */
+	__u64 dout_xferp;	/* [i], [*i] */
+	__u64 din_xferp;	/* [i], [*o] */
+
+	__u32 timeout;		/* [i] units: millisecond */
+	__u32 flags;		/* [i] bit mask */
+	__u64 usr_ptr;		/* [i->o] unused internally */
+	__u32 spare_in;		/* [i] */
+
+	__u32 driver_status;	/* [o] 0 -> ok */
+	__u32 transport_status;	/* [o] 0 -> ok */
+	__u32 device_status;	/* [o] {SCSI: command completion status} */
+	__u32 retry_delay;	/* [o] {SCSI: status auxiliary information} */
+	__u32 info;		/* [o] additional information */
+	__u32 duration;		/* [o] time to complete, in milliseconds */
+	__u32 response_len;	/* [o] bytes of response actually written */
+	__s32 din_resid;	/* [o] actual_din_xfer_len - din_xfer_len */
+	__u32 generated_tag;	/* [o] {SCSI: task tag that transport chose} */
+	__u32 spare_out;	/* [o] */
+
+	__u32 padding;
+};
+
+#ifdef __KERNEL__
+
+#if defined(CONFIG_BLK_DEV_BSG)
+struct bsg_class_device {
+	struct class_device *class_dev;
+	struct device *dev;
+	int minor;
+	struct list_head list;
+	struct request_queue *queue;
+};
+
+extern int bsg_register_queue(struct request_queue *, const char *);
+extern void bsg_unregister_queue(struct request_queue *);
+#else
+struct bsg_class_device { };
+#define bsg_register_queue(disk, name)		(0)
+#define bsg_unregister_queue(disk)	do { } while (0)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 42aa0a5..54398d2 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -10,6 +10,8 @@
 	BUG_TRAP_TYPE_BUG = 2,
 };
 
+struct pt_regs;
+
 #ifdef CONFIG_GENERIC_BUG
 #include <asm-generic/bug.h>
 
@@ -20,7 +22,7 @@
 
 const struct bug_entry *find_bug(unsigned long bugaddr);
 
-enum bug_trap_type report_bug(unsigned long bug_addr);
+enum bug_trap_type report_bug(unsigned long bug_addr, struct pt_regs *regs);
 
 int  module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
 			 struct module *);
@@ -31,7 +33,8 @@
 
 #else	/* !CONFIG_GENERIC_BUG */
 
-static inline enum bug_trap_type report_bug(unsigned long bug_addr)
+static inline enum bug_trap_type report_bug(unsigned long bug_addr,
+					    struct pt_regs *regs)
 {
 	return BUG_TRAP_TYPE_BUG;
 }
diff --git a/include/linux/capability.h b/include/linux/capability.h
index bbf8df7..2dfa585 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -44,7 +44,6 @@
   
 #ifdef __KERNEL__
 
-#include <linux/spinlock.h>
 #include <asm/current.h>
 
 /* #define STRICT_CAP_T_TYPECHECKS */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index f50f04b..2b641b1 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -414,8 +414,8 @@
 #define CDO_CHECK_TYPE		0x10    /* check type on open for data */
 
 /* Special codes used when specifying changer slots. */
-#define CDSL_NONE       	((int) (~0U>>1)-1)
-#define CDSL_CURRENT    	((int) (~0U>>1))
+#define CDSL_NONE       	(INT_MAX-1)
+#define CDSL_CURRENT    	INT_MAX
 
 /* For partition based multisession access. IDE can handle 64 partitions
  * per drive - SCSI CD-ROM's use minors to differentiate between the
diff --git a/include/linux/cobalt-nvram.h b/include/linux/cobalt-nvram.h
deleted file mode 100644
index ea42956..0000000
--- a/include/linux/cobalt-nvram.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * $Id: cobalt-nvram.h,v 1.20 2001/10/17 23:16:55 thockin Exp $
- * cobalt-nvram.h : defines for the various fields in the cobalt NVRAM
- *
- * Copyright 2001,2002 Sun Microsystems, Inc.
- */
-
-#ifndef COBALT_NVRAM_H
-#define COBALT_NVRAM_H
-
-#include <linux/nvram.h>
-
-#define COBT_CMOS_INFO_MAX		0x7f	/* top address allowed */
-#define COBT_CMOS_BIOS_DRIVE_INFO	0x12	/* drive info would go here */
-
-#define COBT_CMOS_CKS_START		NVRAM_OFFSET(0x0e)
-#define COBT_CMOS_CKS_END		NVRAM_OFFSET(0x7f)
-
-/* flag bytes - 16 flags for now, leave room for more */
-#define COBT_CMOS_FLAG_BYTE_0		NVRAM_OFFSET(0x10)
-#define COBT_CMOS_FLAG_BYTE_1		NVRAM_OFFSET(0x11)
-
-/* flags in flag bytes - up to 16 */
-#define COBT_CMOS_FLAG_MIN		0x0001
-#define COBT_CMOS_CONSOLE_FLAG		0x0001 /* console on/off */
-#define COBT_CMOS_DEBUG_FLAG		0x0002 /* ROM debug messages */
-#define COBT_CMOS_AUTO_PROMPT_FLAG	0x0004 /* boot to ROM prompt? */
-#define COBT_CMOS_CLEAN_BOOT_FLAG	0x0008 /* set by a clean shutdown */
-#define COBT_CMOS_HW_NOPROBE_FLAG	0x0010 /* go easy on the probing */
-#define COBT_CMOS_SYSFAULT_FLAG		0x0020 /* system fault detected */
-#define COBT_CMOS_OOPSPANIC_FLAG	0x0040 /* panic on oops */
-#define COBT_CMOS_DELAY_CACHE_FLAG	0x0080 /* delay cache initialization */
-#define COBT_CMOS_NOLOGO_FLAG		0x0100 /* hide "C" logo @ boot */
-#define COBT_CMOS_VERSION_FLAG		0x0200 /* the version field is valid */
-#define COBT_CMOS_FLAG_MAX		0x0200
-
-/* leave byte 0x12 blank - Linux looks for drive info here */
-
-/* CMOS structure version, valid if COBT_CMOS_VERSION_FLAG is true */
-#define COBT_CMOS_VERSION		NVRAM_OFFSET(0x13)
-#define COBT_CMOS_VER_BTOCODE		1 /* min. version needed for btocode */
-
-/* index of default boot method */
-#define COBT_CMOS_BOOT_METHOD		NVRAM_OFFSET(0x20)
-#define COBT_CMOS_BOOT_METHOD_DISK	0
-#define COBT_CMOS_BOOT_METHOD_ROM	1
-#define COBT_CMOS_BOOT_METHOD_NET	2
-
-#define COBT_CMOS_BOOT_DEV_MIN		NVRAM_OFFSET(0x21)
-/* major #, minor # of first through fourth boot device */
-#define COBT_CMOS_BOOT_DEV0_MAJ		NVRAM_OFFSET(0x21)
-#define COBT_CMOS_BOOT_DEV0_MIN		NVRAM_OFFSET(0x22)
-#define COBT_CMOS_BOOT_DEV1_MAJ		NVRAM_OFFSET(0x23)
-#define COBT_CMOS_BOOT_DEV1_MIN		NVRAM_OFFSET(0x24)
-#define COBT_CMOS_BOOT_DEV2_MAJ		NVRAM_OFFSET(0x25)
-#define COBT_CMOS_BOOT_DEV2_MIN		NVRAM_OFFSET(0x26)
-#define COBT_CMOS_BOOT_DEV3_MAJ		NVRAM_OFFSET(0x27)
-#define COBT_CMOS_BOOT_DEV3_MIN		NVRAM_OFFSET(0x28)
-#define COBT_CMOS_BOOT_DEV_MAX		NVRAM_OFFSET(0x28)
-
-/* checksum of bytes 0xe-0x7f */
-#define COBT_CMOS_CHECKSUM		NVRAM_OFFSET(0x2e)
-
-/* running uptime counter, units of 5 minutes (32 bits =~ 41000 years) */
-#define COBT_CMOS_UPTIME_0		NVRAM_OFFSET(0x30)
-#define COBT_CMOS_UPTIME_1		NVRAM_OFFSET(0x31)
-#define COBT_CMOS_UPTIME_2		NVRAM_OFFSET(0x32)
-#define COBT_CMOS_UPTIME_3		NVRAM_OFFSET(0x33)
-
-/* count of successful boots (32 bits) */
-#define COBT_CMOS_BOOTCOUNT_0		NVRAM_OFFSET(0x38)
-#define COBT_CMOS_BOOTCOUNT_1		NVRAM_OFFSET(0x39)
-#define COBT_CMOS_BOOTCOUNT_2		NVRAM_OFFSET(0x3a)
-#define COBT_CMOS_BOOTCOUNT_3		NVRAM_OFFSET(0x3b)
-
-/* 13 bytes: system serial number, same as on the back of the system */
-#define COBT_CMOS_SYS_SERNUM_LEN	13
-#define COBT_CMOS_SYS_SERNUM_0		NVRAM_OFFSET(0x40)
-#define COBT_CMOS_SYS_SERNUM_1		NVRAM_OFFSET(0x41)
-#define COBT_CMOS_SYS_SERNUM_2		NVRAM_OFFSET(0x42)
-#define COBT_CMOS_SYS_SERNUM_3		NVRAM_OFFSET(0x43)
-#define COBT_CMOS_SYS_SERNUM_4		NVRAM_OFFSET(0x44)
-#define COBT_CMOS_SYS_SERNUM_5		NVRAM_OFFSET(0x45)
-#define COBT_CMOS_SYS_SERNUM_6		NVRAM_OFFSET(0x46)
-#define COBT_CMOS_SYS_SERNUM_7		NVRAM_OFFSET(0x47)
-#define COBT_CMOS_SYS_SERNUM_8		NVRAM_OFFSET(0x48)
-#define COBT_CMOS_SYS_SERNUM_9		NVRAM_OFFSET(0x49)
-#define COBT_CMOS_SYS_SERNUM_10		NVRAM_OFFSET(0x4a)
-#define COBT_CMOS_SYS_SERNUM_11		NVRAM_OFFSET(0x4b)
-#define COBT_CMOS_SYS_SERNUM_12		NVRAM_OFFSET(0x4c)
-/* checksum for serial num - 1 byte */
-#define COBT_CMOS_SYS_SERNUM_CSUM	NVRAM_OFFSET(0x4f)
-
-#define COBT_CMOS_ROM_REV_MAJ		NVRAM_OFFSET(0x50)
-#define COBT_CMOS_ROM_REV_MIN		NVRAM_OFFSET(0x51)
-#define COBT_CMOS_ROM_REV_REV		NVRAM_OFFSET(0x52)
-
-#define COBT_CMOS_BTO_CODE_0		NVRAM_OFFSET(0x53)
-#define COBT_CMOS_BTO_CODE_1		NVRAM_OFFSET(0x54)
-#define COBT_CMOS_BTO_CODE_2		NVRAM_OFFSET(0x55)
-#define COBT_CMOS_BTO_CODE_3		NVRAM_OFFSET(0x56)
-
-#define COBT_CMOS_BTO_IP_CSUM		NVRAM_OFFSET(0x57)
-#define COBT_CMOS_BTO_IP_0		NVRAM_OFFSET(0x58)
-#define COBT_CMOS_BTO_IP_1		NVRAM_OFFSET(0x59)
-#define COBT_CMOS_BTO_IP_2		NVRAM_OFFSET(0x5a)
-#define COBT_CMOS_BTO_IP_3		NVRAM_OFFSET(0x5b)
-
-#endif /* COBALT_NVRAM_H */
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index fef6f3d..8c6967f 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -40,9 +40,9 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/kref.h>
+#include <linux/mutex.h>
 
 #include <asm/atomic.h>
-#include <asm/semaphore.h>
 
 #define CONFIGFS_ITEM_NAME_LEN	20
 
@@ -75,7 +75,6 @@
 extern void config_item_init_type_name(struct config_item *item,
 				       const char *name,
 				       struct config_item_type *type);
-extern void config_item_cleanup(struct config_item *);
 
 extern struct config_item * config_item_get(struct config_item *);
 extern void config_item_put(struct config_item *);
@@ -87,12 +86,10 @@
 	struct configfs_attribute		**ct_attrs;
 };
 
-
 /**
  *	group - a group of config_items of a specific type, belonging
  *	to a specific subsystem.
  */
-
 struct config_group {
 	struct config_item		cg_item;
 	struct list_head		cg_children;
@@ -100,13 +97,11 @@
 	struct config_group		**default_groups;
 };
 
-
 extern void config_group_init(struct config_group *group);
 extern void config_group_init_type_name(struct config_group *group,
 					const char *name,
 					struct config_item_type *type);
 
-
 static inline struct config_group *to_config_group(struct config_item *item)
 {
 	return item ? container_of(item,struct config_group,cg_item) : NULL;
@@ -122,7 +117,8 @@
 	config_item_put(&group->cg_item);
 }
 
-extern struct config_item *config_group_find_obj(struct config_group *, const char *);
+extern struct config_item *config_group_find_item(struct config_group *,
+						  const char *);
 
 
 struct configfs_attribute {
@@ -131,6 +127,22 @@
 	mode_t			ca_mode;
 };
 
+/*
+ * Users often need to create attribute structures for their configurable
+ * attributes, containing a configfs_attribute member and function pointers
+ * for the show() and store() operations on that attribute. They can use
+ * this macro (similar to sysfs' __ATTR) to make defining attributes easier.
+ */
+#define __CONFIGFS_ATTR(_name, _mode, _show, _store)			\
+{									\
+	.attr	= {							\
+			.ca_name = __stringify(_name),			\
+			.ca_mode = _mode,				\
+			.ca_owner = THIS_MODULE,			\
+	},								\
+	.show	= _show,						\
+	.store	= _store,						\
+}
 
 /*
  * If allow_link() exists, the item can symlink(2) out to other
@@ -157,12 +169,13 @@
 	struct config_item *(*make_item)(struct config_group *group, const char *name);
 	struct config_group *(*make_group)(struct config_group *group, const char *name);
 	int (*commit_item)(struct config_item *item);
+	void (*disconnect_notify)(struct config_group *group, struct config_item *item);
 	void (*drop_item)(struct config_group *group, struct config_item *item);
 };
 
 struct configfs_subsystem {
 	struct config_group	su_group;
-	struct semaphore	su_sem;
+	struct mutex		su_mutex;
 };
 
 static inline struct configfs_subsystem *to_configfs_subsystem(struct config_group *group)
@@ -175,6 +188,11 @@
 int configfs_register_subsystem(struct configfs_subsystem *subsys);
 void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
 
+/* These functions can sleep and can alloc with GFP_KERNEL */
+/* WARNING: These cannot be called underneath configfs callbacks!! */
+int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
+void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target);
+
 #endif  /* __KERNEL__ */
 
 #endif /* _CONFIGFS_H_ */
diff --git a/include/linux/console.h b/include/linux/console.h
index 62ef6e1..56a7bcd 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -15,7 +15,6 @@
 #define _LINUX_CONSOLE_H_ 1
 
 #include <linux/types.h>
-#include <linux/spinlock.h>
 
 struct vc_data;
 struct console_font_op;
@@ -99,6 +98,7 @@
 	struct tty_driver *(*device)(struct console *, int *);
 	void	(*unblank)(void);
 	int	(*setup)(struct console *, char *);
+	int	(*early_setup)(void);
 	short	flags;
 	short	index;
 	int	cflag;
@@ -107,6 +107,7 @@
 };
 
 extern int add_preferred_console(char *name, int idx, char *options);
+extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
 extern void register_console(struct console *);
 extern int unregister_console(struct console *);
 extern struct console *console_drivers;
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h
index 82c9a1f..06b2768 100644
--- a/include/linux/consolemap.h
+++ b/include/linux/consolemap.h
@@ -8,9 +8,12 @@
 #define IBMPC_MAP 2
 #define USER_MAP 3
 
+#include <linux/types.h>
+
 struct vc_data;
 
-extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
+extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
 extern unsigned short *set_translate(int m, struct vc_data *vc);
 extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
+extern u32 conv_8bit_to_uni(unsigned char c);
 void console_map_init(void);
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 3b2df25..c2236bb 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -120,7 +120,6 @@
 
 #define lock_cpu_hotplug()	do { } while (0)
 #define unlock_cpu_hotplug()	do { } while (0)
-#define lock_cpu_hotplug_interruptible() 0
 #define hotcpu_notifier(fn, pri)	do { (void)(fn); } while (0)
 #define register_hotcpu_notifier(nb)	do { (void)(nb); } while (0)
 #define unregister_hotcpu_notifier(nb)	do { (void)(nb); } while (0)
diff --git a/include/linux/crc7.h b/include/linux/crc7.h
new file mode 100644
index 0000000..1786e77
--- /dev/null
+++ b/include/linux/crc7.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_CRC7_H
+#define _LINUX_CRC7_H
+#include <linux/types.h>
+
+extern const u8 crc7_syndrome_table[256];
+
+static inline u8 crc7_byte(u8 crc, u8 data)
+{
+	return crc7_syndrome_table[(crc << 1) ^ data];
+}
+
+extern u8 crc7(u8 crc, const u8 *buffer, size_t len);
+
+#endif
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9a663c6..2dc21cb 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -31,7 +31,11 @@
 		(dma_direction == DMA_FROM_DEVICE));
 }
 
+#ifdef CONFIG_HAS_DMA
 #include <asm/dma-mapping.h>
+#else
+#include <asm-generic/dma-mapping-broken.h>
+#endif
 
 /* Backwards compat, remove in 2.7.x */
 #define dma_sync_single		dma_sync_single_for_cpu
diff --git a/include/linux/ds17287rtc.h b/include/linux/ds17287rtc.h
index c281ba4..d85d3f4 100644
--- a/include/linux/ds17287rtc.h
+++ b/include/linux/ds17287rtc.h
@@ -11,7 +11,6 @@
 #define __LINUX_DS17287RTC_H
 
 #include <linux/rtc.h>			/* get the user-level API */
-#include <linux/spinlock.h>		/* spinlock_t */
 #include <linux/mc146818rtc.h>
 
 /* Register A */
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index dfed800..16cb25c 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -45,6 +45,7 @@
 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp);
 extern struct dentry *efs_get_parent(struct dentry *);
 extern int efs_bmap(struct inode *, int);
 
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
new file mode 100644
index 0000000..8872fe8
--- /dev/null
+++ b/include/linux/exportfs.h
@@ -0,0 +1,126 @@
+#ifndef LINUX_EXPORTFS_H
+#define LINUX_EXPORTFS_H 1
+
+#include <linux/types.h>
+
+struct dentry;
+struct super_block;
+struct vfsmount;
+
+
+/**
+ * struct export_operations - for nfsd to communicate with file systems
+ * @decode_fh:      decode a file handle fragment and return a &struct dentry
+ * @encode_fh:      encode a file handle fragment from a dentry
+ * @get_name:       find the name for a given inode in a given directory
+ * @get_parent:     find the parent of a given directory
+ * @get_dentry:     find a dentry for the inode given a file handle sub-fragment
+ * @find_exported_dentry:
+ *	set by the exporting module to a standard helper function.
+ *
+ * Description:
+ *    The export_operations structure provides a means for nfsd to communicate
+ *    with a particular exported file system  - particularly enabling nfsd and
+ *    the filesystem to co-operate when dealing with file handles.
+ *
+ *    export_operations contains two basic operation for dealing with file
+ *    handles, decode_fh() and encode_fh(), and allows for some other
+ *    operations to be defined which standard helper routines use to get
+ *    specific information from the filesystem.
+ *
+ *    nfsd encodes information use to determine which filesystem a filehandle
+ *    applies to in the initial part of the file handle.  The remainder, termed
+ *    a file handle fragment, is controlled completely by the filesystem.  The
+ *    standard helper routines assume that this fragment will contain one or
+ *    two sub-fragments, one which identifies the file, and one which may be
+ *    used to identify the (a) directory containing the file.
+ *
+ *    In some situations, nfsd needs to get a dentry which is connected into a
+ *    specific part of the file tree.  To allow for this, it passes the
+ *    function acceptable() together with a @context which can be used to see
+ *    if the dentry is acceptable.  As there can be multiple dentrys for a
+ *    given file, the filesystem should check each one for acceptability before
+ *    looking for the next.  As soon as an acceptable one is found, it should
+ *    be returned.
+ *
+ * decode_fh:
+ *    @decode_fh is given a &struct super_block (@sb), a file handle fragment
+ *    (@fh, @fh_len) and an acceptability testing function (@acceptable,
+ *    @context).  It should return a &struct dentry which refers to the same
+ *    file that the file handle fragment refers to,  and which passes the
+ *    acceptability test.  If it cannot, it should return a %NULL pointer if
+ *    the file was found but no acceptable &dentries were available, or a
+ *    %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
+ *    %ENOMEM).
+ *
+ * encode_fh:
+ *    @encode_fh should store in the file handle fragment @fh (using at most
+ *    @max_len bytes) information that can be used by @decode_fh to recover the
+ *    file refered to by the &struct dentry @de.  If the @connectable flag is
+ *    set, the encode_fh() should store sufficient information so that a good
+ *    attempt can be made to find not only the file but also it's place in the
+ *    filesystem.   This typically means storing a reference to de->d_parent in
+ *    the filehandle fragment.  encode_fh() should return the number of bytes
+ *    stored or a negative error code such as %-ENOSPC
+ *
+ * get_name:
+ *    @get_name should find a name for the given @child in the given @parent
+ *    directory.  The name should be stored in the @name (with the
+ *    understanding that it is already pointing to a a %NAME_MAX+1 sized
+ *    buffer.   get_name() should return %0 on success, a negative error code
+ *    or error.  @get_name will be called without @parent->i_mutex held.
+ *
+ * get_parent:
+ *    @get_parent should find the parent directory for the given @child which
+ *    is also a directory.  In the event that it cannot be found, or storage
+ *    space cannot be allocated, a %ERR_PTR should be returned.
+ *
+ * get_dentry:
+ *    Given a &super_block (@sb) and a pointer to a file-system specific inode
+ *    identifier, possibly an inode number, (@inump) get_dentry() should find
+ *    the identified inode and return a dentry for that inode.  Any suitable
+ *    dentry can be returned including, if necessary, a new dentry created with
+ *    d_alloc_root.  The caller can then find any other extant dentrys by
+ *    following the d_alias links.  If a new dentry was created using
+ *    d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
+ *    should be d_rehash()ed.
+ *
+ *    If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
+ *    can be returned.  The @inump will be whatever was passed to
+ *    nfsd_find_fh_dentry() in either the @obj or @parent parameters.
+ *
+ * Locking rules:
+ *    get_parent is called with child->d_inode->i_mutex down
+ *    get_name is not (which is possibly inconsistent)
+ */
+
+struct export_operations {
+	struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh,
+			int fh_len, int fh_type,
+			int (*acceptable)(void *context, struct dentry *de),
+			void *context);
+	int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
+			int connectable);
+	int (*get_name)(struct dentry *parent, char *name,
+			struct dentry *child);
+	struct dentry * (*get_parent)(struct dentry *child);
+	struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
+
+	/* This is set by the exporting module to a standard helper */
+	struct dentry * (*find_exported_dentry)(
+			struct super_block *sb, void *obj, void *parent,
+			int (*acceptable)(void *context, struct dentry *de),
+			void *context);
+};
+
+extern struct dentry *find_exported_dentry(struct super_block *sb, void *obj,
+	void *parent, int (*acceptable)(void *context, struct dentry *de),
+	void *context);
+
+extern int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+	int connectable);
+extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh,
+	int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *),
+	void *context);
+
+#endif /* LINUX_EXPORTFS_H */
diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h
index 4eda0ed..d149f29 100644
--- a/include/linux/ext2_fs_sb.h
+++ b/include/linux/ext2_fs_sb.h
@@ -33,6 +33,8 @@
 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
 	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
 	unsigned long s_groups_count;	/* Number of groups in the fs */
+	unsigned long s_overhead_last;  /* Last calculated overhead */
+	unsigned long s_blocks_last;    /* Last seen block count */
 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
 	struct ext2_super_block * s_es;	/* Pointer to the super block in the buffer */
 	struct buffer_head ** s_group_desc;
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index f61309c..d3c0835 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -38,6 +38,8 @@
 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
 	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
 	unsigned long s_groups_count;	/* Number of groups in the fs */
+	unsigned long s_overhead_last;  /* Last calculated overhead */
+	unsigned long s_blocks_last;    /* Last seen block count */
 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
 	struct ext3_super_block * s_es;	/* Pointer to the super block in the buffer */
 	struct buffer_head ** s_group_desc;
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
index 691a713..2347557 100644
--- a/include/linux/ext4_fs_sb.h
+++ b/include/linux/ext4_fs_sb.h
@@ -39,6 +39,8 @@
 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
 	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
 	unsigned long s_groups_count;	/* Number of groups in the fs */
+	unsigned long s_overhead_last;  /* Last calculated overhead */
+	unsigned long s_blocks_last;    /* Last seen block count */
 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
 	struct ext4_super_block * s_es;	/* Pointer to the super block in the buffer */
 	struct buffer_head ** s_group_desc;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 6622682..cec5410 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -119,6 +119,7 @@
 #define FB_ACCEL_NV_40          46      /* nVidia Arch 40               */
 #define FB_ACCEL_XGI_VOLARI_V	47	/* XGI Volari V3XT, V5, V8      */
 #define FB_ACCEL_XGI_VOLARI_Z	48	/* XGI Volari Z7                */
+#define FB_ACCEL_OMAP1610	49	/* TI OMAP16xx                  */
 #define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92	/* NeoMagic NM2093              */
@@ -529,6 +530,8 @@
 #define FB_EVENT_CONBLANK               0x0C
 /*      Get drawing requirements        */
 #define FB_EVENT_GET_REQ                0x0D
+/*      Unbind from the console if possible */
+#define FB_EVENT_FB_UNBIND              0x0E
 
 struct fb_event {
 	struct fb_info *info;
diff --git a/include/linux/file.h b/include/linux/file.h
index a59001e..0114fbc 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -73,6 +73,7 @@
 extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag));
 extern void put_filp(struct file *);
 extern int get_unused_fd(void);
+extern int get_unused_fd_flags(int flags);
 extern void FASTCALL(put_unused_fd(unsigned int fd));
 struct kmem_cache;
 
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 4631086..2d38b1a 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -1,5 +1,8 @@
 /* Freezer declarations */
 
+#ifndef FREEZER_H_INCLUDED
+#define FREEZER_H_INCLUDED
+
 #include <linux/sched.h>
 
 #ifdef CONFIG_PM
@@ -115,6 +118,14 @@
 	return !!(p->flags & PF_FREEZER_SKIP);
 }
 
+/*
+ * Tell the freezer that the current task should be frozen by it
+ */
+static inline void set_freezable(void)
+{
+	current->flags &= ~PF_NOFREEZE;
+}
+
 #else
 static inline int frozen(struct task_struct *p) { return 0; }
 static inline int freezing(struct task_struct *p) { return 0; }
@@ -130,4 +141,7 @@
 static inline void freezer_do_not_count(void) {}
 static inline void freezer_count(void) {}
 static inline int freezer_should_skip(struct task_struct *p) { return 0; }
+static inline void set_freezable(void) {}
 #endif
+
+#endif	/* FREEZER_H_INCLUDED */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4f0b3bf..58ce336 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -44,7 +44,7 @@
 struct inodes_stat_t {
 	int nr_inodes;
 	int nr_unused;
-	int dummy[5];
+	int dummy[5];		/* padding for sysctl ABI compatibility */
 };
 extern struct inodes_stat_t inodes_stat;
 
@@ -283,11 +283,13 @@
 #include <linux/init.h>
 #include <linux/pid.h>
 #include <linux/mutex.h>
+#include <linux/sysctl.h>
 
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
 
+struct export_operations;
 struct hd_geometry;
 struct iovec;
 struct nameidata;
@@ -820,6 +822,10 @@
 	union {
 		struct nfs_lock_info	nfs_fl;
 		struct nfs4_lock_info	nfs4_fl;
+		struct {
+			struct list_head link;	/* link in AFS vnode's pending_locks list */
+			int state;		/* state of grant or error if -ve */
+		} afs;
 	} fl_u;
 };
 
@@ -1273,119 +1279,6 @@
 
 int sync_inode(struct inode *inode, struct writeback_control *wbc);
 
-/**
- * struct export_operations - for nfsd to communicate with file systems
- * @decode_fh:      decode a file handle fragment and return a &struct dentry
- * @encode_fh:      encode a file handle fragment from a dentry
- * @get_name:       find the name for a given inode in a given directory
- * @get_parent:     find the parent of a given directory
- * @get_dentry:     find a dentry for the inode given a file handle sub-fragment
- * @find_exported_dentry:
- *	set by the exporting module to a standard helper function.
- *
- * Description:
- *    The export_operations structure provides a means for nfsd to communicate
- *    with a particular exported file system  - particularly enabling nfsd and
- *    the filesystem to co-operate when dealing with file handles.
- *
- *    export_operations contains two basic operation for dealing with file
- *    handles, decode_fh() and encode_fh(), and allows for some other
- *    operations to be defined which standard helper routines use to get
- *    specific information from the filesystem.
- *
- *    nfsd encodes information use to determine which filesystem a filehandle
- *    applies to in the initial part of the file handle.  The remainder, termed
- *    a file handle fragment, is controlled completely by the filesystem.  The
- *    standard helper routines assume that this fragment will contain one or
- *    two sub-fragments, one which identifies the file, and one which may be
- *    used to identify the (a) directory containing the file.
- *
- *    In some situations, nfsd needs to get a dentry which is connected into a
- *    specific part of the file tree.  To allow for this, it passes the
- *    function acceptable() together with a @context which can be used to see
- *    if the dentry is acceptable.  As there can be multiple dentrys for a
- *    given file, the filesystem should check each one for acceptability before
- *    looking for the next.  As soon as an acceptable one is found, it should
- *    be returned.
- *
- * decode_fh:
- *    @decode_fh is given a &struct super_block (@sb), a file handle fragment
- *    (@fh, @fh_len) and an acceptability testing function (@acceptable,
- *    @context).  It should return a &struct dentry which refers to the same
- *    file that the file handle fragment refers to,  and which passes the
- *    acceptability test.  If it cannot, it should return a %NULL pointer if
- *    the file was found but no acceptable &dentries were available, or a
- *    %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
- *    %ENOMEM).
- *
- * encode_fh:
- *    @encode_fh should store in the file handle fragment @fh (using at most
- *    @max_len bytes) information that can be used by @decode_fh to recover the
- *    file refered to by the &struct dentry @de.  If the @connectable flag is
- *    set, the encode_fh() should store sufficient information so that a good
- *    attempt can be made to find not only the file but also it's place in the
- *    filesystem.   This typically means storing a reference to de->d_parent in
- *    the filehandle fragment.  encode_fh() should return the number of bytes
- *    stored or a negative error code such as %-ENOSPC
- *
- * get_name:
- *    @get_name should find a name for the given @child in the given @parent
- *    directory.  The name should be stored in the @name (with the
- *    understanding that it is already pointing to a a %NAME_MAX+1 sized
- *    buffer.   get_name() should return %0 on success, a negative error code
- *    or error.  @get_name will be called without @parent->i_mutex held.
- *
- * get_parent:
- *    @get_parent should find the parent directory for the given @child which
- *    is also a directory.  In the event that it cannot be found, or storage
- *    space cannot be allocated, a %ERR_PTR should be returned.
- *
- * get_dentry:
- *    Given a &super_block (@sb) and a pointer to a file-system specific inode
- *    identifier, possibly an inode number, (@inump) get_dentry() should find
- *    the identified inode and return a dentry for that inode.  Any suitable
- *    dentry can be returned including, if necessary, a new dentry created with
- *    d_alloc_root.  The caller can then find any other extant dentrys by
- *    following the d_alias links.  If a new dentry was created using
- *    d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
- *    should be d_rehash()ed.
- *
- *    If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
- *    can be returned.  The @inump will be whatever was passed to
- *    nfsd_find_fh_dentry() in either the @obj or @parent parameters.
- *
- * Locking rules:
- *    get_parent is called with child->d_inode->i_mutex down
- *    get_name is not (which is possibly inconsistent)
- */
-
-struct export_operations {
-	struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
-			 int (*acceptable)(void *context, struct dentry *de),
-			 void *context);
-	int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
-			 int connectable);
-
-	/* the following are only called from the filesystem itself */
-	int (*get_name)(struct dentry *parent, char *name,
-			struct dentry *child);
-	struct dentry * (*get_parent)(struct dentry *child);
-	struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
-
-	/* This is set by the exporting module to a standard helper */
-	struct dentry * (*find_exported_dentry)(
-		struct super_block *sb, void *obj, void *parent,
-		int (*acceptable)(void *context, struct dentry *de),
-		void *context);
-
-
-};
-
-extern struct dentry *
-find_exported_dentry(struct super_block *sb, void *obj, void *parent,
-		     int (*acceptable)(void *context, struct dentry *de),
-		     void *context);
-
 struct file_system_type {
 	const char *name;
 	int fs_flags;
@@ -1522,7 +1415,7 @@
 
 #ifdef CONFIG_BLOCK
 extern int register_blkdev(unsigned int, const char *);
-extern int unregister_blkdev(unsigned int, const char *);
+extern void unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern void bd_set_size(struct block_device *, loff_t size);
 extern void bd_forget(struct inode *inode);
@@ -1610,6 +1503,9 @@
 extern int invalidate_partition(struct gendisk *, int);
 #endif
 extern int invalidate_inodes(struct super_block *);
+unsigned long __invalidate_mapping_pages(struct address_space *mapping,
+					pgoff_t start, pgoff_t end,
+					bool be_atomic);
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
 					pgoff_t start, pgoff_t end);
 
@@ -2043,5 +1939,9 @@
 { }
 #endif	/* CONFIG_SECURITY */
 
+int proc_nr_files(ctl_table *table, int write, struct file *filp,
+		  void __user *buffer, size_t *lenp, loff_t *ppos);
+
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_FS_H */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 73710d6..695741b 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -112,7 +112,7 @@
 struct fsl_spi_platform_data {
 	u32 	initial_spmode;	/* initial SPMODE value */
 	u16	bus_num;
-
+	bool	qe_mode;
 	/* board specific information */
 	u16	max_chipselect;
 	void	(*activate_cs)(u8 cs, u8 polarity);
@@ -120,5 +120,10 @@
 	u32	sysclk;
 };
 
+struct mpc8xx_pcmcia_ops {
+	void(*hw_ctrl)(int slot, int enable);
+	int(*voltage_set)(int slot, int vcc, int vpp);
+};
+
 #endif /* _FSL_DEVICE_H_ */
 #endif /* __KERNEL__ */
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 534744e..9fbe9d2 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -339,7 +339,7 @@
 	char name[0];
 };
 
-#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name)
+#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
 #define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
 #define FUSE_DIRENT_SIZE(d) \
 	FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 0d2ef0b..bc68dd9 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -30,6 +30,9 @@
  * cannot handle allocation failures.
  *
  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
+ *
+ * __GFP_MOVABLE: Flag that this page will be movable by the page migration
+ * mechanism or reclaimed
  */
 #define __GFP_WAIT	((__force gfp_t)0x10u)	/* Can wait and reschedule? */
 #define __GFP_HIGH	((__force gfp_t)0x20u)	/* Should access emergency pools? */
@@ -45,6 +48,7 @@
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
 #define __GFP_THISNODE	((__force gfp_t)0x40000u)/* No fallback, no policies */
+#define __GFP_MOVABLE	((__force gfp_t)0x80000u) /* Page is movable */
 
 #define __GFP_BITS_SHIFT 20	/* Room for 20 __GFP_FOO bits */
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
@@ -53,7 +57,8 @@
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
 			__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
 			__GFP_NOFAIL|__GFP_NORETRY|__GFP_COMP| \
-			__GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE)
+			__GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE| \
+			__GFP_MOVABLE)
 
 /* This equals 0, but use constants in case they ever change */
 #define GFP_NOWAIT	(GFP_ATOMIC & ~__GFP_HIGH)
@@ -65,6 +70,15 @@
 #define GFP_USER	(__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
 #define GFP_HIGHUSER	(__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
 			 __GFP_HIGHMEM)
+#define GFP_HIGHUSER_MOVABLE	(__GFP_WAIT | __GFP_IO | __GFP_FS | \
+				 __GFP_HARDWALL | __GFP_HIGHMEM | \
+				 __GFP_MOVABLE)
+#define GFP_NOFS_PAGECACHE	(__GFP_WAIT | __GFP_IO | __GFP_MOVABLE)
+#define GFP_USER_PAGECACHE	(__GFP_WAIT | __GFP_IO | __GFP_FS | \
+				 __GFP_HARDWALL | __GFP_MOVABLE)
+#define GFP_HIGHUSER_PAGECACHE	(__GFP_WAIT | __GFP_IO | __GFP_FS | \
+				 __GFP_HARDWALL | __GFP_HIGHMEM | \
+				 __GFP_MOVABLE)
 
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE	(__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
@@ -92,6 +106,9 @@
 	if (flags & __GFP_DMA32)
 		return ZONE_DMA32;
 #endif
+	if ((flags & (__GFP_HIGHMEM | __GFP_MOVABLE)) ==
+			(__GFP_HIGHMEM | __GFP_MOVABLE))
+		return ZONE_MOVABLE;
 #ifdef CONFIG_HIGHMEM
 	if (flags & __GFP_HIGHMEM)
 		return ZONE_HIGHMEM;
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 98e2cce..12c5e4e 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -73,10 +73,27 @@
 }
 
 #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+/**
+ * __alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA with caller-specified movable GFP flags
+ * @movableflags: The GFP flags related to the pages future ability to move like __GFP_MOVABLE
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA but the caller is expected
+ * to specify via movableflags whether the page will be movable in the
+ * future or not
+ *
+ * An architecture may override this function by defining
+ * __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE and providing their own
+ * implementation.
+ */
 static inline struct page *
-alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+__alloc_zeroed_user_highpage(gfp_t movableflags,
+			struct vm_area_struct *vma,
+			unsigned long vaddr)
 {
-	struct page *page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
+	struct page *page = alloc_page_vma(GFP_HIGHUSER | movableflags,
+			vma, vaddr);
 
 	if (page)
 		clear_user_highpage(page, vaddr);
@@ -85,6 +102,36 @@
 }
 #endif
 
+/**
+ * alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA that the caller knows will
+ * not be able to move in the future using move_pages() or reclaim. If it
+ * is known that the page can move, use alloc_zeroed_user_highpage_movable
+ */
+static inline struct page *
+alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+{
+	return __alloc_zeroed_user_highpage(0, vma, vaddr);
+}
+
+/**
+ * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA that the caller knows will
+ * be able to migrate in the future using move_pages() or reclaimed
+ */
+static inline struct page *
+alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
+					unsigned long vaddr)
+{
+	return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
+}
+
 static inline void clear_highpage(struct page *page)
 {
 	void *kaddr = kmap_atomic(page, KM_USER0);
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 17c29dc..540799b 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -329,12 +329,13 @@
 #ifdef CONFIG_TIMER_STATS
 
 extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-				     void *timerf, char * comm);
+				     void *timerf, char *comm,
+				     unsigned int timer_flag);
 
 static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
 {
 	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
-				 timer->function, timer->start_comm);
+				 timer->function, timer->start_comm, 0);
 }
 
 extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 2c13715..49b7053 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -15,6 +15,7 @@
 }
 
 int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
+int hugetlb_treat_movable_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 unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
@@ -29,6 +30,7 @@
 void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
 
 extern unsigned long max_huge_pages;
+extern unsigned long hugepages_treat_as_movable;
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
 extern int sysctl_hugetlb_shm_group;
 
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index 52f53e2..333a370 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>	/* work_struct */
 #include <linux/mempool.h>
+#include <linux/mutex.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>	/* Needed for MUTEX init macros */
@@ -425,7 +426,7 @@
 
 	struct device device;
 
-	struct semaphore lock;	/* device lock */
+	struct mutex lock;	/* device lock */
 };
 
 /*
@@ -544,7 +545,7 @@
 	struct i2o_dma hrt;	/* HW Resource Table */
 	i2o_lct *lct;		/* Logical Config Table */
 	struct i2o_dma dlct;	/* Temp LCT */
-	struct semaphore lct_lock;	/* Lock for LCT updates */
+	struct mutex lct_lock;	/* Lock for LCT updates */
 	struct i2o_dma status_block;	/* IOP status block */
 
 	struct i2o_io base;	/* controller messaging unit */
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 915572f..0edda41 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -78,8 +78,11 @@
 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);
+int idr_for_each(struct idr *idp,
+		 int (*fn)(int id, void *p, void *data), void *data);
 void *idr_replace(struct idr *idp, void *ptr, int id);
 void idr_remove(struct idr *idp, int id);
+void idr_remove_all(struct idr *idp);
 void idr_destroy(struct idr *idp);
 void idr_init(struct idr *idp);
 
diff --git a/include/linux/init.h b/include/linux/init.h
index 56ec4c6..5b52853 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -171,9 +171,6 @@
 #define __setup(str, fn)					\
 	__setup_param(str, fn, fn, 0)
 
-#define __obsolete_setup(str)					\
-	__setup_null_param(str, __LINE__)
-
 /* NOTE: fn is as per module_param, not __setup!  Emits warning if fn
  * returns non-zero. */
 #define early_param(str, fn)					\
@@ -239,7 +236,6 @@
 #define __setup_param(str, unique_id, fn)	/* nothing */
 #define __setup_null_param(str, unique_id) 	/* nothing */
 #define __setup(str, func) 			/* nothing */
-#define __obsolete_setup(str) 			/* nothing */
 #endif
 
 /* Data marked not to be saved by software suspend */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 276ccaa..cab741c 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -8,6 +8,7 @@
 #include <linux/lockdep.h>
 #include <linux/ipc.h>
 #include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
 
 #define INIT_FDTABLE \
 {							\
@@ -78,6 +79,7 @@
 	.uts_ns		= &init_uts_ns,					\
 	.mnt_ns		= NULL,						\
 	INIT_IPC_NS(ipc_ns)						\
+	.user_ns	= &init_user_ns,				\
 }
 
 #define INIT_SIGHAND(sighand) {						\
diff --git a/include/linux/io.h b/include/linux/io.h
index 8423dd3..e3b2dda 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -63,32 +63,7 @@
 void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
 				    unsigned long size);
 void devm_iounmap(struct device *dev, void __iomem *addr);
-
-/**
- *	check_signature		-	find BIOS signatures
- *	@io_addr: mmio address to check
- *	@signature:  signature block
- *	@length: length of signature
- *
- *	Perform a signature comparison with the mmio address io_addr. This
- *	address should have been obtained by ioremap.
- *	Returns 1 on a match.
- */
-
-static inline int check_signature(const volatile void __iomem *io_addr,
-	const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
+int check_signature(const volatile void __iomem *io_addr,
+			const unsigned char *signature, int length);
 
 #endif /* _LINUX_IO_H */
diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 1980867..3fd3ddd 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -52,6 +52,7 @@
 #ifdef __KERNEL__
 
 #include <linux/kref.h>
+#include <linux/spinlock.h>
 
 #define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
 
@@ -92,6 +93,7 @@
 
 #ifdef CONFIG_SYSVIPC
 #define INIT_IPC_NS(ns)		.ns		= &init_ipc_ns,
+extern void free_ipc_ns(struct kref *kref);
 extern struct ipc_namespace *copy_ipcs(unsigned long flags,
 						struct ipc_namespace *ns);
 #else
@@ -103,13 +105,9 @@
 }
 #endif
 
-#ifdef CONFIG_IPC_NS
-extern void free_ipc_ns(struct kref *kref);
-#endif
-
 static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
 {
-#ifdef CONFIG_IPC_NS
+#ifdef CONFIG_SYSVIPC
 	if (ns)
 		kref_get(&ns->kref);
 #endif
@@ -118,7 +116,7 @@
 
 static inline void put_ipc_ns(struct ipc_namespace *ns)
 {
-#ifdef CONFIG_IPC_NS
+#ifdef CONFIG_SYSVIPC
 	kref_put(&ns->kref, free_ipc_ns);
 #endif
 }
@@ -126,5 +124,3 @@
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_IPC_H */
-
-
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1695054..4465719 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -161,6 +161,7 @@
 	unsigned int		wake_depth;	/* nested wake enables */
 	unsigned int		irq_count;	/* For detecting broken IRQs */
 	unsigned int		irqs_unhandled;
+	unsigned long		last_unhandled;	/* Aging timer for unhandled count */
 	spinlock_t		lock;
 #ifdef CONFIG_SMP
 	cpumask_t		affinity;
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 5f06527..f73de6f 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -7,9 +7,9 @@
 
 #include <linux/errno.h>
 
-#define KSYM_NAME_LEN 127
-#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN +	\
-			 2*(BITS_PER_LONG*3/10) + MODULE_NAME_LEN + 1)
+#define KSYM_NAME_LEN 128
+#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
+			 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
 
 #ifdef CONFIG_KALLSYMS
 /* Lookup the address for a symbol. Returns 0 if not found. */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 7a48525..1eb9cde 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -210,6 +210,7 @@
 #define TAINT_MACHINE_CHECK		(1<<4)
 #define TAINT_BAD_PAGE			(1<<5)
 #define TAINT_USER			(1<<6)
+#define TAINT_DIE			(1<<7)
 
 extern void dump_stack(void);
 
diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
index aea34e74..8c4350a 100644
--- a/include/linux/kernelcapi.h
+++ b/include/linux/kernelcapi.h
@@ -64,7 +64,7 @@
 	unsigned long nrecvdatapkt;
 	unsigned long nsentctlpkt;
 	unsigned long nsentdatapkt;
-	struct semaphore recv_sem;
+	struct mutex recv_mtx;
 	struct sk_buff_head recv_queue;
 	struct work_struct recv_work;
 	int release_in_progress;
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 88afcef..494bed7 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -13,7 +13,6 @@
 #define __LINUX_LEDS_H_INCLUDED
 
 #include <linux/list.h>
-#include <linux/spinlock.h>
 
 struct device;
 struct class_device;
diff --git a/include/linux/limits.h b/include/linux/limits.h
index eaf2e09..2d0f941 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -5,8 +5,6 @@
 
 #define NGROUPS_MAX    65536	/* supplemental group IDs are available */
 #define ARG_MAX       131072	/* # bytes of args + environ for exec() */
-#define CHILD_MAX        999    /* no limit :-) */
-#define OPEN_MAX         256	/* # open files a process may have */
 #define LINK_MAX         127	/* # links a file may have */
 #define MAX_CANON        255	/* size of the canonical input queue */
 #define MAX_INPUT        255	/* size of the type-ahead buffer */
diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h
index 9c01bde..08a9296 100644
--- a/include/linux/linux_logo.h
+++ b/include/linux/linux_logo.h
@@ -33,5 +33,13 @@
 };
 
 extern const struct linux_logo *fb_find_logo(int depth);
+#ifdef CONFIG_FB_LOGO_EXTRA
+extern void fb_append_extra_logo(const struct linux_logo *logo,
+				 unsigned int n);
+#else
+static inline void fb_append_extra_logo(const struct linux_logo *logo,
+					unsigned int n)
+{}
+#endif
 
 #endif /* _LINUX_LINUX_LOGO_H */
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 246de1d..6f1637c 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -27,6 +27,7 @@
 						struct nfs_fh *,
 						struct file **);
 	void			(*fclose)(struct file *);
+	unsigned long		(*get_grace_period)(void);
 };
 
 extern struct nlmsvc_binding *	nlmsvc_ops;
@@ -38,4 +39,12 @@
 extern int	lockd_up(int proto);
 extern void	lockd_down(void);
 
+unsigned long get_nfs_grace_period(void);
+
+#ifdef CONFIG_NFSD_V4
+unsigned long get_nfs4_grace_period(void);
+#else
+static inline unsigned long get_nfs4_grace_period(void) {return 0;}
+#endif
+
 #endif /* LINUX_LOCKD_BIND_H */
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
index 582d8b7..d793497 100644
--- a/include/linux/lzo.h
+++ b/include/linux/lzo.h
@@ -17,7 +17,7 @@
 #define LZO1X_MEM_COMPRESS	(16384 * sizeof(unsigned char *))
 #define LZO1X_1_MEM_COMPRESS	LZO1X_MEM_COMPRESS
 
-#define lzo1x_worst_compress(x) (x + (x / 64) + 16 + 3)
+#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
 
 /* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
 int lzo1x_1_compress(const unsigned char *src, size_t src_len,
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index daabb3a..e147cf5 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -159,7 +159,7 @@
 
 extern struct mempolicy default_policy;
 extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
-		unsigned long addr);
+		unsigned long addr, gfp_t gfp_flags);
 extern unsigned slab_node(struct mempolicy *policy);
 
 extern enum zone_type policy_zone;
@@ -256,9 +256,9 @@
 #define set_cpuset_being_rebound(x) do {} while (0)
 
 static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
-		unsigned long addr)
+		unsigned long addr, gfp_t gfp_flags)
 {
-	return NODE_DATA(0)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+	return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
 }
 
 static inline int do_migrate_pages(struct mm_struct *mm,
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1c12074..a5c4518 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,7 +2,6 @@
 #define _LINUX_MM_H
 
 #include <linux/errno.h>
-#include <linux/capability.h>
 
 #ifdef __KERNEL__
 
@@ -27,7 +26,6 @@
 
 extern unsigned long num_physpages;
 extern void * high_memory;
-extern unsigned long vmalloc_earlyreserve;
 extern int page_cluster;
 
 #ifdef CONFIG_SYSCTL
@@ -601,6 +599,7 @@
 {
 	struct address_space *mapping = page->mapping;
 
+	VM_BUG_ON(PageSlab(page));
 	if (unlikely(PageSwapCache(page)))
 		mapping = &swapper_space;
 #ifdef CONFIG_SLUB
@@ -812,27 +811,31 @@
 			       unsigned long flags, unsigned long new_addr);
 
 /*
- * Prototype to add a shrinker callback for ageable caches.
- * 
- * These functions are passed a count `nr_to_scan' and a gfpmask.  They should
- * scan `nr_to_scan' objects, attempting to free them.
+ * A callback you can register to apply pressure to ageable caches.
  *
- * The callback must return the number of objects which remain in the cache.
+ * 'shrink' is passed a count 'nr_to_scan' and a 'gfpmask'.  It should
+ * look through the least-recently-used 'nr_to_scan' entries and
+ * attempt to free them up.  It should return the number of objects
+ * which remain in the cache.  If it returns -1, it means it cannot do
+ * any scanning at this time (eg. there is a risk of deadlock).
  *
- * 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.
+ * The 'gfpmask' refers to the allocation we are currently trying to
+ * fulfil.
+ *
+ * Note that 'shrink' 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, gfp_t gfp_mask);
+struct shrinker {
+	int (*shrink)(int nr_to_scan, gfp_t gfp_mask);
+	int seeks;	/* seeks to recreate an obj */
 
-/*
- * Add an aging callback.  The int is the number of 'seeks' it takes
- * to recreate one of the objects that these functions age.
- */
-
-#define DEFAULT_SEEKS 2
-struct shrinker;
-extern struct shrinker *set_shrinker(int, shrinker_t);
-extern void remove_shrinker(struct shrinker *shrinker);
+	/* These are for internal use */
+	struct list_head list;
+	long nr;	/* objs pending delete */
+};
+#define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
+extern void register_shrinker(struct shrinker *);
+extern void unregister_shrinker(struct shrinker *);
 
 /*
  * Some shared mappigns will want the pages marked read-only
@@ -1072,6 +1075,10 @@
 extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
 	unsigned long flag, unsigned long pgoff);
+extern unsigned long mmap_region(struct file *file, unsigned long addr,
+	unsigned long len, unsigned long flags,
+	unsigned int vm_flags, unsigned long pgoff,
+	int accountable);
 
 static inline unsigned long do_mmap(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index d09b134..da8eb8a 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -24,6 +24,14 @@
 #endif
 #define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
 
+/*
+ * PAGE_ALLOC_COSTLY_ORDER is the order at which allocations are deemed
+ * costly to service.  That is between allocation orders which should
+ * coelesce naturally under reasonable reclaim pressure and those which
+ * will not.
+ */
+#define PAGE_ALLOC_COSTLY_ORDER 3
+
 struct free_area {
 	struct list_head	free_list;
 	unsigned long		nr_free;
@@ -146,6 +154,7 @@
 	 */
 	ZONE_HIGHMEM,
 #endif
+	ZONE_MOVABLE,
 	MAX_NR_ZONES
 };
 
@@ -167,6 +176,7 @@
 	+ defined(CONFIG_ZONE_DMA32)	\
 	+ 1				\
 	+ defined(CONFIG_HIGHMEM)	\
+	+ 1				\
 )
 #if __ZONE_COUNT < 2
 #define ZONES_SHIFT 0
@@ -499,10 +509,22 @@
 	return (!!zone->present_pages);
 }
 
+extern int movable_zone;
+
+static inline int zone_movable_is_highmem(void)
+{
+#if defined(CONFIG_HIGHMEM) && defined(CONFIG_ARCH_POPULATES_NODE_MAP)
+	return movable_zone == ZONE_HIGHMEM;
+#else
+	return 0;
+#endif
+}
+
 static inline int is_highmem_idx(enum zone_type idx)
 {
 #ifdef CONFIG_HIGHMEM
-	return (idx == ZONE_HIGHMEM);
+	return (idx == ZONE_HIGHMEM ||
+		(idx == ZONE_MOVABLE && zone_movable_is_highmem()));
 #else
 	return 0;
 #endif
@@ -522,7 +544,9 @@
 static inline int is_highmem(struct zone *zone)
 {
 #ifdef CONFIG_HIGHMEM
-	return zone == zone->zone_pgdat->node_zones + ZONE_HIGHMEM;
+	int zone_idx = zone - zone->zone_pgdat->node_zones;
+	return zone_idx == ZONE_HIGHMEM ||
+		(zone_idx == ZONE_MOVABLE && zone_movable_is_highmem());
 #else
 	return 0;
 #endif
@@ -566,6 +590,11 @@
 int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int,
 			struct file *, void __user *, size_t *, loff_t *);
 
+extern int numa_zonelist_order_handler(struct ctl_table *, int,
+			struct file *, void __user *, size_t *, loff_t *);
+extern char numa_zonelist_order[];
+#define NUMA_ZONELIST_ORDER_LEN 16	/* string buffer size */
+
 #include <linux/topology.h>
 /* Returns the number of the current Node. */
 #ifndef numa_node_id
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 1fa4d98..8eed44f 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -14,7 +14,7 @@
 	int event;
 };
 
-extern struct mnt_namespace *copy_mnt_ns(int, struct mnt_namespace *,
+extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
 		struct fs_struct *);
 extern void __put_mnt_ns(struct mnt_namespace *ns);
 
diff --git a/include/linux/module.h b/include/linux/module.h
index e6e0f86..b6a646c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -6,7 +6,6 @@
  * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
  * Rewritten again by Rusty Russell, 2002
  */
-#include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/stat.h>
 #include <linux/compiler.h>
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 0e09c00..f950921 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -146,7 +146,7 @@
 };
 
 struct msdos_dir_entry {
-	__u8	name[8],ext[3];	/* name and extension */
+	__u8	name[MSDOS_NAME];/* name and extension */
 	__u8	attr;		/* attribute bits */
 	__u8    lcase;		/* Case for base and extension */
 	__u8	ctime_cs;	/* Creation time, centiseconds (0-199) */
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 83e39eb..88766e4 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -148,8 +148,6 @@
 #include <linux/ncp_fs_i.h>
 #include <linux/ncp_fs_sb.h>
 
-/* undef because public define in umsdos_fs.h (ncp_fs.h isn't public) */
-#undef PRINTK
 /* define because it is easy to change PRINTK to {*}PRINTK */
 #define PRINTK(format, args...) printk(KERN_DEBUG format , ## args)
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 322b5ea..da7a13c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -262,8 +262,6 @@
 	__LINK_STATE_LINKWATCH_PENDING,
 	__LINK_STATE_DORMANT,
 	__LINK_STATE_QDISC_RUNNING,
-	/* Set by the netpoll NAPI code */
-	__LINK_STATE_POLL_LIST_FROZEN,
 };
 
 
@@ -1022,14 +1020,6 @@
 {
 	unsigned long flags;
 
-#ifdef CONFIG_NETPOLL
-	/* Prevent race with netpoll - yes, this is a kludge.
-	 * But at least it doesn't penalize the non-netpoll
-	 * code path. */
-	if (test_bit(__LINK_STATE_POLL_LIST_FROZEN, &dev->state))
-		return;
-#endif
-
 	local_irq_save(flags);
 	__netif_rx_complete(dev);
 	local_irq_restore(flags);
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 9f62d61..78feb7b 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -42,6 +42,9 @@
 #define	NFSEXP_NOACL		0x8000	/* reserved for possible ACL related use */
 #define NFSEXP_ALLFLAGS		0xFE3F
 
+/* The flags that may vary depending on security flavor: */
+#define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
+					| NFSEXP_ALLSQUASH)
 
 #ifdef __KERNEL__
 
@@ -64,6 +67,19 @@
 	int migrated;
 };
 
+/*
+ * We keep an array of pseudoflavors with the export, in order from most
+ * to least preferred.  For the forseeable future, we don't expect more
+ * than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3,
+ * spkm3i, and spkm3p (and using all 8 at once should be rare).
+ */
+#define MAX_SECINFO_LIST	8
+
+struct exp_flavor_info {
+	u32	pseudoflavor;
+	u32	flags;
+};
+
 struct svc_export {
 	struct cache_head	h;
 	struct auth_domain *	ex_client;
@@ -76,6 +92,8 @@
 	int			ex_fsid;
 	unsigned char *		ex_uuid; /* 16 byte fsid */
 	struct nfsd4_fs_locations ex_fslocs;
+	int			ex_nflavors;
+	struct exp_flavor_info	ex_flavors[MAX_SECINFO_LIST];
 };
 
 /* an "export key" (expkey) maps a filehandlefragement to an
@@ -95,10 +113,22 @@
 
 #define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
 #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
-#define EX_RDONLY(exp)		((exp)->ex_flags & NFSEXP_READONLY)
 #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
 #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
 
+static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (f->pseudoflavor == rqstp->rq_flavor)
+			return f->flags & NFSEXP_READONLY;
+	}
+	return exp->ex_flags & NFSEXP_READONLY;
+}
+
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
 
 /*
  * Function declarations
@@ -112,13 +142,19 @@
 					struct vfsmount *mnt,
 					struct dentry *dentry,
 					struct cache_req *reqp);
+struct svc_export *	rqst_exp_get_by_name(struct svc_rqst *,
+					     struct vfsmount *,
+					     struct dentry *);
 struct svc_export *	exp_parent(struct auth_domain *clp,
 				   struct vfsmount *mnt,
 				   struct dentry *dentry,
 				   struct cache_req *reqp);
+struct svc_export *	rqst_exp_parent(struct svc_rqst *,
+					struct vfsmount *mnt,
+					struct dentry *dentry);
 int			exp_rootfh(struct auth_domain *, 
 					char *path, struct knfsd_fh *, int maxsize);
-__be32			exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
+__be32			exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
 __be32			nfserrno(int errno);
 
 extern struct cache_detail svc_export_cache;
@@ -135,6 +171,7 @@
 extern struct svc_export *
 exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
 	 struct cache_req *reqp);
+struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/nfsd/interface.h b/include/linux/nfsd/interface.h
deleted file mode 100644
index af09797..0000000
--- a/include/linux/nfsd/interface.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * include/linux/nfsd/interface.h
- *
- * defines interface between nfsd and other bits of
- * the kernel.  Particularly filesystems (eventually).
- *
- * Copyright (C) 2000 Neil Brown <neilb@cse.unsw.edu.au>
- */
-
-#ifndef LINUX_NFSD_INTERFACE_H
-#define LINUX_NFSD_INTERFACE_H
-
-#endif /* LINUX_NFSD_INTERFACE_H */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 72feac5..e452256 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -22,7 +22,6 @@
 #include <linux/nfsd/export.h>
 #include <linux/nfsd/auth.h>
 #include <linux/nfsd/stats.h>
-#include <linux/nfsd/interface.h>
 /*
  * nfsd version
  */
@@ -72,6 +71,9 @@
 		                struct svc_export **expp);
 __be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
 				const char *, int, struct svc_fh *);
+__be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
+				const char *, int,
+				struct svc_export **, struct dentry **);
 __be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
 				struct iattr *, int, time_t);
 #ifdef CONFIG_NFSD_V4
@@ -120,7 +122,8 @@
 				struct kstatfs *);
 
 int		nfsd_notify_change(struct inode *, struct iattr *);
-__be32		nfsd_permission(struct svc_export *, struct dentry *, int);
+__be32		nfsd_permission(struct svc_rqst *, struct svc_export *,
+				struct dentry *, int);
 int		nfsd_sync_dir(struct dentry *dp);
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
@@ -149,6 +152,7 @@
  * NFSv4 State
  */
 #ifdef CONFIG_NFSD_V4
+extern unsigned int max_delegations;
 void nfs4_state_init(void);
 int nfs4_state_start(void);
 void nfs4_state_shutdown(void);
@@ -236,6 +240,7 @@
 #define	nfserr_badname		__constant_htonl(NFSERR_BADNAME)
 #define	nfserr_cb_path_down	__constant_htonl(NFSERR_CB_PATH_DOWN)
 #define	nfserr_locked		__constant_htonl(NFSERR_LOCKED)
+#define	nfserr_wrongsec		__constant_htonl(NFSERR_WRONGSEC)
 #define	nfserr_replay_me	__constant_htonl(NFSERR_REPLAY_ME)
 
 /* error codes for internal use */
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index ab5c236..db348f7 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -67,7 +67,7 @@
 	int			cbr_trunc;
 	stateid_t		cbr_stateid;
 	u32			cbr_fhlen;
-	u32			cbr_fhval[NFS4_FHSIZE];
+	char			cbr_fhval[NFS4_FHSIZE];
 	struct nfs4_delegation	*cbr_dp;
 };
 
@@ -224,6 +224,7 @@
 	struct inode		*fi_inode;
 	u32                     fi_id;      /* used with stateowner->so_id 
 					     * for stateid_hashtbl hash */
+	bool			fi_had_conflict;
 };
 
 /*
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 09799bc..1b65326 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -293,6 +293,12 @@
 	struct nfsd4_change_info  rn_tinfo; /* response */
 };
 
+struct nfsd4_secinfo {
+	u32 si_namelen;					/* request */
+	char *si_name;					/* request */
+	struct svc_export *si_exp;			/* response */
+};
+
 struct nfsd4_setattr {
 	stateid_t	sa_stateid;         /* request */
 	u32		sa_bmval[2];        /* request */
@@ -365,6 +371,7 @@
 		struct nfsd4_remove		remove;
 		struct nfsd4_rename		rename;
 		clientid_t			renew;
+		struct nfsd4_secinfo		secinfo;
 		struct nfsd4_setattr		setattr;
 		struct nfsd4_setclientid	setclientid;
 		struct nfsd4_setclientid_confirm setclientid_confirm;
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 189e0dc..ce06188 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -28,10 +28,11 @@
 	struct ipc_namespace *ipc_ns;
 	struct mnt_namespace *mnt_ns;
 	struct pid_namespace *pid_ns;
+	struct user_namespace *user_ns;
 };
 extern struct nsproxy init_nsproxy;
 
-int copy_namespaces(int flags, struct task_struct *tsk);
+int copy_namespaces(unsigned long flags, struct task_struct *tsk);
 void get_task_namespaces(struct task_struct *tsk);
 void free_nsproxy(struct nsproxy *ns);
 int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 37a7158..5e84f2e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -432,6 +432,8 @@
  * code, or pci core code. */
 extern struct list_head pci_root_buses;	/* list of all known PCI buses */
 extern struct list_head pci_devices;	/* list of all devices */
+/* Some device drivers need know if pci is initiated */
+extern int no_pci_devices(void);
 
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
@@ -724,6 +726,7 @@
 { return NULL; }
 
 #define pci_dev_present(ids)	(0)
+#define no_pci_devices()	(1)
 #define pci_find_present(ids)	(NULL)
 #define pci_dev_put(dev)	do { } while (0)
 
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index b72be2f..926adaa 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -1,7 +1,7 @@
 #ifndef __LINUX_PERCPU_H
 #define __LINUX_PERCPU_H
 
-#include <linux/spinlock.h> /* For preempt_disable() */
+#include <linux/preempt.h>
 #include <linux/slab.h> /* For kmalloc() */
 #include <linux/smp.h>
 #include <linux/string.h> /* For memset() */
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index f5aa593..3d9f709 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -8,6 +8,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/smp.h>
+#include <linux/list.h>
 #include <linux/threads.h>
 #include <linux/percpu.h>
 #include <linux/types.h>
@@ -17,6 +18,9 @@
 struct percpu_counter {
 	spinlock_t lock;
 	s64 count;
+#ifdef CONFIG_HOTPLUG_CPU
+	struct list_head list;	/* All percpu_counters are on a list */
+#endif
 	s32 *counters;
 };
 
@@ -26,18 +30,8 @@
 #define FBC_BATCH	(NR_CPUS*4)
 #endif
 
-static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
-{
-	spin_lock_init(&fbc->lock);
-	fbc->count = amount;
-	fbc->counters = alloc_percpu(s32);
-}
-
-static inline void percpu_counter_destroy(struct percpu_counter *fbc)
-{
-	free_percpu(fbc->counters);
-}
-
+void percpu_counter_init(struct percpu_counter *fbc, s64 amount);
+void percpu_counter_destroy(struct percpu_counter *fbc);
 void percpu_counter_mod(struct percpu_counter *fbc, s32 amount);
 s64 percpu_counter_sum(struct percpu_counter *fbc);
 
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 169c6c2..b9a17e0 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -29,7 +29,7 @@
 	kref_get(&ns->kref);
 }
 
-extern struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *ns);
+extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
 extern void free_pid_ns(struct kref *kref);
 
 static inline void put_pid_ns(struct pid_namespace *ns)
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 52a9be4..e2eff90 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -59,4 +59,8 @@
 # define PR_ENDIAN_LITTLE	1	/* True little endian mode */
 # define PR_ENDIAN_PPC_LITTLE	2	/* "PowerPC" pseudo little endian */
 
+/* Get/set process seccomp mode */
+#define PR_GET_SECCOMP	21
+#define PR_SET_SECCOMP	22
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/prefetch.h b/include/linux/prefetch.h
index fc86f27..1adfe66 100644
--- a/include/linux/prefetch.h
+++ b/include/linux/prefetch.h
@@ -27,7 +27,7 @@
 	
 	prefetch(x)  	- prefetches the cacheline at "x" for read
 	prefetchw(x)	- prefetches the cacheline at "x" for write
-	spin_lock_prefetch(x) - prefectches the spinlock *x for taking
+	spin_lock_prefetch(x) - prefetches the spinlock *x for taking
 	
 	there is also PREFETCH_STRIDE which is the architecure-prefered 
 	"lookahead" size for prefetching streamed operations.
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 3469f96..28e3664 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -7,6 +7,8 @@
 #include <linux/magic.h>
 #include <asm/atomic.h>
 
+struct completion;
+
 /*
  * The proc filesystem constants/structures
  */
@@ -56,6 +58,14 @@
 	gid_t gid;
 	loff_t size;
 	const struct inode_operations *proc_iops;
+	/*
+	 * NULL ->proc_fops means "PDE is going away RSN" or
+	 * "PDE is just created". In either case, e.g. ->read_proc won't be
+	 * called because it's too late or too early, respectively.
+	 *
+	 * If you're allocating ->proc_fops dynamically, save a pointer
+	 * somewhere.
+	 */
 	const struct file_operations *proc_fops;
 	get_info_t *get_info;
 	struct module *owner;
@@ -66,6 +76,9 @@
 	atomic_t count;		/* use count */
 	int deleted;		/* delete flag */
 	void *set;
+	int pde_users;	/* number of callers into module in progress */
+	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
+	struct completion *pde_unload_completion;
 };
 
 struct kcore_list {
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index eeb1976..ae8146a 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -110,6 +110,8 @@
 		__ptrace_unlink(child);
 }
 
+int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data);
+int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data);
 
 #ifndef force_successful_syscall_return
 /*
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index dd5a05d..75e17a0 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -262,7 +262,7 @@
 
 char *file_path(struct file *file, char *buf, int count);
 void bitmap_print_sb(struct bitmap *bitmap);
-int bitmap_update_sb(struct bitmap *bitmap);
+void bitmap_update_sb(struct bitmap *bitmap);
 
 int  bitmap_setallbits(struct bitmap *bitmap);
 void bitmap_write_all(struct bitmap *bitmap);
@@ -278,8 +278,8 @@
 void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
 void bitmap_close_sync(struct bitmap *bitmap);
 
-int bitmap_unplug(struct bitmap *bitmap);
-int bitmap_daemon_work(struct bitmap *bitmap);
+void bitmap_unplug(struct bitmap *bitmap);
+void bitmap_daemon_work(struct bitmap *bitmap);
 #endif
 
 #endif
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index de72c49..28ac632 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -51,7 +51,7 @@
 
 	sector_t size;			/* Device size (in blocks) */
 	mddev_t *mddev;			/* RAID array if running */
-	unsigned long last_events;	/* IO event timestamp */
+	long last_events;		/* IO event timestamp */
 
 	struct block_device *bdev;	/* block device handle */
 
diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h
new file mode 100644
index 0000000..e8c7c21
--- /dev/null
+++ b/include/linux/rtc/m48t59.h
@@ -0,0 +1,57 @@
+/*
+ * include/linux/rtc/m48t59.h
+ *
+ * Definitions for the platform data of m48t59 RTC chip driver.
+ *
+ * Copyright (c) 2007 Wind River Systems, Inc.
+ *
+ * Mark Zhan <rongkai.zhan@windriver.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.
+ */
+
+#ifndef _LINUX_RTC_M48T59_H_
+#define _LINUX_RTC_M48T59_H_
+
+/*
+ * M48T59 Register Offset
+ */
+#define M48T59_YEAR		0x1fff
+#define M48T59_MONTH		0x1ffe
+#define M48T59_MDAY		0x1ffd	/* Day of Month */
+#define M48T59_WDAY		0x1ffc	/* Day of Week */
+#define M48T59_WDAY_CB			0x20	/* Century Bit */
+#define M48T59_WDAY_CEB			0x10	/* Century Enable Bit */
+#define M48T59_HOUR		0x1ffb
+#define M48T59_MIN		0x1ffa
+#define M48T59_SEC		0x1ff9
+#define M48T59_CNTL		0x1ff8
+#define M48T59_CNTL_READ		0x40
+#define M48T59_CNTL_WRITE		0x80
+#define M48T59_WATCHDOG		0x1ff7
+#define M48T59_INTR		0x1ff6
+#define M48T59_INTR_AFE			0x80	/* Alarm Interrupt Enable */
+#define M48T59_INTR_ABE			0x20
+#define M48T59_ALARM_DATE	0x1ff5
+#define M48T59_ALARM_HOUR	0x1ff4
+#define M48T59_ALARM_MIN	0x1ff3
+#define M48T59_ALARM_SEC	0x1ff2
+#define M48T59_UNUSED		0x1ff1
+#define M48T59_FLAGS		0x1ff0
+#define M48T59_FLAGS_WDT		0x80	/* watchdog timer expired */
+#define M48T59_FLAGS_AF			0x40	/* alarm */
+#define M48T59_FLAGS_BF			0x10	/* low battery */
+
+#define M48T59_NVRAM_SIZE	0x1ff0
+
+struct m48t59_plat_data {
+	/* The method to access M48T59 registers,
+	 * NOTE: The 'ofs' should be 0x00~0x1fff
+	 */
+	void (*write_byte)(struct device *dev, u32 ofs, u8 val);
+	unsigned char (*read_byte)(struct device *dev, u32 ofs);
+};
+
+#endif /* _LINUX_RTC_M48T59_H_ */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index cfb6805..731edaca 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -26,6 +26,7 @@
 #define CLONE_STOPPED		0x02000000	/* Start in stopped state */
 #define CLONE_NEWUTS		0x04000000	/* New utsname group? */
 #define CLONE_NEWIPC		0x08000000	/* New ipcs */
+#define CLONE_NEWUSER		0x10000000	/* New user namespace */
 
 /*
  * Scheduling policies
@@ -287,6 +288,7 @@
 asmlinkage void schedule(void);
 
 struct nsproxy;
+struct user_namespace;
 
 /* Maximum number of active map areas.. This is a random (large) number */
 #define DEFAULT_MAX_MAP_COUNT	65536
@@ -529,6 +531,10 @@
 #ifdef CONFIG_TASKSTATS
 	struct taskstats *stats;
 #endif
+#ifdef CONFIG_AUDIT
+	unsigned audit_tty;
+	struct tty_audit_buf *tty_audit_buf;
+#endif
 };
 
 /* Context switch must be unlocked if interrupts are to be enabled */
@@ -972,7 +978,8 @@
 	unsigned int rt_priority;
 	cputime_t utime, stime;
 	unsigned long nvcsw, nivcsw; /* context switch counts */
-	struct timespec start_time;
+	struct timespec start_time; 		/* monotonic time */
+	struct timespec real_start_time;	/* boot based time */
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 	unsigned long min_flt, maj_flt;
 
@@ -1403,7 +1410,7 @@
 extern void __set_special_pids(pid_t session, pid_t pgrp);
 
 /* per-UID process charging. */
-extern struct user_struct * alloc_uid(uid_t);
+extern struct user_struct * alloc_uid(struct user_namespace *, uid_t);
 static inline struct user_struct *get_uid(struct user_struct *u)
 {
 	atomic_inc(&u->__count);
diff --git a/include/linux/scx200_gpio.h b/include/linux/scx200_gpio.h
index 1a82d30..d2b0581 100644
--- a/include/linux/scx200_gpio.h
+++ b/include/linux/scx200_gpio.h
@@ -1,5 +1,3 @@
-#include <linux/spinlock.h>
-
 u32 scx200_gpio_configure(unsigned index, u32 set, u32 clear);
 
 extern unsigned scx200_gpio_base;
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 3e8b1cf..262a8dc 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -4,8 +4,6 @@
 
 #ifdef CONFIG_SECCOMP
 
-#define NR_SECCOMP_MODES 1
-
 #include <linux/thread_info.h>
 #include <asm/seccomp.h>
 
@@ -18,20 +16,23 @@
 		__secure_computing(this_syscall);
 }
 
-static inline int has_secure_computing(struct thread_info *ti)
-{
-	return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
-}
+extern long prctl_get_seccomp(void);
+extern long prctl_set_seccomp(unsigned long);
 
 #else /* CONFIG_SECCOMP */
 
 typedef struct { } seccomp_t;
 
 #define secure_computing(x) do { } while (0)
-/* static inline to preserve typechecking */
-static inline int has_secure_computing(struct thread_info *ti)
+
+static inline long prctl_get_seccomp(void)
 {
-	return 0;
+	return -EINVAL;
+}
+
+static inline long prctl_set_seccomp(unsigned long arg2)
+{
+	return -EINVAL;
 }
 
 #endif /* CONFIG_SECCOMP */
diff --git a/include/linux/serial.h b/include/linux/serial.h
index 33fc8cb..deb7143 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -177,11 +177,5 @@
 #ifdef __KERNEL__
 #include <linux/compiler.h>
 
-/* Allow architectures to override entries in serial8250_ports[] at run time: */
-struct uart_port;	/* forward declaration */
-extern int early_serial_setup(struct uart_port *port);
-extern int early_serial_console_init(char *options);
-extern int serial8250_start_console(struct uart_port *port, char *options);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SERIAL_H */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 71310d8..706ee9a 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -60,4 +60,8 @@
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
 
+extern int serial8250_find_port(struct uart_port *p);
+extern int serial8250_find_port_for_earlycon(void);
+extern int setup_early_serial8250_console(char *cmdline);
+
 #endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 7f2c99d..9c721cd 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -142,6 +142,9 @@
 /* Micrel KS8695 */
 #define PORT_KS8695	76
 
+/* Broadcom SB1250, etc. SOC */
+#define PORT_SB1250_DUART	77
+
 
 #ifdef __KERNEL__
 
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 9a5eac5..ea91abe 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -6,7 +6,6 @@
 
 #ifdef __KERNEL__
 #include <linux/list.h>
-#include <linux/spinlock.h>
 
 /*
  * Real Time signals may be queued.
diff --git a/include/linux/slab.h b/include/linux/slab.h
index cebcd38..0e1d0da 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -14,8 +14,6 @@
 #include <linux/gfp.h>
 #include <linux/types.h>
 
-typedef struct kmem_cache kmem_cache_t __deprecated;
-
 /*
  * Flags to pass to kmem_cache_create().
  * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
@@ -33,6 +31,19 @@
 #define SLAB_TRACE		0x00200000UL	/* Trace allocations and frees */
 
 /*
+ * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
+ *
+ * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
+ *
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
+ * Both make kfree a no-op.
+ */
+#define ZERO_SIZE_PTR ((void *)16)
+
+#define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) < \
+				(unsigned long)ZERO_SIZE_PTR)
+
+/*
  * struct kmem_cache related prototypes
  */
 void __init kmem_cache_init(void);
@@ -44,8 +55,6 @@
 			void (*)(void *, struct kmem_cache *, unsigned long));
 void kmem_cache_destroy(struct kmem_cache *);
 int kmem_cache_shrink(struct kmem_cache *);
-void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
-void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
 void kmem_cache_free(struct kmem_cache *, void *);
 unsigned int kmem_cache_size(struct kmem_cache *);
 const char *kmem_cache_name(struct kmem_cache *);
@@ -63,16 +72,6 @@
 		sizeof(struct __struct), __alignof__(struct __struct),\
 		(__flags), NULL, NULL)
 
-#ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
-#else
-static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
-					gfp_t flags, int node)
-{
-	return kmem_cache_alloc(cachep, flags);
-}
-#endif
-
 /*
  * The largest kmalloc size supported by the slab allocators is
  * 32 megabyte (2^25) or the maximum allocatable page order if that is
@@ -91,51 +90,42 @@
 /*
  * Common kmalloc functions provided by all allocators
  */
-void *__kmalloc(size_t, gfp_t);
-void *__kzalloc(size_t, gfp_t);
 void * __must_check krealloc(const void *, size_t, gfp_t);
 void kfree(const void *);
 size_t ksize(const void *);
 
+/*
+ * Allocator specific definitions. These are mainly used to establish optimized
+ * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by
+ * selecting the appropriate general cache at compile time.
+ *
+ * Allocators must define at least:
+ *
+ *	kmem_cache_alloc()
+ *	__kmalloc()
+ *	kmalloc()
+ *
+ * Those wishing to support NUMA must also define:
+ *
+ *	kmem_cache_alloc_node()
+ *	kmalloc_node()
+ *
+ * See each allocator definition file for additional comments and
+ * implementation notes.
+ */
+#ifdef CONFIG_SLUB
+#include <linux/slub_def.h>
+#elif defined(CONFIG_SLOB)
+#include <linux/slob_def.h>
+#else
+#include <linux/slab_def.h>
+#endif
+
 /**
  * kcalloc - allocate memory for an array. The memory is set to zero.
  * @n: number of elements.
  * @size: element size.
  * @flags: the type of memory to allocate.
- */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-{
-	if (n != 0 && size > ULONG_MAX / n)
-		return NULL;
-	return __kzalloc(n * size, flags);
-}
-
-/*
- * Allocator specific definitions. These are mainly used to establish optimized
- * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by selecting
- * the appropriate general cache at compile time.
- */
-
-#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
-#ifdef CONFIG_SLUB
-#include <linux/slub_def.h>
-#else
-#include <linux/slab_def.h>
-#endif /* !CONFIG_SLUB */
-#else
-
-/*
- * Fallback definitions for an allocator not wanting to provide
- * its own optimized kmalloc definitions (like SLOB).
- */
-
-/**
- * kmalloc - allocate memory
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * kmalloc is the normal method of allocating memory
- * in the kernel.
  *
  * The @flags argument may be one of:
  *
@@ -143,7 +133,7 @@
  *
  * %GFP_KERNEL - Allocate normal kernel ram.  May sleep.
  *
- * %GFP_ATOMIC - Allocation will not sleep.
+ * %GFP_ATOMIC - Allocation will not sleep.  May use emergency pools.
  *   For example, use this inside interrupt handlers.
  *
  * %GFP_HIGHUSER - Allocate pages from high memory.
@@ -152,18 +142,22 @@
  *
  * %GFP_NOFS - Do not make any fs calls while trying to get memory.
  *
+ * %GFP_NOWAIT - Allocation will not sleep.
+ *
+ * %GFP_THISNODE - Allocate node-local memory only.
+ *
+ * %GFP_DMA - Allocation suitable for DMA.
+ *   Should only be used for kmalloc() caches. Otherwise, use a
+ *   slab created with SLAB_DMA.
+ *
  * Also it is possible to set different flags by OR'ing
  * in one or more of the following additional @flags:
  *
  * %__GFP_COLD - Request cache-cold pages instead of
  *   trying to return cache-warm pages.
  *
- * %__GFP_DMA - Request memory from the DMA-capable zone.
- *
  * %__GFP_HIGH - This allocation has high priority and may use emergency pools.
  *
- * %__GFP_HIGHMEM - Allocated memory may be from highmem.
- *
  * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail
  *   (think twice before using).
  *
@@ -173,24 +167,29 @@
  * %__GFP_NOWARN - If allocation fails, don't issue any warnings.
  *
  * %__GFP_REPEAT - If allocation fails initially, try once more before failing.
+ *
+ * There are other flags available as well, but these are not intended
+ * for general use, and so are not documented here. For a full list of
+ * potential flags, always refer to linux/gfp.h.
  */
-static inline void *kmalloc(size_t size, gfp_t flags)
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
 {
-	return __kmalloc(size, flags);
+	if (n != 0 && size > ULONG_MAX / n)
+		return NULL;
+	return __kmalloc(n * size, flags | __GFP_ZERO);
 }
 
+#if !defined(CONFIG_NUMA) && !defined(CONFIG_SLOB)
 /**
- * kzalloc - allocate memory. The memory is set to zero.
+ * kmalloc_node - allocate memory from a specific node
  * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate (see kmalloc).
+ * @flags: the type of memory to allocate (see kcalloc).
+ * @node: node to allocate from.
+ *
+ * kmalloc() for non-local nodes, used to allocate from a specific node
+ * if available. Equivalent to kmalloc() in the non-NUMA single-node
+ * case.
  */
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
-	return __kzalloc(size, flags);
-}
-#endif
-
-#ifndef CONFIG_NUMA
 static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
 	return kmalloc(size, flags);
@@ -200,7 +199,15 @@
 {
 	return __kmalloc(size, flags);
 }
-#endif /* !CONFIG_NUMA */
+
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+
+static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
+					gfp_t flags, int node)
+{
+	return kmem_cache_alloc(cachep, flags);
+}
+#endif /* !CONFIG_NUMA && !CONFIG_SLOB */
 
 /*
  * kmalloc_track_caller is a special version of kmalloc that records the
@@ -245,6 +252,23 @@
 
 #endif /* DEBUG_SLAB */
 
+/*
+ * Shortcuts
+ */
+static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags)
+{
+	return kmem_cache_alloc(k, flags | __GFP_ZERO);
+}
+
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+	return kmalloc(size, flags | __GFP_ZERO);
+}
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SLAB_H */
-
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 8d81a60..32bdc2f 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -25,10 +25,17 @@
 };
 extern struct cache_sizes malloc_sizes[];
 
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *__kmalloc(size_t size, gfp_t flags);
+
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
 	if (__builtin_constant_p(size)) {
 		int i = 0;
+
+		if (!size)
+			return ZERO_SIZE_PTR;
+
 #define CACHE(x) \
 		if (size <= x) \
 			goto found; \
@@ -51,39 +58,18 @@
 	return __kmalloc(size, flags);
 }
 
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
-	if (__builtin_constant_p(size)) {
-		int i = 0;
-#define CACHE(x) \
-		if (size <= x) \
-			goto found; \
-		else \
-			i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
-		{
-			extern void __you_cannot_kzalloc_that_much(void);
-			__you_cannot_kzalloc_that_much();
-		}
-found:
-#ifdef CONFIG_ZONE_DMA
-		if (flags & GFP_DMA)
-			return kmem_cache_zalloc(malloc_sizes[i].cs_dmacachep,
-						flags);
-#endif
-		return kmem_cache_zalloc(malloc_sizes[i].cs_cachep, flags);
-	}
-	return __kzalloc(size, flags);
-}
-
 #ifdef CONFIG_NUMA
 extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 
 static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
 	if (__builtin_constant_p(size)) {
 		int i = 0;
+
+		if (!size)
+			return ZERO_SIZE_PTR;
+
 #define CACHE(x) \
 		if (size <= x) \
 			goto found; \
diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h
new file mode 100644
index 0000000..a2daf2d
--- /dev/null
+++ b/include/linux/slob_def.h
@@ -0,0 +1,46 @@
+#ifndef __LINUX_SLOB_DEF_H
+#define __LINUX_SLOB_DEF_H
+
+void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
+
+static inline void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
+{
+	return kmem_cache_alloc_node(cachep, flags, -1);
+}
+
+void *__kmalloc_node(size_t size, gfp_t flags, int node);
+
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+	return __kmalloc_node(size, flags, node);
+}
+
+/**
+ * kmalloc - allocate memory
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kcalloc).
+ *
+ * kmalloc is the normal method of allocating memory
+ * in the kernel.
+ */
+static inline void *kmalloc(size_t size, gfp_t flags)
+{
+	return __kmalloc_node(size, flags, -1);
+}
+
+static inline void *__kmalloc(size_t size, gfp_t flags)
+{
+	return kmalloc(size, flags);
+}
+
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kcalloc).
+ */
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+	return __kzalloc(size, flags);
+}
+
+#endif /* __LINUX_SLOB_DEF_H */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 6207a3d..07f7e4c 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -16,7 +16,9 @@
 	unsigned long nr_partial;
 	atomic_long_t nr_slabs;
 	struct list_head partial;
+#ifdef CONFIG_SLUB_DEBUG
 	struct list_head full;
+#endif
 };
 
 /*
@@ -44,7 +46,9 @@
 	int align;		/* Alignment */
 	const char *name;	/* Name (only for display!) */
 	struct list_head list;	/* List of slab caches */
+#ifdef CONFIG_SLUB_DEBUG
 	struct kobject kobj;	/* For sysfs */
+#endif
 
 #ifdef CONFIG_NUMA
 	int defrag_ratio;
@@ -159,17 +163,8 @@
 #define SLUB_DMA 0
 #endif
 
-
-/*
- * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
- *
- * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
- *
- * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
- * Both make kfree a no-op.
- */
-#define ZERO_SIZE_PTR ((void *)16)
-
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *__kmalloc(size_t size, gfp_t flags);
 
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
@@ -184,21 +179,9 @@
 		return __kmalloc(size, flags);
 }
 
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
-	if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
-		struct kmem_cache *s = kmalloc_slab(size);
-
-		if (!s)
-			return ZERO_SIZE_PTR;
-
-		return kmem_cache_zalloc(s, flags);
-	} else
-		return __kzalloc(size, flags);
-}
-
 #ifdef CONFIG_NUMA
-extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+void *__kmalloc_node(size_t size, gfp_t flags, int node);
+void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 
 static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index cf715a4..58962c5 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -3,7 +3,6 @@
 
 #ifdef CONFIG_LOCK_KERNEL
 #include <linux/sched.h>
-#include <linux/spinlock.h>
 
 #define kernel_locked()		(current->lock_depth >= 0)
 
diff --git a/include/linux/socket.h b/include/linux/socket.h
index fe195c9..f852e1a 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -253,6 +253,9 @@
 
 #define MSG_EOF         MSG_FIN
 
+#define MSG_CMSG_CLOEXEC 0x40000000	/* Set close_on_exit for file
+					   descriptor received through
+					   SCM_RIGHTS */
 #if defined(CONFIG_COMPAT)
 #define MSG_CMSG_COMPAT	0x80000000	/* This message needs 32 bit fixups */
 #else
diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h
index 34d4b07..40c7b5d 100644
--- a/include/linux/sonypi.h
+++ b/include/linux/sonypi.h
@@ -153,8 +153,6 @@
 #define SONYPI_COMMAND_GETCAMERAROMVERSION	18	/* obsolete */
 #define SONYPI_COMMAND_GETCAMERAREVISION	19	/* obsolete */
 
-int sonypi_camera_command(int command, u8 value);
-
 #endif				/* __KERNEL__ */
 
 #endif				/* _SONYPI_H_ */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 1be5ea0..302b81d 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -76,6 +76,7 @@
 #define	SPI_MODE_3	(SPI_CPOL|SPI_CPHA)
 #define	SPI_CS_HIGH	0x04			/* chipselect active high? */
 #define	SPI_LSB_FIRST	0x08			/* per-word bits-on-wire */
+#define	SPI_3WIRE	0x10			/* SI/SO signals shared */
 	u8			bits_per_word;
 	int			irq;
 	void			*controller_state;
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index 9dbca62..b8db32c 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -26,6 +26,7 @@
 	struct list_head	queue;
 	u8			busy;
 	u8			use_dma;
+	u8			flags;		/* extra spi->mode support */
 
 	struct spi_master	*master;
 
diff --git a/include/linux/spi/tle62x0.h b/include/linux/spi/tle62x0.h
new file mode 100644
index 0000000..60b5918
--- /dev/null
+++ b/include/linux/spi/tle62x0.h
@@ -0,0 +1,24 @@
+/*
+ * tle62x0.h - platform glue to Infineon TLE62x0 driver chips
+ *
+ * Copyright 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+struct tle62x0_pdata {
+	unsigned int		init_state;
+	unsigned int		gpio_count;
+};
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index a946176..c376f3b 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -282,6 +282,13 @@
 	1 : ({ local_irq_restore(flags); 0; }); \
 })
 
+#define write_trylock_irqsave(lock, flags) \
+({ \
+	local_irq_save(flags); \
+	write_trylock(lock) ? \
+	1 : ({ local_irq_restore(flags); 0; }); \
+})
+
 /*
  * Locks two spinlocks l1 and l2.
  * l1_first indicates if spinlock l1 should be taken first.
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index bbac101..459c5fc 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -58,6 +58,7 @@
 u32 gss_delete_sec_context(
 		struct gss_ctx		**ctx_id);
 
+u32 gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 service);
 u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
 char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
 
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 129d50f..8531a70 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -212,6 +212,7 @@
 	struct svc_pool *	rq_pool;	/* thread pool */
 	struct svc_procedure *	rq_procinfo;	/* procedure info */
 	struct auth_ops *	rq_authop;	/* authentication flavour */
+	u32			rq_flavor;	/* pseudoflavor */
 	struct svc_cred		rq_cred;	/* auth info */
 	struct sk_buff *	rq_skbuff;	/* fast recv inet buffer */
 	struct svc_deferred_req*rq_deferred;	/* deferred request we are replaying */
@@ -248,6 +249,7 @@
 						 */
 	/* Catering to nfsd */
 	struct auth_domain *	rq_client;	/* RPC peer info */
+	struct auth_domain *	rq_gssclient;	/* "gss/"-style peer info */
 	struct svc_cacherep *	rq_cacherep;	/* cache info */
 	struct knfsd_fh *	rq_reffh;	/* Referrence filehandle, used to
 						 * determine what device number
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index de92619..22e1ef8 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -127,6 +127,7 @@
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 extern void svcauth_unix_info_release(void *);
+extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
 
 static inline unsigned long hash_str(char *name, int bits)
 {
diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
index 5a5db16..417a1de 100644
--- a/include/linux/sunrpc/svcauth_gss.h
+++ b/include/linux/sunrpc/svcauth_gss.h
@@ -22,6 +22,7 @@
 int gss_svc_init(void);
 void gss_svc_shutdown(void);
 int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
+u32 svcauth_gss_flavor(struct auth_domain *dom);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 0068688..665f85f 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -188,7 +188,8 @@
 extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
-extern unsigned long try_to_free_pages(struct zone **, gfp_t);
+extern unsigned long try_to_free_pages(struct zone **zones, int order,
+					gfp_t gfp_mask);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
 extern int remove_mapping(struct address_space *mapping, struct page *page);
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index a46104a..dce1ed204 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -31,7 +31,7 @@
  */
 
 
-#define TASKSTATS_VERSION	4
+#define TASKSTATS_VERSION	5
 #define TS_COMM_LEN		32	/* should be >= TASK_COMM_LEN
 					 * in linux/sched.h */
 
@@ -149,6 +149,9 @@
 	__u64	read_bytes;		/* bytes of read I/O */
 	__u64	write_bytes;		/* bytes of write I/O */
 	__u64	cancelled_write_bytes;	/* bytes of cancelled write I/O */
+
+	__u64  nvcsw;			/* voluntary_ctxt_switches */
+	__u64  nivcsw;			/* nonvoluntary_ctxt_switches */
 };
 
 
diff --git a/include/linux/time.h b/include/linux/time.h
index dda9be6..ec3b0ce 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -36,7 +36,8 @@
 #define NSEC_PER_SEC	1000000000L
 #define FSEC_PER_SEC	1000000000000000L
 
-static inline int timespec_equal(struct timespec *a, struct timespec *b)
+static inline int timespec_equal(const struct timespec *a,
+                                 const struct timespec *b)
 {
 	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
 }
@@ -116,6 +117,8 @@
 extern unsigned int alarm_setitimer(unsigned int seconds);
 extern int do_getitimer(int which, struct itimerval *value);
 extern void getnstimeofday(struct timespec *tv);
+extern void getboottime(struct timespec *ts);
+extern void monotonic_to_bootbased(struct timespec *ts);
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 extern int timekeeping_is_continuous(void);
diff --git a/include/linux/timer.h b/include/linux/timer.h
index c661710..78cf899 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -3,7 +3,6 @@
 
 #include <linux/list.h>
 #include <linux/ktime.h>
-#include <linux/spinlock.h>
 #include <linux/stddef.h>
 
 struct tvec_t_base_s;
@@ -91,16 +90,13 @@
  */
 #ifdef CONFIG_TIMER_STATS
 
+#define TIMER_STATS_FLAG_DEFERRABLE	0x1
+
 extern void init_timer_stats(void);
 
 extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-				     void *timerf, char * comm);
-
-static inline void timer_stats_account_timer(struct timer_list *timer)
-{
-	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
-				 timer->function, timer->start_comm);
-}
+				     void *timerf, char *comm,
+				     unsigned int timer_flag);
 
 extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
 					       void *addr);
@@ -119,10 +115,6 @@
 {
 }
 
-static inline void timer_stats_account_timer(struct timer_list *timer)
-{
-}
-
 static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
 {
 }
diff --git a/include/linux/tty.h b/include/linux/tty.h
index bb45760..691a174 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -178,6 +178,7 @@
 #define L_IEXTEN(tty)	_L_FLAG((tty),IEXTEN)
 
 struct device;
+struct signal_struct;
 /*
  * Where all of the state associated with a tty is kept while the tty
  * is open.  Since the termios state should be kept even if the tty
@@ -310,6 +311,7 @@
 extern void tty_vhangup(struct tty_struct * tty);
 extern void tty_unhangup(struct file *filp);
 extern int tty_hung_up_p(struct file * filp);
+extern int is_tty(struct file *filp);
 extern void do_SAK(struct tty_struct *tty);
 extern void __do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
@@ -338,9 +340,46 @@
 
 extern struct mutex tty_mutex;
 
+extern void tty_write_unlock(struct tty_struct *tty);
+extern int tty_write_lock(struct tty_struct *tty, int ndelay);
+#define tty_is_writelocked(tty)  (mutex_is_locked(&tty->atomic_write_lock))
+
+
+
 /* n_tty.c */
 extern struct tty_ldisc tty_ldisc_N_TTY;
 
+/* tty_audit.c */
+#ifdef CONFIG_AUDIT
+extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+			       size_t size);
+extern void tty_audit_exit(void);
+extern void tty_audit_fork(struct signal_struct *sig);
+extern void tty_audit_push(struct tty_struct *tty);
+extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid);
+extern void tty_audit_opening(void);
+#else
+static inline void tty_audit_add_data(struct tty_struct *tty,
+				      unsigned char *data, size_t size)
+{
+}
+static inline void tty_audit_exit(void)
+{
+}
+static inline void tty_audit_fork(struct signal_struct *sig)
+{
+}
+static inline void tty_audit_push(struct tty_struct *tty)
+{
+}
+static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+{
+}
+static inline void tty_audit_opening(void)
+{
+}
+#endif
+
 /* tty_ioctl.c */
 extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
 		       unsigned int cmd, unsigned long arg);
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 9af8bbc..b7fe138 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -13,10 +13,6 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-
-/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C
-   library one from sys/uio.h if you have a very old library set */
-
 struct iovec
 {
 	void __user *iov_base;	/* BSD uses caddr_t (1003.1g requires void *) */
@@ -38,11 +34,6 @@
  
 #define UIO_FASTIOV	8
 #define UIO_MAXIOV	1024
-#if 0
-#define UIO_MAXIOV	16	/* Maximum iovec's in one operation 
-				   16 matches BSD */
-                                /* Beg pardon: BSD has 1024 --ANK */
-#endif
 
 /*
  * Total number of bytes covered by an iovec.
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
new file mode 100644
index 0000000..bb32057
--- /dev/null
+++ b/include/linux/user_namespace.h
@@ -0,0 +1,61 @@
+#ifndef _LINUX_USER_NAMESPACE_H
+#define _LINUX_USER_NAMESPACE_H
+
+#include <linux/kref.h>
+#include <linux/nsproxy.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+
+#define UIDHASH_BITS	(CONFIG_BASE_SMALL ? 3 : 8)
+#define UIDHASH_SZ	(1 << UIDHASH_BITS)
+
+struct user_namespace {
+	struct kref		kref;
+	struct list_head	uidhash_table[UIDHASH_SZ];
+	struct user_struct	*root_user;
+};
+
+extern struct user_namespace init_user_ns;
+
+#ifdef CONFIG_USER_NS
+
+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+{
+	if (ns)
+		kref_get(&ns->kref);
+	return ns;
+}
+
+extern struct user_namespace *copy_user_ns(int flags,
+					   struct user_namespace *old_ns);
+extern void free_user_ns(struct kref *kref);
+
+static inline void put_user_ns(struct user_namespace *ns)
+{
+	if (ns)
+		kref_put(&ns->kref, free_user_ns);
+}
+
+#else
+
+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+{
+	return &init_user_ns;
+}
+
+static inline struct user_namespace *copy_user_ns(int flags,
+						  struct user_namespace *old_ns)
+{
+	if (flags & CLONE_NEWUSER)
+		return ERR_PTR(-EINVAL);
+
+	return NULL;
+}
+
+static inline void put_user_ns(struct user_namespace *ns)
+{
+}
+
+#endif
+
+#endif /* _LINUX_USER_H */
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index f8d3b32..923db99 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -48,26 +48,14 @@
 	kref_get(&ns->kref);
 }
 
-#ifdef CONFIG_UTS_NS
-extern struct uts_namespace *copy_utsname(int flags, struct uts_namespace *ns);
+extern struct uts_namespace *copy_utsname(unsigned long flags,
+					struct uts_namespace *ns);
 extern void free_uts_ns(struct kref *kref);
 
 static inline void put_uts_ns(struct uts_namespace *ns)
 {
 	kref_put(&ns->kref, free_uts_ns);
 }
-#else
-static inline struct uts_namespace *copy_utsname(int flags,
-						struct uts_namespace *ns)
-{
-	return ns;
-}
-
-static inline void put_uts_ns(struct uts_namespace *ns)
-{
-}
-#endif
-
 static inline struct new_utsname *utsname(void)
 {
 	return &current->nsproxy->uts_ns->name;
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 4b7ee83..132b260 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -65,9 +65,10 @@
 					  unsigned long flags, int node,
 					  gfp_t gfp_mask);
 extern struct vm_struct *remove_vm_area(void *addr);
+
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
 			struct page ***pages);
-extern void unmap_vm_area(struct vm_struct *area);
+extern void unmap_kernel_range(unsigned long addr, unsigned long size);
 
 /*
  *	Internals.  Dont't use..
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index d9325cf..75370ec 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -25,7 +25,7 @@
 #define HIGHMEM_ZONE(xx)
 #endif
 
-#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx)
+#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx) , xx##_MOVABLE
 
 enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		FOR_ALL_ZONES(PGALLOC),
@@ -170,7 +170,8 @@
 #ifdef CONFIG_HIGHMEM
 		zone_page_state(&zones[ZONE_HIGHMEM], item) +
 #endif
-		zone_page_state(&zones[ZONE_NORMAL], item);
+		zone_page_state(&zones[ZONE_NORMAL], item) +
+		zone_page_state(&zones[ZONE_MOVABLE], item);
 }
 
 extern void zone_statistics(struct zonelist *, struct zone *);
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index d961635..699b7e9 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -75,6 +75,8 @@
 int vt_waitactive(int vt);
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
+extern int unbind_con_driver(const struct consw *csw, int first, int last,
+			     int deflt);
 
 /*
  * vc_screen.c shares this temporary buffer with the console write code so that
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index ce0719a..ce6badc 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -148,7 +148,7 @@
 extern void init_workqueues(void);
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
-extern void cancel_work_sync(struct work_struct *work);
+extern int cancel_work_sync(struct work_struct *work);
 
 /*
  * Kill off a pending schedule_delayed_work().  Note that the work callback
@@ -166,14 +166,21 @@
 	return ret;
 }
 
-extern void cancel_rearming_delayed_work(struct delayed_work *work);
+extern int cancel_delayed_work_sync(struct delayed_work *work);
 
-/* Obsolete. use cancel_rearming_delayed_work() */
+/* Obsolete. use cancel_delayed_work_sync() */
 static inline
 void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
 					struct delayed_work *work)
 {
-	cancel_rearming_delayed_work(work);
+	cancel_delayed_work_sync(work);
+}
+
+/* Obsolete. use cancel_delayed_work_sync() */
+static inline
+void cancel_rearming_delayed_work(struct delayed_work *work)
+{
+	cancel_delayed_work_sync(work);
 }
 
 #endif
diff --git a/include/net/scm.h b/include/net/scm.h
index 5637d5e..423cb1d 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -8,7 +8,7 @@
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
  */
-#define SCM_MAX_FD	(OPEN_MAX-1)
+#define SCM_MAX_FD	255
 
 struct scm_fp_list
 {
diff --git a/include/video/tgafb.h b/include/video/tgafb.h
index 03d0dbe..7bc5e2c 100644
--- a/include/video/tgafb.h
+++ b/include/video/tgafb.h
@@ -216,6 +216,7 @@
 	u32 pll_freq;			/* pixclock in mhz */
 	u32 bits_per_pixel;		/* bits per pixel */
 	u32 sync_on_green;		/* set if sync is on green */
+	u32 palette[16];
 };
 
 
diff --git a/init/Kconfig b/init/Kconfig
index d9d878a..e205682 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -120,15 +120,6 @@
 	  section 6.4 of the Linux Programmer's Guide, available from
 	  <http://www.tldp.org/guides.html>.
 
-config IPC_NS
-	bool "IPC Namespaces"
-	depends on SYSVIPC
-	default n
-	help
-	  Support ipc namespaces.  This allows containers, i.e. virtual
-	  environments, to use ipc namespaces to provide different ipc
-	  objects for different servers.  If unsure, say N.
-
 config SYSVIPC_SYSCTL
 	bool
 	depends on SYSVIPC
@@ -218,13 +209,14 @@
 
 	  Say N if unsure.
 
-config UTS_NS
-	bool "UTS Namespaces"
+config USER_NS
+	bool "User Namespaces (EXPERIMENTAL)"
 	default n
+	depends on EXPERIMENTAL
 	help
-	  Support uts namespaces.  This allows containers, i.e.
-	  vservers, to use uts namespaces to provide different
-	  uts info for different servers.  If unsure, say N.
+	  Support user namespaces.  This allows containers, i.e.
+	  vservers, to use user namespaces to provide different
+	  user info for different servers.  If unsure, say N.
 
 config AUDIT
 	bool "Auditing support"
@@ -554,7 +546,7 @@
 
 choice
 	prompt "Choose SLAB allocator"
-	default SLAB
+	default SLUB
 	help
 	   This option allows to select a slab allocator.
 
@@ -576,7 +568,7 @@
 	   and has enhanced diagnostics.
 
 config SLOB
-	depends on EMBEDDED && !SPARSEMEM
+	depends on EMBEDDED
 	bool "SLOB (Simple Allocator)"
 	help
 	   SLOB replaces the SLAB allocator with a drastically simpler
@@ -602,9 +594,7 @@
 	default 0 if BASE_FULL
 	default 1 if !BASE_FULL
 
-menu "Loadable module support"
-
-config MODULES
+menuconfig MODULES
 	bool "Enable loadable module support"
 	help
 	  Kernel modules are small pieces of compiled code which can
@@ -684,6 +674,5 @@
 	depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU
 	help
 	  Need stop_machine() primitive.
-endmenu
 
 source "block/Kconfig"
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 46fe407..4efa1e5 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -25,6 +25,7 @@
 int root_mountflags = MS_RDONLY | MS_SILENT;
 char * __initdata root_device_name;
 static char __initdata saved_root_name[64];
+static int __initdata root_wait;
 
 dev_t ROOT_DEV;
 
@@ -216,6 +217,16 @@
 
 __setup("root=", root_dev_setup);
 
+static int __init rootwait_setup(char *str)
+{
+	if (*str)
+		return 0;
+	root_wait = 1;
+	return 1;
+}
+
+__setup("rootwait", rootwait_setup);
+
 static char * __initdata root_mount_data;
 static int __init root_data_setup(char *str)
 {
@@ -438,11 +449,20 @@
 			root_device_name += 5;
 	}
 
-	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
-
 	if (initrd_load())
 		goto out;
 
+	/* wait for any asynchronous scanning to complete */
+	if ((ROOT_DEV == 0) && root_wait) {
+		printk(KERN_INFO "Waiting for root device %s...\n",
+			saved_root_name);
+		while (driver_probe_done() != 0 ||
+			(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
+			msleep(100);
+	}
+
+	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+
 	if (is_floppy && rd_doload && rd_load_disk(0))
 		ROOT_DEV = Root_RAM0;
 
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index b222ce9..a6b4c0c 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -56,12 +56,9 @@
 	sys_chroot(".");
 
 	pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
-	if (pid > 0) {
-		while (pid != sys_wait4(-1, NULL, 0, NULL)) {
-			try_to_freeze();
+	if (pid > 0)
+		while (pid != sys_wait4(-1, NULL, 0, NULL))
 			yield();
-		}
-	}
 
 	/* move initrd to rootfs' /old */
 	sys_fchdir(old_fd);
diff --git a/init/main.c b/init/main.c
index 0eb1c74..d3bcb3b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -132,20 +132,9 @@
 static char *execute_command;
 static char *ramdisk_execute_command;
 
+#ifdef CONFIG_SMP
 /* Setup configured maximum number of CPUs to activate */
-static unsigned int max_cpus = NR_CPUS;
-
-/*
- * If set, this is an indication to the drivers that reset the underlying
- * device before going ahead with the initialization otherwise driver might
- * rely on the BIOS and skip the reset operation.
- *
- * This is useful if kernel is booting in an unreliable environment.
- * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
- * skipped and devices will be in unknown state.
- */
-unsigned int reset_devices;
-EXPORT_SYMBOL(reset_devices);
+static unsigned int __initdata max_cpus = NR_CPUS;
 
 /*
  * Setup routine for controlling SMP activation
@@ -160,10 +149,10 @@
 static int __init nosmp(char *str)
 {
 	max_cpus = 0;
-	return 1;
+	return 0;
 }
 
-__setup("nosmp", nosmp);
+early_param("nosmp", nosmp);
 
 static int __init maxcpus(char *str)
 {
@@ -172,6 +161,21 @@
 }
 
 __setup("maxcpus=", maxcpus);
+#else
+#define max_cpus NR_CPUS
+#endif
+
+/*
+ * If set, this is an indication to the drivers that reset the underlying
+ * device before going ahead with the initialization otherwise driver might
+ * rely on the BIOS and skip the reset operation.
+ *
+ * This is useful if kernel is booting in an unreliable environment.
+ * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
+ * skipped and devices will be in unknown state.
+ */
+unsigned int reset_devices;
+EXPORT_SYMBOL(reset_devices);
 
 static int __init set_reset_devices(char *str)
 {
@@ -385,6 +389,10 @@
 {
 	unsigned int cpu;
 
+#ifndef CONFIG_HOTPLUG_CPU
+	cpu_possible_map = cpu_present_map;
+#endif
+
 	/* FIXME: This should be done in userspace --RR */
 	for_each_present_cpu(cpu) {
 		if (num_online_cpus() >= max_cpus)
@@ -453,7 +461,10 @@
 	struct obs_kernel_param *p;
 
 	for (p = __setup_start; p < __setup_end; p++) {
-		if (p->early && strcmp(param, p->str) == 0) {
+		if ((p->early && strcmp(param, p->str) == 0) ||
+		    (strcmp(param, "console") == 0 &&
+		     strcmp(p->str, "earlycon") == 0)
+		) {
 			if (p->setup_func(val) != 0)
 				printk(KERN_WARNING
 				       "Malformed early option '%s'\n", param);
@@ -526,6 +537,10 @@
 	setup_arch(&command_line);
 	setup_command_line(command_line);
 	unwind_setup();
+#ifndef CONFIG_HOTPLUG_CPU
+	if (max_cpus < 2)
+		cpu_possible_map = cpu_online_map;
+#endif
 	setup_per_cpu_areas();
 	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
 
@@ -725,6 +740,15 @@
 	do_initcalls();
 }
 
+static int __initdata nosoftlockup;
+
+static int __init nosoftlockup_setup(char *str)
+{
+	nosoftlockup = 1;
+	return 1;
+}
+__setup("nosoftlockup", nosoftlockup_setup);
+
 static void __init do_pre_smp_initcalls(void)
 {
 	extern int spawn_ksoftirqd(void);
@@ -734,7 +758,8 @@
 	migration_init();
 #endif
 	spawn_ksoftirqd();
-	spawn_softlockup_task();
+	if (!nosoftlockup)
+		spawn_softlockup_task();
 }
 
 static void run_init_process(char *init_filename)
diff --git a/ipc/msg.c b/ipc/msg.c
index a388824..cbd27e5 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -87,7 +87,7 @@
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 #endif
 
-static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
 {
 	ns->ids[IPC_MSG_IDS] = ids;
 	ns->msg_ctlmax = MSGMAX;
@@ -96,7 +96,6 @@
 	ipc_init_ids(ids, ns->msg_ctlmni);
 }
 
-#ifdef CONFIG_IPC_NS
 int msg_init_ns(struct ipc_namespace *ns)
 {
 	struct ipc_ids *ids;
@@ -128,7 +127,6 @@
 	kfree(ns->ids[IPC_MSG_IDS]);
 	ns->ids[IPC_MSG_IDS] = NULL;
 }
-#endif
 
 void __init msg_init(void)
 {
diff --git a/ipc/sem.c b/ipc/sem.c
index 9964b22..89bfdff 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -121,7 +121,7 @@
 #define sc_semopm	sem_ctls[2]
 #define sc_semmni	sem_ctls[3]
 
-static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
 {
 	ns->ids[IPC_SEM_IDS] = ids;
 	ns->sc_semmsl = SEMMSL;
@@ -132,7 +132,6 @@
 	ipc_init_ids(ids, ns->sc_semmni);
 }
 
-#ifdef CONFIG_IPC_NS
 int sem_init_ns(struct ipc_namespace *ns)
 {
 	struct ipc_ids *ids;
@@ -164,7 +163,6 @@
 	kfree(ns->ids[IPC_SEM_IDS]);
 	ns->ids[IPC_SEM_IDS] = NULL;
 }
-#endif
 
 void __init sem_init (void)
 {
diff --git a/ipc/shm.c b/ipc/shm.c
index 0852f20..242c3f6 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -77,7 +77,7 @@
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
 #endif
 
-static void __ipc_init __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
 {
 	ns->ids[IPC_SHM_IDS] = ids;
 	ns->shm_ctlmax = SHMMAX;
@@ -98,7 +98,6 @@
 		shm_destroy(ns, shp);
 }
 
-#ifdef CONFIG_IPC_NS
 int shm_init_ns(struct ipc_namespace *ns)
 {
 	struct ipc_ids *ids;
@@ -130,7 +129,6 @@
 	kfree(ns->ids[IPC_SHM_IDS]);
 	ns->ids[IPC_SHM_IDS] = NULL;
 }
-#endif
 
 void __init shm_init (void)
 {
diff --git a/ipc/util.c b/ipc/util.c
index 7536a72..44e5135 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -50,7 +50,6 @@
 	},
 };
 
-#ifdef CONFIG_IPC_NS
 static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
 {
 	int err;
@@ -110,14 +109,6 @@
 	shm_exit_ns(ns);
 	kfree(ns);
 }
-#else
-struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
-{
-	if (flags & CLONE_NEWIPC)
-		return ERR_PTR(-EINVAL);
-	return ns;
-}
-#endif
 
 /**
  *	ipc_init	-	initialise IPC subsystem
@@ -145,7 +136,7 @@
  *	array itself. 
  */
  
-void __ipc_init ipc_init_ids(struct ipc_ids* ids, int size)
+void ipc_init_ids(struct ipc_ids* ids, int size)
 {
 	int i;
 
diff --git a/ipc/util.h b/ipc/util.h
index e3aa2c5..333e891 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -41,12 +41,8 @@
 };
 
 struct seq_file;
-#ifdef CONFIG_IPC_NS
-#define __ipc_init
-#else
-#define __ipc_init	__init
-#endif
-void __ipc_init ipc_init_ids(struct ipc_ids *ids, int size);
+
+void ipc_init_ids(struct ipc_ids *ids, int size);
 #ifdef CONFIG_PROC_FS
 void __init ipc_init_proc_interface(const char *path, const char *header,
 		int ids, int (*show)(struct seq_file *, void *));
diff --git a/kernel/Makefile b/kernel/Makefile
index 642d427..2a99983 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -4,11 +4,12 @@
 
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
 	    exit.o itimer.o time.o softirq.o resource.o \
-	    sysctl.o capability.o ptrace.o timer.o user.o \
+	    sysctl.o capability.o ptrace.o timer.o user.o user_namespace.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
-	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o
+	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o \
+	    utsname.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
@@ -48,7 +49,6 @@
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RELAY) += relay.o
 obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
-obj-$(CONFIG_UTS_NS) += utsname.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
 obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
 
diff --git a/kernel/audit.c b/kernel/audit.c
index d13276d..eb0f916 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -58,6 +58,7 @@
 #include <linux/selinux.h>
 #include <linux/inotify.h>
 #include <linux/freezer.h>
+#include <linux/tty.h>
 
 #include "audit.h"
 
@@ -391,6 +392,7 @@
 {
 	struct sk_buff *skb;
 
+	set_freezable();
 	while (!kthread_should_stop()) {
 		skb = skb_dequeue(&audit_skb_queue);
 		wake_up(&audit_backlog_wait);
@@ -423,6 +425,31 @@
 	return 0;
 }
 
+static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
+{
+	struct task_struct *tsk;
+	int err;
+
+	read_lock(&tasklist_lock);
+	tsk = find_task_by_pid(pid);
+	err = -ESRCH;
+	if (!tsk)
+		goto out;
+	err = 0;
+
+	spin_lock_irq(&tsk->sighand->siglock);
+	if (!tsk->signal->audit_tty)
+		err = -EPERM;
+	spin_unlock_irq(&tsk->sighand->siglock);
+	if (err)
+		goto out;
+
+	tty_audit_push_task(tsk, loginuid);
+out:
+	read_unlock(&tasklist_lock);
+	return err;
+}
+
 int audit_send_list(void *_dest)
 {
 	struct audit_netlink_list *dest = _dest;
@@ -511,6 +538,8 @@
 	case AUDIT_DEL:
 	case AUDIT_DEL_RULE:
 	case AUDIT_SIGNAL_INFO:
+	case AUDIT_TTY_GET:
+	case AUDIT_TTY_SET:
 		if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
 			err = -EPERM;
 		break;
@@ -622,6 +651,11 @@
 		err = audit_filter_user(&NETLINK_CB(skb), msg_type);
 		if (err == 1) {
 			err = 0;
+			if (msg_type == AUDIT_USER_TTY) {
+				err = audit_prepare_user_tty(pid, loginuid);
+				if (err)
+					break;
+			}
 			ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
 			if (ab) {
 				audit_log_format(ab,
@@ -638,8 +672,17 @@
 							" subj=%s", ctx);
 					kfree(ctx);
 				}
-				audit_log_format(ab, " msg='%.1024s'",
-					 (char *)data);
+				if (msg_type != AUDIT_USER_TTY)
+					audit_log_format(ab, " msg='%.1024s'",
+							 (char *)data);
+				else {
+					int size;
+
+					audit_log_format(ab, " msg=");
+					size = nlmsg_len(nlh);
+					audit_log_n_untrustedstring(ab, size,
+								    data);
+				}
 				audit_set_pid(ab, pid);
 				audit_log_end(ab);
 			}
@@ -730,6 +773,45 @@
 				0, 0, sig_data, sizeof(*sig_data) + len);
 		kfree(sig_data);
 		break;
+	case AUDIT_TTY_GET: {
+		struct audit_tty_status s;
+		struct task_struct *tsk;
+
+		read_lock(&tasklist_lock);
+		tsk = find_task_by_pid(pid);
+		if (!tsk)
+			err = -ESRCH;
+		else {
+			spin_lock_irq(&tsk->sighand->siglock);
+			s.enabled = tsk->signal->audit_tty != 0;
+			spin_unlock_irq(&tsk->sighand->siglock);
+		}
+		read_unlock(&tasklist_lock);
+		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0,
+				 &s, sizeof(s));
+		break;
+	}
+	case AUDIT_TTY_SET: {
+		struct audit_tty_status *s;
+		struct task_struct *tsk;
+
+		if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
+			return -EINVAL;
+		s = data;
+		if (s->enabled != 0 && s->enabled != 1)
+			return -EINVAL;
+		read_lock(&tasklist_lock);
+		tsk = find_task_by_pid(pid);
+		if (!tsk)
+			err = -ESRCH;
+		else {
+			spin_lock_irq(&tsk->sighand->siglock);
+			tsk->signal->audit_tty = s->enabled != 0;
+			spin_unlock_irq(&tsk->sighand->siglock);
+		}
+		read_unlock(&tasklist_lock);
+		break;
+	}
 	default:
 		err = -EINVAL;
 		break;
@@ -1185,7 +1267,7 @@
 }
 
 /**
- * audit_log_n_unstrustedstring - log a string that may contain random characters
+ * audit_log_n_untrustedstring - log a string that may contain random characters
  * @ab: audit_buffer
  * @len: lenth of string (not including trailing null)
  * @string: string to be logged
@@ -1201,25 +1283,24 @@
 const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
 					const char *string)
 {
-	const unsigned char *p = string;
+	const unsigned char *p;
 
-	while (*p) {
+	for (p = string; p < (const unsigned char *)string + len && *p; p++) {
 		if (*p == '"' || *p < 0x21 || *p > 0x7f) {
 			audit_log_hex(ab, string, len);
 			return string + len + 1;
 		}
-		p++;
 	}
 	audit_log_n_string(ab, len, string);
 	return p + 1;
 }
 
 /**
- * audit_log_unstrustedstring - log a string that may contain random characters
+ * audit_log_untrustedstring - log a string that may contain random characters
  * @ab: audit_buffer
  * @string: string to be logged
  *
- * Same as audit_log_n_unstrustedstring(), except that strlen is used to
+ * Same as audit_log_n_untrustedstring(), except that strlen is used to
  * determine string length.
  */
 const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
diff --git a/kernel/audit.h b/kernel/audit.h
index 815d6f5..9587743 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -115,7 +115,6 @@
 extern void		    audit_send_reply(int pid, int seq, int type,
 					     int done, int multi,
 					     void *payload, int size);
-extern void		    audit_log_lost(const char *message);
 extern void		    audit_panic(const char *message);
 
 struct audit_netlink_list {
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e36481e..b7640a5 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -71,9 +71,6 @@
 
 extern struct list_head audit_filter_list[];
 
-/* No syscall auditing will take place unless audit_enabled != 0. */
-extern int audit_enabled;
-
 /* AUDIT_NAMES is the number of slots we reserve in the audit_context
  * for saving names from getname(). */
 #define AUDIT_NAMES    20
@@ -2040,7 +2037,7 @@
 
 /**
  * audit_core_dumps - record information about processes that end abnormally
- * @sig: signal value
+ * @signr: signal value
  *
  * If a process ends with a core dump, something fishy is going on and we
  * should record the event for investigation.
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index c4d123f..b4796d8 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -981,10 +981,10 @@
 		mmarray = kmalloc(ntasks * sizeof(*mmarray), GFP_KERNEL);
 		if (!mmarray)
 			goto done;
-		write_lock_irq(&tasklist_lock);		/* block fork */
+		read_lock(&tasklist_lock);		/* block fork */
 		if (atomic_read(&cs->count) <= ntasks)
 			break;				/* got enough */
-		write_unlock_irq(&tasklist_lock);	/* try again */
+		read_unlock(&tasklist_lock);		/* try again */
 		kfree(mmarray);
 	}
 
@@ -1006,7 +1006,7 @@
 			continue;
 		mmarray[n++] = mm;
 	} while_each_thread(g, p);
-	write_unlock_irq(&tasklist_lock);
+	read_unlock(&tasklist_lock);
 
 	/*
 	 * Now that we've dropped the tasklist spinlock, we can
diff --git a/kernel/exit.c b/kernel/exit.c
index ca6a11b..e8af8d0 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -31,6 +31,7 @@
 #include <linux/mempolicy.h>
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
+#include <linux/freezer.h>
 #include <linux/cpuset.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
@@ -387,6 +388,11 @@
 	 * they would be locked into memory.
 	 */
 	exit_mm(current);
+	/*
+	 * We don't want to have TIF_FREEZE set if the system-wide hibernation
+	 * or suspend transition begins right now.
+	 */
+	current->flags |= PF_NOFREEZE;
 
 	set_special_pids(1, 1);
 	proc_clear_tty(current);
@@ -858,6 +864,34 @@
 		release_task(tsk);
 }
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+static void check_stack_usage(void)
+{
+	static DEFINE_SPINLOCK(low_water_lock);
+	static int lowest_to_date = THREAD_SIZE;
+	unsigned long *n = end_of_stack(current);
+	unsigned long free;
+
+	while (*n == 0)
+		n++;
+	free = (unsigned long)n - (unsigned long)end_of_stack(current);
+
+	if (free >= lowest_to_date)
+		return;
+
+	spin_lock(&low_water_lock);
+	if (free < lowest_to_date) {
+		printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
+				"left\n",
+				current->comm, free);
+		lowest_to_date = free;
+	}
+	spin_unlock(&low_water_lock);
+}
+#else
+static inline void check_stack_usage(void) {}
+#endif
+
 fastcall NORET_TYPE void do_exit(long code)
 {
 	struct task_struct *tsk = current;
@@ -937,6 +971,8 @@
 	if (unlikely(tsk->compat_robust_list))
 		compat_exit_robust_list(tsk);
 #endif
+	if (group_dead)
+		tty_audit_exit();
 	if (unlikely(tsk->audit_context))
 		audit_free(tsk);
 
@@ -949,6 +985,7 @@
 	exit_sem(tsk);
 	__exit_files(tsk);
 	__exit_fs(tsk);
+	check_stack_usage();
 	exit_thread();
 	cpuset_exit(tsk);
 	exit_keys(tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index da3a155..ba39bdb 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -49,6 +49,7 @@
 #include <linux/delayacct.h>
 #include <linux/taskstats_kern.h>
 #include <linux/random.h>
+#include <linux/tty.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -897,6 +898,8 @@
 	}
 	acct_init_pacct(&sig->pacct);
 
+	tty_audit_fork(sig);
+
 	return 0;
 }
 
@@ -920,7 +923,7 @@
 {
 	unsigned long new_flags = p->flags;
 
-	new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE);
+	new_flags &= ~PF_SUPERPRIV;
 	new_flags |= PF_FORKNOEXEC;
 	if (!(clone_flags & CLONE_PTRACE))
 		p->ptrace = 0;
@@ -999,7 +1002,7 @@
 	if (atomic_read(&p->user->processes) >=
 			p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
 		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
-				p->user != &root_user)
+		    p->user != current->nsproxy->user_ns->root_user)
 			goto bad_fork_free;
 	}
 
@@ -1059,6 +1062,8 @@
 
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
+	p->real_start_time = p->start_time;
+	monotonic_to_bootbased(&p->real_start_time);
 	p->security = NULL;
 	p->io_context = NULL;
 	p->io_wait = NULL;
@@ -1601,7 +1606,7 @@
 	err = -EINVAL;
 	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
 				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
-				CLONE_NEWUTS|CLONE_NEWIPC))
+				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER))
 		goto bad_unshare_out;
 
 	if ((err = unshare_thread(unshare_flags)))
diff --git a/kernel/futex.c b/kernel/futex.c
index 45490be..5c3f45d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -121,6 +121,24 @@
 static struct vfsmount *futex_mnt;
 
 /*
+ * Take mm->mmap_sem, when futex is shared
+ */
+static inline void futex_lock_mm(struct rw_semaphore *fshared)
+{
+	if (fshared)
+		down_read(fshared);
+}
+
+/*
+ * Release mm->mmap_sem, when the futex is shared
+ */
+static inline void futex_unlock_mm(struct rw_semaphore *fshared)
+{
+	if (fshared)
+		up_read(fshared);
+}
+
+/*
  * We hash on the keys returned from get_futex_key (see below).
  */
 static struct futex_hash_bucket *hash_futex(union futex_key *key)
@@ -287,7 +305,18 @@
 }
 EXPORT_SYMBOL_GPL(drop_futex_key_refs);
 
-static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
+static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+{
+	u32 curval;
+
+	pagefault_disable();
+	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	pagefault_enable();
+
+	return curval;
+}
+
+static int get_futex_value_locked(u32 *dest, u32 __user *from)
 {
 	int ret;
 
@@ -620,9 +649,7 @@
 
 		newval = FUTEX_WAITERS | new_owner->pid;
 
-		pagefault_disable();
-		curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-		pagefault_enable();
+		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
 
 		if (curval == -EFAULT)
 			ret = -EFAULT;
@@ -659,9 +686,7 @@
 	 * There is no waiter, so we unlock the futex. The owner died
 	 * bit has not to be preserved here. We are the owner:
 	 */
-	pagefault_disable();
-	oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0);
-	pagefault_enable();
+	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
 
 	if (oldval == -EFAULT)
 		return oldval;
@@ -700,8 +725,7 @@
 	union futex_key key;
 	int ret;
 
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &key);
 	if (unlikely(ret != 0))
@@ -725,8 +749,7 @@
 
 	spin_unlock(&hb->lock);
 out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 }
 
@@ -746,8 +769,7 @@
 	int ret, op_ret, attempt = 0;
 
 retryfull:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr1, fshared, &key1);
 	if (unlikely(ret != 0))
@@ -793,7 +815,7 @@
 		 */
 		if (attempt++) {
 			ret = futex_handle_fault((unsigned long)uaddr2,
-						fshared, attempt);
+						 fshared, attempt);
 			if (ret)
 				goto out;
 			goto retry;
@@ -803,8 +825,7 @@
 		 * If we would have faulted, release mmap_sem,
 		 * fault it in and start all over again.
 		 */
-		if (fshared)
-			up_read(fshared);
+		futex_unlock_mm(fshared);
 
 		ret = get_user(dummy, uaddr2);
 		if (ret)
@@ -841,8 +862,8 @@
 	if (hb1 != hb2)
 		spin_unlock(&hb2->lock);
 out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
+
 	return ret;
 }
 
@@ -861,8 +882,7 @@
 	int ret, drop_count = 0;
 
  retry:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr1, fshared, &key1);
 	if (unlikely(ret != 0))
@@ -890,8 +910,7 @@
 			 * If we would have faulted, release mmap_sem, fault
 			 * it in and start all over again.
 			 */
-			if (fshared)
-				up_read(fshared);
+			futex_unlock_mm(fshared);
 
 			ret = get_user(curval, uaddr1);
 
@@ -944,8 +963,7 @@
 		drop_futex_key_refs(&key1);
 
 out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 }
 
@@ -1113,10 +1131,7 @@
 	while (!ret) {
 		newval = (uval & FUTEX_OWNER_DIED) | newtid;
 
-		pagefault_disable();
-		curval = futex_atomic_cmpxchg_inatomic(uaddr,
-						       uval, newval);
-		pagefault_enable();
+		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
 
 		if (curval == -EFAULT)
 			ret = -EFAULT;
@@ -1134,6 +1149,7 @@
 #define ARG3_SHARED  1
 
 static long futex_wait_restart(struct restart_block *restart);
+
 static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
 		      u32 val, ktime_t *abs_time)
 {
@@ -1148,8 +1164,7 @@
 
 	q.pi_state = NULL;
  retry:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &q.key);
 	if (unlikely(ret != 0))
@@ -1186,8 +1201,7 @@
 		 * If we would have faulted, release mmap_sem, fault it in and
 		 * start all over again.
 		 */
-		if (fshared)
-			up_read(fshared);
+		futex_unlock_mm(fshared);
 
 		ret = get_user(uval, uaddr);
 
@@ -1206,8 +1220,7 @@
 	 * Now the futex is queued and we have checked the data, we
 	 * don't want to hold mmap_sem while we sleep.
 	 */
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	/*
 	 * There might have been scheduling since the queue_me(), as we
@@ -1285,8 +1298,7 @@
 	queue_unlock(&q, hb);
 
  out_release_sem:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 }
 
@@ -1333,8 +1345,7 @@
 
 	q.pi_state = NULL;
  retry:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &q.key);
 	if (unlikely(ret != 0))
@@ -1353,9 +1364,7 @@
 	 */
 	newval = current->pid;
 
-	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval);
-	pagefault_enable();
+	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
 
 	if (unlikely(curval == -EFAULT))
 		goto uaddr_faulted;
@@ -1398,9 +1407,7 @@
 		lock_taken = 1;
 	}
 
-	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-	pagefault_enable();
+	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
 
 	if (unlikely(curval == -EFAULT))
 		goto uaddr_faulted;
@@ -1428,8 +1435,7 @@
 			 * exit to complete.
 			 */
 			queue_unlock(&q, hb);
-			if (fshared)
-				up_read(fshared);
+			futex_unlock_mm(fshared);
 			cond_resched();
 			goto retry;
 
@@ -1465,8 +1471,7 @@
 	 * Now the futex is queued and we have checked the data, we
 	 * don't want to hold mmap_sem while we sleep.
 	 */
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	WARN_ON(!q.pi_state);
 	/*
@@ -1480,8 +1485,7 @@
 		ret = ret ? 0 : -EWOULDBLOCK;
 	}
 
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 	spin_lock(q.lock_ptr);
 
 	if (!ret) {
@@ -1518,8 +1522,7 @@
 
 	/* Unqueue and drop the lock */
 	unqueue_me_pi(&q);
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
@@ -1527,8 +1530,7 @@
 	queue_unlock(&q, hb);
 
  out_release_sem:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 
  uaddr_faulted:
@@ -1550,8 +1552,7 @@
 		goto retry_unlocked;
 	}
 
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	ret = get_user(uval, uaddr);
 	if (!ret && (uval != -EFAULT))
@@ -1585,8 +1586,7 @@
 	/*
 	 * First take all the futex related locks:
 	 */
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &key);
 	if (unlikely(ret != 0))
@@ -1601,11 +1601,9 @@
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	if (!(uval & FUTEX_OWNER_DIED)) {
-		pagefault_disable();
-		uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0);
-		pagefault_enable();
-	}
+	if (!(uval & FUTEX_OWNER_DIED))
+		uval = cmpxchg_futex_value_locked(uaddr, current->pid, 0);
+
 
 	if (unlikely(uval == -EFAULT))
 		goto pi_faulted;
@@ -1647,8 +1645,7 @@
 out_unlock:
 	spin_unlock(&hb->lock);
 out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	return ret;
 
@@ -1671,8 +1668,7 @@
 		goto retry_unlocked;
 	}
 
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	ret = get_user(uval, uaddr);
 	if (!ret && (uval != -EFAULT))
@@ -1729,8 +1725,8 @@
 
 	if (printk_timed_ratelimit(&printk_interval, 60 * 60 * 1000)) {
 		printk(KERN_WARNING "Process `%s' used FUTEX_FD, which "
-		    	"will be removed from the kernel in June 2007\n",
-			current->comm);
+		       "will be removed from the kernel in June 2007\n",
+		       current->comm);
 	}
 
 	ret = -EINVAL;
@@ -1908,10 +1904,8 @@
 		 * Wake robust non-PI futexes here. The wakeup of
 		 * PI futexes happens in exit_pi_state():
 		 */
-		if (!pi) {
-			if (uval & FUTEX_WAITERS)
+		if (!pi && (uval & FUTEX_WAITERS))
 				futex_wake(uaddr, &curr->mm->mmap_sem, 1);
-		}
 	}
 	return 0;
 }
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 23c03f4..72d0342 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1406,7 +1406,7 @@
 static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
 					unsigned long action, void *hcpu)
 {
-	long cpu = (long)hcpu;
+	unsigned int cpu = (long)hcpu;
 
 	switch (action) {
 
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index bd9e272..32b1619 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -172,7 +172,17 @@
 		    irqreturn_t action_ret)
 {
 	if (unlikely(action_ret != IRQ_HANDLED)) {
-		desc->irqs_unhandled++;
+		/*
+		 * If we are seeing only the odd spurious IRQ caused by
+		 * bus asynchronicity then don't eventually trigger an error,
+		 * otherwise the couter becomes a doomsday timer for otherwise
+		 * working systems
+		 */
+		if (jiffies - desc->last_unhandled > HZ/10)
+			desc->irqs_unhandled = 1;
+		else
+			desc->irqs_unhandled++;
+		desc->last_unhandled = jiffies;
 		if (unlikely(action_ret != IRQ_NONE))
 			report_bad_irq(irq, desc, action_ret);
 	}
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index fed5441..474219a 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -152,7 +152,7 @@
 /* Lookup the address for this symbol. Returns 0 if not found. */
 unsigned long kallsyms_lookup_name(const char *name)
 {
-	char namebuf[KSYM_NAME_LEN+1];
+	char namebuf[KSYM_NAME_LEN];
 	unsigned long i;
 	unsigned int off;
 
@@ -248,7 +248,7 @@
 {
 	const char *msym;
 
-	namebuf[KSYM_NAME_LEN] = 0;
+	namebuf[KSYM_NAME_LEN - 1] = 0;
 	namebuf[0] = 0;
 
 	if (is_ksym_addr(addr)) {
@@ -265,7 +265,7 @@
 	/* see if it's in a module */
 	msym = module_address_lookup(addr, symbolsize, offset, modname);
 	if (msym)
-		return strncpy(namebuf, msym, KSYM_NAME_LEN);
+		return strncpy(namebuf, msym, KSYM_NAME_LEN - 1);
 
 	return NULL;
 }
@@ -273,7 +273,7 @@
 int lookup_symbol_name(unsigned long addr, char *symname)
 {
 	symname[0] = '\0';
-	symname[KSYM_NAME_LEN] = '\0';
+	symname[KSYM_NAME_LEN - 1] = '\0';
 
 	if (is_ksym_addr(addr)) {
 		unsigned long pos;
@@ -291,7 +291,7 @@
 			unsigned long *offset, char *modname, char *name)
 {
 	name[0] = '\0';
-	name[KSYM_NAME_LEN] = '\0';
+	name[KSYM_NAME_LEN - 1] = '\0';
 
 	if (is_ksym_addr(addr)) {
 		unsigned long pos;
@@ -312,18 +312,17 @@
 	char *modname;
 	const char *name;
 	unsigned long offset, size;
-	char namebuf[KSYM_NAME_LEN+1];
+	char namebuf[KSYM_NAME_LEN];
 
 	name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
 	if (!name)
 		return sprintf(buffer, "0x%lx", address);
-	else {
-		if (modname)
-			return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
+
+	if (modname)
+		return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
 				size, modname);
-		else
-			return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
-	}
+	else
+		return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
 }
 
 /* Look up a kernel symbol and print it to the kernel messages. */
@@ -343,8 +342,8 @@
 	unsigned long value;
 	unsigned int nameoff; /* If iterating in core kernel symbols */
 	char type;
-	char name[KSYM_NAME_LEN+1];
-	char module_name[MODULE_NAME_LEN + 1];
+	char name[KSYM_NAME_LEN];
+	char module_name[MODULE_NAME_LEN];
 	int exported;
 };
 
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index cee4191..bc41ad0 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/kfifo.h>
+#include <linux/log2.h>
 
 /**
  * kfifo_init - allocates a new FIFO using a preallocated buffer
@@ -41,7 +42,7 @@
 	struct kfifo *fifo;
 
 	/* size must be a power of 2 */
-	BUG_ON(size & (size - 1));
+	BUG_ON(!is_power_of_2(size));
 
 	fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
 	if (!fifo)
diff --git a/kernel/kthread.c b/kernel/kthread.c
index bbd51b8..a404f7e 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -215,7 +215,7 @@
 EXPORT_SYMBOL(kthread_stop);
 
 
-static __init void kthreadd_setup(void)
+static noinline __init_refok void kthreadd_setup(void)
 {
 	struct task_struct *tsk = current;
 
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 1a5ff22..edba2ff 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -379,7 +379,7 @@
 
 static void print_lock_name(struct lock_class *class)
 {
-	char str[KSYM_NAME_LEN + 1], c1, c2, c3, c4;
+	char str[KSYM_NAME_LEN], c1, c2, c3, c4;
 	const char *name;
 
 	get_usage_chars(class, &c1, &c2, &c3, &c4);
@@ -401,7 +401,7 @@
 static void print_lockdep_cache(struct lockdep_map *lock)
 {
 	const char *name;
-	char str[KSYM_NAME_LEN + 1];
+	char str[KSYM_NAME_LEN];
 
 	name = lock->name;
 	if (!name)
diff --git a/kernel/module.c b/kernel/module.c
index 015d60c..33c04ad 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -61,10 +61,8 @@
 /* If this is set, the section belongs in the init part of the module */
 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
 
-/* Protects module list */
-static DEFINE_SPINLOCK(modlist_lock);
-
-/* List of modules, protected by module_mutex AND modlist_lock */
+/* List of modules, protected by module_mutex or preempt_disable
+ * (add/delete uses stop_machine). */
 static DEFINE_MUTEX(module_mutex);
 static LIST_HEAD(modules);
 
@@ -760,14 +758,13 @@
 void __symbol_put(const char *symbol)
 {
 	struct module *owner;
-	unsigned long flags;
 	const unsigned long *crc;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	if (!__find_symbol(symbol, &owner, &crc, 1))
 		BUG();
 	module_put(owner);
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 }
 EXPORT_SYMBOL(__symbol_put);
 
@@ -1228,14 +1225,14 @@
 void *__symbol_get(const char *symbol)
 {
 	struct module *owner;
-	unsigned long value, flags;
+	unsigned long value;
 	const unsigned long *crc;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	value = __find_symbol(symbol, &owner, &crc, 1);
 	if (value && !strong_try_module_get(owner))
 		value = 0;
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	return (void *)value;
 }
@@ -2136,7 +2133,7 @@
 			sym = get_ksymbol(mod, addr, NULL, NULL);
 			if (!sym)
 				goto out;
-			strlcpy(symname, sym, KSYM_NAME_LEN + 1);
+			strlcpy(symname, sym, KSYM_NAME_LEN);
 			mutex_unlock(&module_mutex);
 			return 0;
 		}
@@ -2161,9 +2158,9 @@
 			if (!sym)
 				goto out;
 			if (modname)
-				strlcpy(modname, mod->name, MODULE_NAME_LEN + 1);
+				strlcpy(modname, mod->name, MODULE_NAME_LEN);
 			if (name)
-				strlcpy(name, sym, KSYM_NAME_LEN + 1);
+				strlcpy(name, sym, KSYM_NAME_LEN);
 			mutex_unlock(&module_mutex);
 			return 0;
 		}
@@ -2184,8 +2181,8 @@
 			*value = mod->symtab[symnum].st_value;
 			*type = mod->symtab[symnum].st_info;
 			strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
-				KSYM_NAME_LEN + 1);
-			strlcpy(module_name, mod->name, MODULE_NAME_LEN + 1);
+				KSYM_NAME_LEN);
+			strlcpy(module_name, mod->name, MODULE_NAME_LEN);
 			*exported = is_exported(name, mod);
 			mutex_unlock(&module_mutex);
 			return 0;
@@ -2232,26 +2229,13 @@
 /* Called by the /proc file system to return a list of modules. */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
-	struct list_head *i;
-	loff_t n = 0;
-
 	mutex_lock(&module_mutex);
-	list_for_each(i, &modules) {
-		if (n++ == *pos)
-			break;
-	}
-	if (i == &modules)
-		return NULL;
-	return i;
+	return seq_list_start(&modules, *pos);
 }
 
 static void *m_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	struct list_head *i = p;
-	(*pos)++;
-	if (i->next == &modules)
-		return NULL;
-	return i->next;
+	return seq_list_next(p, &modules, pos);
 }
 
 static void m_stop(struct seq_file *m, void *p)
@@ -2321,11 +2305,10 @@
 /* Given an address, look for it in the module exception tables. */
 const struct exception_table_entry *search_module_extables(unsigned long addr)
 {
-	unsigned long flags;
 	const struct exception_table_entry *e = NULL;
 	struct module *mod;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	list_for_each_entry(mod, &modules, list) {
 		if (mod->num_exentries == 0)
 			continue;
@@ -2336,7 +2319,7 @@
 		if (e)
 			break;
 	}
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	/* Now, if we found one, we are running inside it now, hence
            we cannot unload the module, hence no refcnt needed. */
@@ -2348,25 +2331,24 @@
  */
 int is_module_address(unsigned long addr)
 {
-	unsigned long flags;
 	struct module *mod;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 
 	list_for_each_entry(mod, &modules, list) {
 		if (within(addr, mod->module_core, mod->core_size)) {
-			spin_unlock_irqrestore(&modlist_lock, flags);
+			preempt_enable();
 			return 1;
 		}
 	}
 
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	return 0;
 }
 
 
-/* Is this a valid kernel address?  We don't grab the lock: we are oopsing. */
+/* Is this a valid kernel address? */
 struct module *__module_text_address(unsigned long addr)
 {
 	struct module *mod;
@@ -2381,11 +2363,10 @@
 struct module *module_text_address(unsigned long addr)
 {
 	struct module *mod;
-	unsigned long flags;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	mod = __module_text_address(addr);
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	return mod;
 }
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 9e83b58..10f0bbb 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -21,6 +21,8 @@
 #include <linux/utsname.h>
 #include <linux/pid_namespace.h>
 
+static struct kmem_cache *nsproxy_cachep;
+
 struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
 
 static inline void get_nsproxy(struct nsproxy *ns)
@@ -43,9 +45,11 @@
 {
 	struct nsproxy *ns;
 
-	ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
-	if (ns)
+	ns = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
+	if (ns) {
+		memcpy(ns, orig, sizeof(struct nsproxy));
 		atomic_set(&ns->count, 1);
+	}
 	return ns;
 }
 
@@ -54,33 +58,51 @@
  * Return the newly created nsproxy.  Do not attach this to the task,
  * leave it to the caller to do proper locking and attach it to task.
  */
-static struct nsproxy *create_new_namespaces(int flags, struct task_struct *tsk,
-			struct fs_struct *new_fs)
+static struct nsproxy *create_new_namespaces(unsigned long flags,
+			struct task_struct *tsk, struct fs_struct *new_fs)
 {
 	struct nsproxy *new_nsp;
+	int err;
 
 	new_nsp = clone_nsproxy(tsk->nsproxy);
 	if (!new_nsp)
 		return ERR_PTR(-ENOMEM);
 
 	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
-	if (IS_ERR(new_nsp->mnt_ns))
+	if (IS_ERR(new_nsp->mnt_ns)) {
+		err = PTR_ERR(new_nsp->mnt_ns);
 		goto out_ns;
+	}
 
 	new_nsp->uts_ns = copy_utsname(flags, tsk->nsproxy->uts_ns);
-	if (IS_ERR(new_nsp->uts_ns))
+	if (IS_ERR(new_nsp->uts_ns)) {
+		err = PTR_ERR(new_nsp->uts_ns);
 		goto out_uts;
+	}
 
 	new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns);
-	if (IS_ERR(new_nsp->ipc_ns))
+	if (IS_ERR(new_nsp->ipc_ns)) {
+		err = PTR_ERR(new_nsp->ipc_ns);
 		goto out_ipc;
+	}
 
 	new_nsp->pid_ns = copy_pid_ns(flags, tsk->nsproxy->pid_ns);
-	if (IS_ERR(new_nsp->pid_ns))
+	if (IS_ERR(new_nsp->pid_ns)) {
+		err = PTR_ERR(new_nsp->pid_ns);
 		goto out_pid;
+	}
+
+	new_nsp->user_ns = copy_user_ns(flags, tsk->nsproxy->user_ns);
+	if (IS_ERR(new_nsp->user_ns)) {
+		err = PTR_ERR(new_nsp->user_ns);
+		goto out_user;
+	}
 
 	return new_nsp;
 
+out_user:
+	if (new_nsp->pid_ns)
+		put_pid_ns(new_nsp->pid_ns);
 out_pid:
 	if (new_nsp->ipc_ns)
 		put_ipc_ns(new_nsp->ipc_ns);
@@ -91,15 +113,15 @@
 	if (new_nsp->mnt_ns)
 		put_mnt_ns(new_nsp->mnt_ns);
 out_ns:
-	kfree(new_nsp);
-	return ERR_PTR(-ENOMEM);
+	kmem_cache_free(nsproxy_cachep, new_nsp);
+	return ERR_PTR(err);
 }
 
 /*
  * called from clone.  This now handles copy for nsproxy and all
  * namespaces therein.
  */
-int copy_namespaces(int flags, struct task_struct *tsk)
+int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 {
 	struct nsproxy *old_ns = tsk->nsproxy;
 	struct nsproxy *new_ns;
@@ -110,7 +132,7 @@
 
 	get_nsproxy(old_ns);
 
-	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER)))
 		return 0;
 
 	if (!capable(CAP_SYS_ADMIN)) {
@@ -140,7 +162,9 @@
 		put_ipc_ns(ns->ipc_ns);
 	if (ns->pid_ns)
 		put_pid_ns(ns->pid_ns);
-	kfree(ns);
+	if (ns->user_ns)
+		put_user_ns(ns->user_ns);
+	kmem_cache_free(nsproxy_cachep, ns);
 }
 
 /*
@@ -152,19 +176,10 @@
 {
 	int err = 0;
 
-	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+			       CLONE_NEWUSER)))
 		return 0;
 
-#ifndef CONFIG_IPC_NS
-	if (unshare_flags & CLONE_NEWIPC)
-		return -EINVAL;
-#endif
-
-#ifndef CONFIG_UTS_NS
-	if (unshare_flags & CLONE_NEWUTS)
-		return -EINVAL;
-#endif
-
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
@@ -174,3 +189,12 @@
 		err = PTR_ERR(*new_nsp);
 	return err;
 }
+
+static int __init nsproxy_cache_init(void)
+{
+	nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
+					   0, SLAB_PANIC, NULL, NULL);
+	return 0;
+}
+
+module_init(nsproxy_cache_init);
diff --git a/kernel/panic.c b/kernel/panic.c
index 623d182..f64f4c1 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -159,14 +159,15 @@
 {
 	static char buf[20];
 	if (tainted) {
-		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c",
+		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c",
 			tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
 			tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
 			tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
 			tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
  			tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
 			tainted & TAINT_BAD_PAGE ? 'B' : ' ',
-			tainted & TAINT_USER ? 'U' : ' ');
+			tainted & TAINT_USER ? 'U' : ' ',
+			tainted & TAINT_DIE ? 'D' : ' ');
 	}
 	else
 		snprintf(buf, sizeof(buf), "Not tainted");
diff --git a/kernel/pid.c b/kernel/pid.c
index eb66bd2..c6e3f9f 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -365,7 +365,7 @@
 }
 EXPORT_SYMBOL_GPL(find_get_pid);
 
-struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *old_ns)
+struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
 {
 	BUG_ON(!old_ns);
 	get_pid_ns(old_ns);
diff --git a/kernel/printk.c b/kernel/printk.c
index 0bbdeac..051d27e 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -449,13 +449,16 @@
 #else
 static int printk_time = 0;
 #endif
-module_param(printk_time, int, S_IRUGO | S_IWUSR);
+module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
 
 static int __init printk_time_setup(char *str)
 {
 	if (*str)
 		return 0;
 	printk_time = 1;
+	printk(KERN_NOTICE "The 'time' option is deprecated and "
+		"is scheduled for removal in early 2008\n");
+	printk(KERN_NOTICE "Use 'printk.time=<value>' instead\n");
 	return 1;
 }
 
@@ -483,6 +486,9 @@
  * @fmt: format string
  *
  * This is printk().  It can be called from any context.  We want it to work.
+ * Be aware of the fact that if oops_in_progress is not set, we might try to
+ * wake klogd up which could deadlock on runqueue lock if printk() is called
+ * from scheduler code.
  *
  * 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
@@ -654,7 +660,7 @@
  */
 static int __init console_setup(char *str)
 {
-	char name[sizeof(console_cmdline[0].name)];
+	char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */
 	char *s, *options;
 	int idx;
 
@@ -662,27 +668,27 @@
 	 * Decode str into name, index, options.
 	 */
 	if (str[0] >= '0' && str[0] <= '9') {
-		strcpy(name, "ttyS");
-		strncpy(name + 4, str, sizeof(name) - 5);
+		strcpy(buf, "ttyS");
+		strncpy(buf + 4, str, sizeof(buf) - 5);
 	} else {
-		strncpy(name, str, sizeof(name) - 1);
+		strncpy(buf, str, sizeof(buf) - 1);
 	}
-	name[sizeof(name) - 1] = 0;
+	buf[sizeof(buf) - 1] = 0;
 	if ((options = strchr(str, ',')) != NULL)
 		*(options++) = 0;
 #ifdef __sparc__
 	if (!strcmp(str, "ttya"))
-		strcpy(name, "ttyS0");
+		strcpy(buf, "ttyS0");
 	if (!strcmp(str, "ttyb"))
-		strcpy(name, "ttyS1");
+		strcpy(buf, "ttyS1");
 #endif
-	for (s = name; *s; s++)
+	for (s = buf; *s; s++)
 		if ((*s >= '0' && *s <= '9') || *s == ',')
 			break;
 	idx = simple_strtoul(s, NULL, 10);
 	*s = 0;
 
-	add_preferred_console(name, idx, options);
+	add_preferred_console(buf, idx, options);
 	return 1;
 }
 __setup("console=", console_setup);
@@ -709,7 +715,7 @@
 	 *	See if this tty is not yet registered, and
 	 *	if we have a slot free.
 	 */
-	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, name) == 0 &&
 			  console_cmdline[i].index == idx) {
 				selected_console = i;
@@ -726,6 +732,25 @@
 	return 0;
 }
 
+int __init update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
+{
+	struct console_cmdline *c;
+	int i;
+
+	for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+		if (strcmp(console_cmdline[i].name, name) == 0 &&
+			  console_cmdline[i].index == idx) {
+				c = &console_cmdline[i];
+				memcpy(c->name, name_new, sizeof(c->name));
+				c->name[sizeof(c->name) - 1] = 0;
+				c->options = options;
+				c->index = idx_new;
+				return i;
+		}
+	/* not found */
+	return -1;
+}
+
 #ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
 /**
  * suspend_console - suspend the console subsystem
@@ -942,6 +967,9 @@
 	if (preferred_console < 0 || bootconsole || !console_drivers)
 		preferred_console = selected_console;
 
+	if (console->early_setup)
+		console->early_setup();
+
 	/*
 	 *	See if we want to use this console driver. If we
 	 *	didn't select a console we take the first one
@@ -985,12 +1013,15 @@
 	if (!(console->flags & CON_ENABLED))
 		return;
 
-	if (bootconsole) {
+	if (bootconsole && (console->flags & CON_CONSDEV)) {
 		printk(KERN_INFO "console handover: boot [%s%d] -> real [%s%d]\n",
 		       bootconsole->name, bootconsole->index,
 		       console->name, console->index);
 		unregister_console(bootconsole);
 		console->flags &= ~CON_PRINTBUFFER;
+	} else {
+		printk(KERN_INFO "console [%s%d] enabled\n",
+		       console->name, console->index);
 	}
 
 	/*
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index ad7949a..4a1745f1 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -161,6 +161,7 @@
 int ptrace_attach(struct task_struct *task)
 {
 	int retval;
+	unsigned long flags;
 
 	audit_ptrace(task);
 
@@ -181,9 +182,7 @@
 	 * cpu's that may have task_lock).
 	 */
 	task_lock(task);
-	local_irq_disable();
-	if (!write_trylock(&tasklist_lock)) {
-		local_irq_enable();
+	if (!write_trylock_irqsave(&tasklist_lock, flags)) {
 		task_unlock(task);
 		do {
 			cpu_relax();
@@ -211,7 +210,7 @@
 	force_sig_specific(SIGSTOP, task);
 
 bad:
-	write_unlock_irq(&tasklist_lock);
+	write_unlock_irqrestore(&tasklist_lock, flags);
 	task_unlock(task);
 out:
 	return retval;
@@ -491,3 +490,22 @@
 	return ret;
 }
 #endif /* __ARCH_SYS_PTRACE */
+
+int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data)
+{
+	unsigned long tmp;
+	int copied;
+
+	copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
+	if (copied != sizeof(tmp))
+		return -EIO;
+	return put_user(tmp, (unsigned long __user *)data);
+}
+
+int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
+{
+	int copied;
+
+	copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
+	return (copied == sizeof(data)) ? 0 : -EIO;
+}
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 55ba82a..ddff332 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -40,6 +40,7 @@
 #include <linux/moduleparam.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
+#include <linux/freezer.h>
 #include <linux/cpu.h>
 #include <linux/random.h>
 #include <linux/delay.h>
@@ -518,7 +519,6 @@
 
 	VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
 	set_user_nice(current, 19);
-	current->flags |= PF_NOFREEZE;
 
 	do {
 		schedule_timeout_uninterruptible(1);
@@ -558,7 +558,6 @@
 
 	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
 	set_user_nice(current, 19);
-	current->flags |= PF_NOFREEZE;
 
 	do {
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
@@ -589,7 +588,6 @@
 
 	VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
 	set_user_nice(current, 19);
-	current->flags |= PF_NOFREEZE;
 
 	do {
 		idx = cur_ops->readlock();
diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c
index da8d6bf..5aedbee 100644
--- a/kernel/rtmutex-debug.c
+++ b/kernel/rtmutex-debug.c
@@ -29,12 +29,6 @@
 
 #include "rtmutex_common.h"
 
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
 # define TRACE_WARN_ON(x)			WARN_ON(x)
 # define TRACE_BUG_ON(x)			BUG_ON(x)
 
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 015fc63..e3055ba 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -260,6 +260,7 @@
 	int ret;
 
 	current->flags |= PF_MUTEX_TESTER;
+	set_freezable();
 	allow_signal(SIGHUP);
 
 	for(;;) {
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 17d28ce..8cd9bd2 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -17,12 +17,6 @@
 
 #include "rtmutex_common.h"
 
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
 /*
  * lock->owner state tracking:
  *
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
index 9c75856..2d3b835 100644
--- a/kernel/rtmutex_common.h
+++ b/kernel/rtmutex_common.h
@@ -103,7 +103,7 @@
 
 static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock)
 {
- 	return (struct task_struct *)
+	return (struct task_struct *)
 		((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
 }
 
@@ -120,4 +120,11 @@
 				       struct task_struct *proxy_owner);
 extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
 				  struct task_struct *proxy_owner);
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
+
 #endif
diff --git a/kernel/sched.c b/kernel/sched.c
index 3332bbb..cb31fb4 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -736,7 +736,9 @@
  *
  * The "10% effect" is relative and cumulative: from _any_ nice level,
  * if you go up 1 level, it's -10% CPU usage, if you go down 1 level
- * it's +10% CPU usage.
+ * it's +10% CPU usage. (to achieve that we use a multiplier of 1.25.
+ * If a task goes up by ~10% and another task goes down by ~10% then
+ * the relative distance between them is ~25%.)
  */
 static const int prio_to_weight[40] = {
 /* -20 */ 88818, 71054, 56843, 45475, 36380, 29104, 23283, 18626, 14901, 11921,
@@ -746,15 +748,22 @@
 /*  10 */   110,    87,    70,    56,    45,    36,    29,    23,    18,    15,
 };
 
+/*
+ * Inverse (2^32/x) values of the prio_to_weight[] array, precalculated.
+ *
+ * In cases where the weight does not change often, we can use the
+ * precalculated inverse to speed up arithmetics by turning divisions
+ * into multiplications:
+ */
 static const u32 prio_to_wmult[40] = {
-	48356,   60446,   75558,   94446,  118058,  147573,
-	184467,  230589,  288233,  360285,  450347,
-	562979,  703746,  879575, 1099582, 1374389,
-	1717986, 2147483, 2684354, 3355443, 4194304,
-	5244160, 6557201, 8196502, 10250518, 12782640,
-	16025997, 19976592, 24970740, 31350126, 39045157,
-	49367440, 61356675, 76695844, 95443717, 119304647,
-	148102320, 186737708, 238609294, 286331153,
+/* -20 */     48356,     60446,     75558,     94446,    118058,
+/* -15 */    147573,    184467,    230589,    288233,    360285,
+/* -10 */    450347,    562979,    703746,    879575,   1099582,
+/*  -5 */   1374389,   1717986,   2147483,   2684354,   3355443,
+/*   0 */   4194304,   5244160,   6557201,   8196502,  10250518,
+/*   5 */  12782640,  16025997,  19976592,  24970740,  31350126,
+/*  10 */  39045157,  49367440,  61356675,  76695844,  95443717,
+/*  15 */ 119304647, 148102320, 186737708, 238609294, 286331153,
 };
 
 static inline void
@@ -4903,8 +4912,6 @@
 		struct migration_req *req;
 		struct list_head *head;
 
-		try_to_freeze();
-
 		spin_lock_irq(&rq->lock);
 
 		if (cpu_is_offline(cpu)) {
@@ -5138,7 +5145,6 @@
 		p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
 		if (IS_ERR(p))
 			return NOTIFY_BAD;
-		p->flags |= PF_NOFREEZE;
 		kthread_bind(p, cpu);
 		/* Must be high prio: stop_machine expects to yield to it. */
 		rq = task_rq_lock(p, &flags);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index c3391b6..ad64fcb 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -10,6 +10,7 @@
 #include <linux/sched.h>
 
 /* #define SECCOMP_DEBUG 1 */
+#define NR_SECCOMP_MODES 1
 
 /*
  * Secure computing mode 1 allows only read/write/exit/sigreturn.
@@ -54,3 +55,31 @@
 #endif
 	do_exit(SIGKILL);
 }
+
+long prctl_get_seccomp(void)
+{
+	return current->seccomp.mode;
+}
+
+long prctl_set_seccomp(unsigned long seccomp_mode)
+{
+	long ret;
+
+	/* can set it only once to be even more secure */
+	ret = -EPERM;
+	if (unlikely(current->seccomp.mode))
+		goto out;
+
+	ret = -EINVAL;
+	if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
+		current->seccomp.mode = seccomp_mode;
+		set_thread_flag(TIF_SECCOMP);
+#ifdef TIF_NOTSC
+		disable_TSC();
+#endif
+		ret = 0;
+	}
+
+ out:
+	return ret;
+}
diff --git a/kernel/signal.c b/kernel/signal.c
index f940560..39d1227 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -718,6 +718,37 @@
 #define LEGACY_QUEUE(sigptr, sig) \
 	(((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
 
+int print_fatal_signals;
+
+static void print_fatal_signal(struct pt_regs *regs, int signr)
+{
+	printk("%s/%d: potentially unexpected fatal signal %d.\n",
+		current->comm, current->pid, signr);
+
+#ifdef __i386__
+	printk("code at %08lx: ", regs->eip);
+	{
+		int i;
+		for (i = 0; i < 16; i++) {
+			unsigned char insn;
+
+			__get_user(insn, (unsigned char *)(regs->eip + i));
+			printk("%02x ", insn);
+		}
+	}
+#endif
+	printk("\n");
+	show_regs(regs);
+}
+
+static int __init setup_print_fatal_signals(char *str)
+{
+	get_option (&str, &print_fatal_signals);
+
+	return 1;
+}
+
+__setup("print-fatal-signals=", setup_print_fatal_signals);
 
 static int
 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
@@ -1855,6 +1886,8 @@
 		 * Anything else is fatal, maybe with a core dump.
 		 */
 		current->flags |= PF_SIGNALED;
+		if ((signr != SIGKILL) && print_fatal_signals)
+			print_fatal_signal(regs, signr);
 		if (sig_kernel_coredump(signr)) {
 			/*
 			 * If it was able to dump core, this kills all
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 73217a9..0f546dd 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -14,6 +14,7 @@
 #include <linux/notifier.h>
 #include <linux/percpu.h>
 #include <linux/cpu.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/rcupdate.h>
 #include <linux/smp.h>
@@ -488,8 +489,6 @@
 
 static int ksoftirqd(void * __bind_cpu)
 {
-	current->flags |= PF_NOFREEZE;
-
 	set_current_state(TASK_INTERRUPTIBLE);
 
 	while (!kthread_should_stop()) {
@@ -614,12 +613,16 @@
 		kthread_bind(per_cpu(ksoftirqd, hotcpu),
 			     any_online_cpu(cpu_online_map));
 	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
+	case CPU_DEAD_FROZEN: {
+		struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
 		p = per_cpu(ksoftirqd, hotcpu);
 		per_cpu(ksoftirqd, hotcpu) = NULL;
+		sched_setscheduler(p, SCHED_FIFO, &param);
 		kthread_stop(p);
 		takeover_tasklets(hotcpu);
 		break;
+	}
 #endif /* CONFIG_HOTPLUG_CPU */
  	}
 	return NOTIFY_OK;
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 0131e29..708d488 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -10,6 +10,7 @@
 #include <linux/cpu.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/notifier.h>
 #include <linux/module.h>
@@ -116,7 +117,6 @@
 	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
-	current->flags |= PF_NOFREEZE;
 
 	/* initialize timestamp */
 	touch_softlockup_watchdog();
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index fcee2a8..319821e 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -93,10 +93,6 @@
 static int stop_machine(void)
 {
 	int i, ret = 0;
-	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
-
-	/* One high-prio thread per cpu.  We'll do this one. */
-	sched_setscheduler(current, SCHED_FIFO, &param);
 
 	atomic_set(&stopmachine_thread_ack, 0);
 	stopmachine_num_threads = 0;
@@ -189,6 +185,10 @@
 
 	p = kthread_create(do_stop, &smdata, "kstopmachine");
 	if (!IS_ERR(p)) {
+		struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
+		/* One high-prio thread per cpu.  We'll do this one. */
+		sched_setscheduler(p, SCHED_FIFO, &param);
 		kthread_bind(p, cpu);
 		wake_up_process(p);
 		wait_for_completion(&smdata.done);
diff --git a/kernel/sys.c b/kernel/sys.c
index 872271c..4d141ae 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -31,10 +31,12 @@
 #include <linux/cn_proc.h>
 #include <linux/getcpu.h>
 #include <linux/task_io_accounting_ops.h>
+#include <linux/seccomp.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
 #include <linux/kprobes.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -1078,13 +1080,13 @@
 {
 	struct user_struct *new_user;
 
-	new_user = alloc_uid(new_ruid);
+	new_user = alloc_uid(current->nsproxy->user_ns, new_ruid);
 	if (!new_user)
 		return -EAGAIN;
 
 	if (atomic_read(&new_user->processes) >=
 				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
-			new_user != &root_user) {
+			new_user != current->nsproxy->user_ns->root_user) {
 		free_uid(new_user);
 		return -EAGAIN;
 	}
@@ -2241,6 +2243,13 @@
 			error = SET_ENDIAN(current, arg2);
 			break;
 
+		case PR_GET_SECCOMP:
+			error = prctl_get_seccomp();
+			break;
+		case PR_SET_SECCOMP:
+			error = prctl_set_seccomp(arg2);
+			break;
+
 		default:
 			error = -EINVAL;
 			break;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 7e11e2c..b0ec498 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -14,6 +14,7 @@
 
 cond_syscall(sys_nfsservctl);
 cond_syscall(sys_quotactl);
+cond_syscall(sys32_quotactl);
 cond_syscall(sys_acct);
 cond_syscall(sys_lookup_dcookie);
 cond_syscall(sys_swapon);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d93e13d..7063ebc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -29,6 +29,7 @@
 #include <linux/utsname.h>
 #include <linux/capability.h>
 #include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kobject.h>
@@ -49,9 +50,6 @@
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
-                     void __user *buffer, size_t *lenp, loff_t *ppos);
-
 #ifdef CONFIG_X86
 #include <asm/nmi.h>
 #include <asm/stacktrace.h>
@@ -61,6 +59,7 @@
 
 /* External variables not in a header file. */
 extern int C_A_D;
+extern int print_fatal_signals;
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int sysctl_panic_on_oom;
@@ -202,7 +201,10 @@
 		.mode		= 0555,
 		.child		= dev_table,
 	},
-
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
 	{ .ctl_name = 0 }
 };
 
@@ -340,6 +342,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "print-fatal-signals",
+		.data		= &print_fatal_signals,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 #ifdef __sparc__
 	{
 		.ctl_name	= KERN_SPARC_REBOOT,
@@ -814,6 +824,14 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	 },
+	 {
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "hugepages_treat_as_movable",
+		.data		= &hugepages_treat_as_movable,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &hugetlb_treat_movable_handler,
+	},
 #endif
 	{
 		.ctl_name	= VM_LOWMEM_RESERVE_RATIO,
@@ -958,6 +976,17 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_doulongvec_minmax,
 	},
+#ifdef CONFIG_NUMA
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "numa_zonelist_order",
+		.data		= &numa_zonelist_order,
+		.maxlen		= NUMA_ZONELIST_ORDER_LEN,
+		.mode		= 0644,
+		.proc_handler	= &numa_zonelist_order_handler,
+		.strategy	= &sysctl_string,
+	},
+#endif
 #endif
 #if defined(CONFIG_X86_32) || \
    (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
@@ -972,6 +1001,10 @@
 		.extra1		= &zero,
 	},
 #endif
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
 	{ .ctl_name = 0 }
 };
 
@@ -1112,6 +1145,10 @@
 		.child		= binfmt_misc_table,
 	},
 #endif
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
 	{ .ctl_name = 0 }
 };
 
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 906cae7..059431e 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -196,6 +196,8 @@
 
 	/* fill in basic acct fields */
 	stats->version = TASKSTATS_VERSION;
+	stats->nvcsw = tsk->nvcsw;
+	stats->nivcsw = tsk->nivcsw;
 	bacct_add_tsk(stats, tsk);
 
 	/* fill in extended acct fields */
@@ -242,6 +244,8 @@
 		 */
 		delayacct_add_tsk(stats, tsk);
 
+		stats->nvcsw += tsk->nvcsw;
+		stats->nivcsw += tsk->nivcsw;
 	} while_each_thread(first, tsk);
 
 	unlock_task_sighand(first, &flags);
diff --git a/kernel/time.c b/kernel/time.c
index f04791f..ffe1914 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -57,14 +57,17 @@
  */
 asmlinkage long sys_time(time_t __user * tloc)
 {
-	time_t i;
-	struct timeval tv;
+	/*
+	 * We read xtime.tv_sec atomically - it's updated
+	 * atomically by update_wall_time(), so no need to
+	 * even read-lock the xtime seqlock:
+	 */
+	time_t i = xtime.tv_sec;
 
-	do_gettimeofday(&tv);
-	i = tv.tv_sec;
+	smp_rmb(); /* sys_time() results are coherent */
 
 	if (tloc) {
-		if (put_user(i,tloc))
+		if (put_user(i, tloc))
 			i = -EFAULT;
 	}
 	return i;
@@ -373,12 +376,25 @@
 
 	tv->tv_sec = sec;
 	tv->tv_usec = usec;
-}
 
+	/*
+	 * Make sure xtime.tv_sec [returned by sys_time()] always
+	 * follows the gettimeofday() result precisely. This
+	 * condition is extremely unlikely, it can hit at most
+	 * once per second:
+	 */
+	if (unlikely(xtime.tv_sec != tv->tv_sec)) {
+		unsigned long flags;
+
+		write_seqlock_irqsave(&xtime_lock, flags);
+		update_wall_time();
+		write_sequnlock_irqrestore(&xtime_lock, flags);
+	}
+}
 EXPORT_SYMBOL(do_gettimeofday);
 
+#else	/* CONFIG_TIME_INTERPOLATION */
 
-#else
 #ifndef CONFIG_GENERIC_TIME
 /*
  * Simulate gettimeofday using do_gettimeofday which only allows a timeval
@@ -394,7 +410,7 @@
 }
 EXPORT_SYMBOL_GPL(getnstimeofday);
 #endif
-#endif
+#endif	/* CONFIG_TIME_INTERPOLATION */
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 76212b2..2ad1c37 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -205,47 +205,6 @@
 }
 
 /**
- * clockevents_request_device
- */
-struct clock_event_device *clockevents_request_device(unsigned int features,
-						      cpumask_t cpumask)
-{
-	struct clock_event_device *cur, *dev = NULL;
-	struct list_head *tmp;
-
-	spin_lock(&clockevents_lock);
-
-	list_for_each(tmp, &clockevent_devices) {
-		cur = list_entry(tmp, struct clock_event_device, list);
-
-		if ((cur->features & features) == features &&
-		    cpus_equal(cpumask, cur->cpumask)) {
-			if (!dev || dev->rating < cur->rating)
-				dev = cur;
-		}
-	}
-
-	clockevents_exchange_device(NULL, dev);
-
-	spin_unlock(&clockevents_lock);
-
-	return dev;
-}
-
-/**
- * clockevents_release_device
- */
-void clockevents_release_device(struct clock_event_device *dev)
-{
-	spin_lock(&clockevents_lock);
-
-	clockevents_exchange_device(dev, NULL);
-	clockevents_notify_released();
-
-	spin_unlock(&clockevents_lock);
-}
-
-/**
  * clockevents_notify - notification about relevant events
  */
 void clockevents_notify(unsigned long reason, void *arg)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index cf53bb5..438c6b7 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -13,7 +13,7 @@
 #include <linux/timex.h>
 #include <linux/jiffies.h>
 #include <linux/hrtimer.h>
-
+#include <linux/capability.h>
 #include <asm/div64.h>
 #include <asm/timex.h>
 
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 3d1042f..728cedf 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -36,9 +36,17 @@
  * at zero at system boot time, so wall_to_monotonic will be negative,
  * however, we will ALWAYS keep the tv_nsec part positive so we can use
  * the usual normalization.
+ *
+ * wall_to_monotonic is moved after resume from suspend for the monotonic
+ * time not to jump. We need to add total_sleep_time to wall_to_monotonic
+ * to get the real boot based time offset.
+ *
+ * - wall_to_monotonic is no longer the boot time, getboottime must be
+ * used instead.
  */
 struct timespec xtime __attribute__ ((aligned (16)));
 struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+static unsigned long total_sleep_time;		/* seconds */
 
 EXPORT_SYMBOL(xtime);
 
@@ -251,6 +259,7 @@
 	xtime.tv_nsec = 0;
 	set_normalized_timespec(&wall_to_monotonic,
 		-xtime.tv_sec, -xtime.tv_nsec);
+	total_sleep_time = 0;
 
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 }
@@ -282,6 +291,7 @@
 
 		xtime.tv_sec += sleep_length;
 		wall_to_monotonic.tv_sec -= sleep_length;
+		total_sleep_time += sleep_length;
 	}
 	/* re-base the last cycle value */
 	clock->cycle_last = clocksource_read(clock);
@@ -476,3 +486,30 @@
 	change_clocksource();
 	update_vsyscall(&xtime, clock);
 }
+
+/**
+ * getboottime - Return the real time of system boot.
+ * @ts:		pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec.
+ *
+ * This is based on the wall_to_monotonic offset and the total suspend
+ * time. Calls to settimeofday will affect the value returned (which
+ * basically means that however wrong your real time clock is at boot time,
+ * you get the right time here).
+ */
+void getboottime(struct timespec *ts)
+{
+	set_normalized_timespec(ts,
+		- (wall_to_monotonic.tv_sec + total_sleep_time),
+		- wall_to_monotonic.tv_nsec);
+}
+
+/**
+ * monotonic_to_bootbased - Convert the monotonic time to boot based.
+ * @ts:		pointer to the timespec to be converted
+ */
+void monotonic_to_bootbased(struct timespec *ts)
+{
+	ts->tv_sec += total_sleep_time;
+}
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 8bbcfb7..e5edc3a 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -38,7 +38,7 @@
 
 static void print_name_offset(struct seq_file *m, void *sym)
 {
-	char symname[KSYM_NAME_LEN+1];
+	char symname[KSYM_NAME_LEN];
 
 	if (lookup_symbol_name((unsigned long)sym, symname) < 0)
 		SEQ_printf(m, "<%p>", sym);
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index 3216937..8ed62fd 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -68,6 +68,7 @@
 	 * Number of timeout events:
 	 */
 	unsigned long		count;
+	unsigned int		timer_flag;
 
 	/*
 	 * We save the command-line string to preserve
@@ -231,7 +232,8 @@
  * incremented. Otherwise the timer is registered in a free slot.
  */
 void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-			      void *timerf, char * comm)
+			      void *timerf, char *comm,
+			      unsigned int timer_flag)
 {
 	/*
 	 * It doesnt matter which lock we take:
@@ -249,6 +251,7 @@
 	input.start_func = startf;
 	input.expire_func = timerf;
 	input.pid = pid;
+	input.timer_flag = timer_flag;
 
 	spin_lock_irqsave(lock, flags);
 	if (!active)
@@ -266,7 +269,7 @@
 
 static void print_name_offset(struct seq_file *m, unsigned long addr)
 {
-	char symname[KSYM_NAME_LEN+1];
+	char symname[KSYM_NAME_LEN];
 
 	if (lookup_symbol_name(addr, symname) < 0)
 		seq_printf(m, "<%p>", (void *)addr);
@@ -295,7 +298,7 @@
 	period = ktime_to_timespec(time);
 	ms = period.tv_nsec / 1000000;
 
-	seq_puts(m, "Timer Stats Version: v0.1\n");
+	seq_puts(m, "Timer Stats Version: v0.2\n");
 	seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
 	if (atomic_read(&overflow_count))
 		seq_printf(m, "Overflow: %d entries\n",
@@ -303,8 +306,13 @@
 
 	for (i = 0; i < nr_entries; i++) {
 		entry = entries + i;
-		seq_printf(m, "%4lu, %5d %-16s ",
+ 		if (entry->timer_flag & TIMER_STATS_FLAG_DEFERRABLE) {
+			seq_printf(m, "%4luD, %5d %-16s ",
 				entry->count, entry->pid, entry->comm);
+		} else {
+			seq_printf(m, " %4lu, %5d %-16s ",
+				entry->count, entry->pid, entry->comm);
+		}
 
 		print_name_offset(m, (unsigned long)entry->start_func);
 		seq_puts(m, " (");
diff --git a/kernel/timer.c b/kernel/timer.c
index 1a69705..b7792fb 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -305,6 +305,20 @@
 	memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
 	timer->start_pid = current->pid;
 }
+
+static void timer_stats_account_timer(struct timer_list *timer)
+{
+	unsigned int flag = 0;
+
+	if (unlikely(tbase_get_deferrable(timer->base)))
+		flag |= TIMER_STATS_FLAG_DEFERRABLE;
+
+	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+				 timer->function, timer->start_comm, flag);
+}
+
+#else
+static void timer_stats_account_timer(struct timer_list *timer) {}
 #endif
 
 /**
@@ -1114,6 +1128,7 @@
 		getnstimeofday(&tp);
 		tp.tv_sec += wall_to_monotonic.tv_sec;
 		tp.tv_nsec += wall_to_monotonic.tv_nsec;
+		monotonic_to_bootbased(&tp);
 		if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
 			tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
 			tp.tv_sec++;
@@ -1206,7 +1221,8 @@
 			/*
 			 * The APs use this path later in boot
 			 */
-			base = kmalloc_node(sizeof(*base), GFP_KERNEL,
+			base = kmalloc_node(sizeof(*base),
+						GFP_KERNEL | __GFP_ZERO,
 						cpu_to_node(cpu));
 			if (!base)
 				return -ENOMEM;
@@ -1217,7 +1233,6 @@
 				kfree(base);
 				return -ENOMEM;
 			}
-			memset(base, 0, sizeof(*base));
 			per_cpu(tvec_bases, cpu) = base;
 		} else {
 			/*
diff --git a/kernel/user.c b/kernel/user.c
index 4869563..98b8250 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -14,20 +14,19 @@
 #include <linux/bitops.h>
 #include <linux/key.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/user_namespace.h>
 
 /*
  * UID task count cache, to get fast user lookup in "alloc_uid"
  * when changing user ID's (ie setuid() and friends).
  */
 
-#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
-#define UIDHASH_SZ		(1 << UIDHASH_BITS)
 #define UIDHASH_MASK		(UIDHASH_SZ - 1)
 #define __uidhashfn(uid)	(((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
-#define uidhashentry(uid)	(uidhash_table + __uidhashfn((uid)))
+#define uidhashentry(ns, uid)	((ns)->uidhash_table + __uidhashfn((uid)))
 
 static struct kmem_cache *uid_cachep;
-static struct list_head uidhash_table[UIDHASH_SZ];
 
 /*
  * The uidhash_lock is mostly taken from process context, but it is
@@ -94,9 +93,10 @@
 {
 	struct user_struct *ret;
 	unsigned long flags;
+	struct user_namespace *ns = current->nsproxy->user_ns;
 
 	spin_lock_irqsave(&uidhash_lock, flags);
-	ret = uid_hash_find(uid, uidhashentry(uid));
+	ret = uid_hash_find(uid, uidhashentry(ns, uid));
 	spin_unlock_irqrestore(&uidhash_lock, flags);
 	return ret;
 }
@@ -120,9 +120,9 @@
 	}
 }
 
-struct user_struct * alloc_uid(uid_t uid)
+struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
 {
-	struct list_head *hashent = uidhashentry(uid);
+	struct list_head *hashent = uidhashentry(ns, uid);
 	struct user_struct *up;
 
 	spin_lock_irq(&uidhash_lock);
@@ -211,11 +211,11 @@
 			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 
 	for(n = 0; n < UIDHASH_SZ; ++n)
-		INIT_LIST_HEAD(uidhash_table + n);
+		INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
 
 	/* Insert the root user immediately (init already runs as root) */
 	spin_lock_irq(&uidhash_lock);
-	uid_hash_insert(&root_user, uidhashentry(0));
+	uid_hash_insert(&root_user, uidhashentry(&init_user_ns, 0));
 	spin_unlock_irq(&uidhash_lock);
 
 	return 0;
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
new file mode 100644
index 0000000..d055d98
--- /dev/null
+++ b/kernel/user_namespace.c
@@ -0,0 +1,87 @@
+/*
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation, version 2 of the
+ *  License.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/nsproxy.h>
+#include <linux/user_namespace.h>
+
+struct user_namespace init_user_ns = {
+	.kref = {
+		.refcount	= ATOMIC_INIT(2),
+	},
+	.root_user = &root_user,
+};
+
+EXPORT_SYMBOL_GPL(init_user_ns);
+
+#ifdef CONFIG_USER_NS
+
+/*
+ * Clone a new ns copying an original user ns, setting refcount to 1
+ * @old_ns: namespace to clone
+ * Return NULL on error (failure to kmalloc), new ns otherwise
+ */
+static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
+{
+	struct user_namespace *ns;
+	struct user_struct *new_user;
+	int n;
+
+	ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL);
+	if (!ns)
+		return ERR_PTR(-ENOMEM);
+
+	kref_init(&ns->kref);
+
+	for (n = 0; n < UIDHASH_SZ; ++n)
+		INIT_LIST_HEAD(ns->uidhash_table + n);
+
+	/* Insert new root user.  */
+	ns->root_user = alloc_uid(ns, 0);
+	if (!ns->root_user) {
+		kfree(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Reset current->user with a new one */
+	new_user = alloc_uid(ns, current->uid);
+	if (!new_user) {
+		free_uid(ns->root_user);
+		kfree(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	switch_uid(new_user);
+	return ns;
+}
+
+struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns)
+{
+	struct user_namespace *new_ns;
+
+	BUG_ON(!old_ns);
+	get_user_ns(old_ns);
+
+	if (!(flags & CLONE_NEWUSER))
+		return old_ns;
+
+	new_ns = clone_user_ns(old_ns);
+
+	put_user_ns(old_ns);
+	return new_ns;
+}
+
+void free_user_ns(struct kref *kref)
+{
+	struct user_namespace *ns;
+
+	ns = container_of(kref, struct user_namespace, kref);
+	kfree(ns);
+}
+
+#endif /* CONFIG_USER_NS */
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 160c8c5..9d8180a 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -13,6 +13,7 @@
 #include <linux/uts.h>
 #include <linux/utsname.h>
 #include <linux/version.h>
+#include <linux/err.h>
 
 /*
  * Clone a new ns copying an original utsname, setting refcount to 1
@@ -24,10 +25,11 @@
 	struct uts_namespace *ns;
 
 	ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL);
-	if (ns) {
-		memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
-		kref_init(&ns->kref);
-	}
+	if (!ns)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
+	kref_init(&ns->kref);
 	return ns;
 }
 
@@ -37,7 +39,7 @@
  * utsname of this process won't be seen by parent, and vice
  * versa.
  */
-struct uts_namespace *copy_utsname(int flags, struct uts_namespace *old_ns)
+struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns)
 {
 	struct uts_namespace *new_ns;
 
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
index f22b9db..c76c064 100644
--- a/kernel/utsname_sysctl.c
+++ b/kernel/utsname_sysctl.c
@@ -18,10 +18,7 @@
 static void *get_uts(ctl_table *table, int write)
 {
 	char *which = table->data;
-#ifdef CONFIG_UTS_NS
-	struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
-	which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
-#endif
+
 	if (!write)
 		down_read(&uts_sem);
 	else
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 3bebf73..58e5c15 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -282,8 +282,8 @@
 	struct cpu_workqueue_struct *cwq = __cwq;
 	DEFINE_WAIT(wait);
 
-	if (!cwq->wq->freezeable)
-		current->flags |= PF_NOFREEZE;
+	if (cwq->wq->freezeable)
+		set_freezable();
 
 	set_user_nice(current, -5);
 
@@ -382,16 +382,16 @@
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
 /*
- * Upon a successful return, the caller "owns" WORK_STRUCT_PENDING bit,
+ * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit,
  * so this work can't be re-armed in any way.
  */
 static int try_to_grab_pending(struct work_struct *work)
 {
 	struct cpu_workqueue_struct *cwq;
-	int ret = 0;
+	int ret = -1;
 
 	if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work)))
-		return 1;
+		return 0;
 
 	/*
 	 * The queueing is in progress, or it is already queued. Try to
@@ -457,10 +457,28 @@
 		wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
 }
 
+static int __cancel_work_timer(struct work_struct *work,
+				struct timer_list* timer)
+{
+	int ret;
+
+	do {
+		ret = (timer && likely(del_timer(timer)));
+		if (!ret)
+			ret = try_to_grab_pending(work);
+		wait_on_work(work);
+	} while (unlikely(ret < 0));
+
+	work_clear_pending(work);
+	return ret;
+}
+
 /**
  * cancel_work_sync - block until a work_struct's callback has terminated
  * @work: the work which is to be flushed
  *
+ * Returns true if @work was pending.
+ *
  * cancel_work_sync() will cancel the work if it is queued. If the work's
  * callback appears to be running, cancel_work_sync() will block until it
  * has completed.
@@ -476,31 +494,26 @@
  * The caller must ensure that workqueue_struct on which this work was last
  * queued can't be destroyed before this function returns.
  */
-void cancel_work_sync(struct work_struct *work)
+int cancel_work_sync(struct work_struct *work)
 {
-	while (!try_to_grab_pending(work))
-		cpu_relax();
-	wait_on_work(work);
-	work_clear_pending(work);
+	return __cancel_work_timer(work, NULL);
 }
 EXPORT_SYMBOL_GPL(cancel_work_sync);
 
 /**
- * cancel_rearming_delayed_work - reliably kill off a delayed work.
+ * cancel_delayed_work_sync - reliably kill off a delayed work.
  * @dwork: the delayed work struct
  *
+ * Returns true if @dwork was pending.
+ *
  * It is possible to use this function if @dwork rearms itself via queue_work()
  * or queue_delayed_work(). See also the comment for cancel_work_sync().
  */
-void cancel_rearming_delayed_work(struct delayed_work *dwork)
+int cancel_delayed_work_sync(struct delayed_work *dwork)
 {
-	while (!del_timer(&dwork->timer) &&
-	       !try_to_grab_pending(&dwork->work))
-		cpu_relax();
-	wait_on_work(&dwork->work);
-	work_clear_pending(&dwork->work);
+	return __cancel_work_timer(&dwork->work, &dwork->timer);
 }
-EXPORT_SYMBOL(cancel_rearming_delayed_work);
+EXPORT_SYMBOL(cancel_delayed_work_sync);
 
 static struct workqueue_struct *keventd_wq __read_mostly;
 
@@ -739,18 +752,17 @@
 	if (cwq->thread == NULL)
 		return;
 
+	flush_cpu_workqueue(cwq);
 	/*
-	 * If the caller is CPU_DEAD the single flush_cpu_workqueue()
-	 * is not enough, a concurrent flush_workqueue() can insert a
-	 * barrier after us.
+	 * If the caller is CPU_DEAD and cwq->worklist was not empty,
+	 * a concurrent flush_workqueue() can insert a barrier after us.
+	 * However, in that case run_workqueue() won't return and check
+	 * kthread_should_stop() until it flushes all work_struct's.
 	 * When ->worklist becomes empty it is safe to exit because no
 	 * more work_structs can be queued on this cwq: flush_workqueue
 	 * checks list_empty(), and a "normal" queue_work() can't use
 	 * a dead CPU.
 	 */
-	while (flush_cpu_workqueue(cwq))
-		;
-
 	kthread_stop(cwq->thread);
 	cwq->thread = NULL;
 }
diff --git a/lib/Kconfig b/lib/Kconfig
index 3eb29d5..e5c2c51 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -41,6 +41,14 @@
 	  kernel tree does. Such modules that use library CRC32 functions
 	  require M here.
 
+config CRC7
+	tristate "CRC7 functions"
+	help
+	  This option is provided for the case where no in-kernel-tree
+	  modules require CRC7 functions, but a module built outside
+	  the kernel tree does. Such modules that use library CRC7
+	  functions require M here.
+
 config LIBCRC32C
 	tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
 	help
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index fab32a2..6408440 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -152,6 +152,19 @@
 	bool "Memory leak debugging"
 	depends on DEBUG_SLAB
 
+config SLUB_DEBUG_ON
+	bool "SLUB debugging on by default"
+	depends on SLUB && SLUB_DEBUG
+	default n
+	help
+	  Boot with debugging on by default. SLUB boots by default with
+	  the runtime debug capabilities switched off. Enabling this is
+	  equivalent to specifying the "slub_debug" parameter on boot.
+	  There is no support for more fine grained debug control like
+	  possible with slub_debug=xxx. SLUB debugging may be switched
+	  off in a kernel built with CONFIG_SLUB_DEBUG_ON by specifying
+	  "slub_debug=-".
+
 config DEBUG_PREEMPT
 	bool "Debug preemptible kernel"
 	depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
diff --git a/lib/Makefile b/lib/Makefile
index d1b366b..da68b2c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -21,7 +21,7 @@
 endif
 
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
-obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
+obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
@@ -43,6 +43,7 @@
 obj-$(CONFIG_CRC16)	+= crc16.o
 obj-$(CONFIG_CRC_ITU_T)	+= crc-itu-t.o
 obj-$(CONFIG_CRC32)	+= crc32.o
+obj-$(CONFIG_CRC7)	+= crc7.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
diff --git a/lib/bug.c b/lib/bug.c
index 014b582..530f38f 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -38,6 +38,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/bug.h>
+#include <linux/sched.h>
 
 extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
 
@@ -112,7 +113,7 @@
 	return module_find_bug(bugaddr);
 }
 
-enum bug_trap_type report_bug(unsigned long bugaddr)
+enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
 {
 	const struct bug_entry *bug;
 	const char *file;
@@ -147,7 +148,7 @@
 			       "[verbose debug info unavailable]\n",
 			       (void *)bugaddr);
 
-		dump_stack();
+		show_regs(regs);
 		return BUG_TRAP_TYPE_WARN;
 	}
 
diff --git a/lib/check_signature.c b/lib/check_signature.c
new file mode 100644
index 0000000..fd6af19
--- /dev/null
+++ b/lib/check_signature.c
@@ -0,0 +1,26 @@
+#include <linux/io.h>
+#include <linux/module.h>
+
+/**
+ *	check_signature		-	find BIOS signatures
+ *	@io_addr: mmio address to check
+ *	@signature:  signature block
+ *	@length: length of signature
+ *
+ *	Perform a signature comparison with the mmio address io_addr. This
+ *	address should have been obtained by ioremap.
+ *	Returns 1 on a match.
+ */
+
+int check_signature(const volatile void __iomem *io_addr,
+			const unsigned char *signature, int length)
+{
+	while (length--) {
+		if (readb(io_addr) != *signature)
+			return 0;
+		io_addr++;
+		signature++;
+	}
+	return 1;
+}
+EXPORT_SYMBOL(check_signature);
diff --git a/lib/crc7.c b/lib/crc7.c
new file mode 100644
index 0000000..f1c3a14
--- /dev/null
+++ b/lib/crc7.c
@@ -0,0 +1,68 @@
+/*
+ *      crc7.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/crc7.h>
+
+
+/* Table for CRC-7 (polynomial x^7 + x^3 + 1) */
+const u8 crc7_syndrome_table[256] = {
+	0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+	0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+	0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+	0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
+	0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
+	0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+	0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
+	0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
+	0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+	0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
+	0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
+	0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+	0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
+	0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
+	0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+	0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
+	0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
+	0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+	0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
+	0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
+	0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+	0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+	0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
+	0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+	0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
+	0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
+	0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+	0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
+	0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
+	0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+	0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
+	0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
+};
+EXPORT_SYMBOL(crc7_syndrome_table);
+
+/**
+ * crc7 - update the CRC7 for the data buffer
+ * @crc:     previous CRC7 value
+ * @buffer:  data pointer
+ * @len:     number of bytes in the buffer
+ * Context: any
+ *
+ * Returns the updated CRC7 value.
+ */
+u8 crc7(u8 crc, const u8 *buffer, size_t len)
+{
+	while (len--)
+		crc = crc7_byte(crc, *buffer++);
+	return crc;
+}
+EXPORT_SYMBOL(crc7);
+
+MODULE_DESCRIPTION("CRC7 calculations");
+MODULE_LICENSE("GPL");
diff --git a/lib/genalloc.c b/lib/genalloc.c
index eb7c2ba..f6d276d 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -54,11 +54,10 @@
 	int nbytes = sizeof(struct gen_pool_chunk) +
 				(nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
 
-	chunk = kmalloc_node(nbytes, GFP_KERNEL, nid);
+	chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
 	if (unlikely(chunk == NULL))
 		return -1;
 
-	memset(chunk, 0, nbytes);
 	spin_lock_init(&chunk->lock);
 	chunk->start_addr = addr;
 	chunk->end_addr = addr + size;
diff --git a/lib/idr.c b/lib/idr.c
index b98f01a..5ca67b3 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -391,6 +391,53 @@
 EXPORT_SYMBOL(idr_remove);
 
 /**
+ * idr_remove_all - remove all ids from the given idr tree
+ * @idp: idr handle
+ *
+ * idr_destroy() only frees up unused, cached idp_layers, but this
+ * function will remove all id mappings and leave all idp_layers
+ * unused.
+ *
+ * A typical clean-up sequence for objects stored in an idr tree, will
+ * use idr_for_each() to free all objects, if necessay, then
+ * idr_remove_all() to remove all ids, and idr_destroy() to free
+ * up the cached idr_layers.
+ */
+void idr_remove_all(struct idr *idp)
+{
+	int n, id, max, error = 0;
+	struct idr_layer *p;
+	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer **paa = &pa[0];
+
+	n = idp->layers * IDR_BITS;
+	p = idp->top;
+	max = 1 << n;
+
+	id = 0;
+	while (id < max && !error) {
+		while (n > IDR_BITS && p) {
+			n -= IDR_BITS;
+			*paa++ = p;
+			p = p->ary[(id >> n) & IDR_MASK];
+		}
+
+		id += 1 << n;
+		while (n < fls(id)) {
+			if (p) {
+				memset(p, 0, sizeof *p);
+				free_layer(idp, p);
+			}
+			n += IDR_BITS;
+			p = *--paa;
+		}
+	}
+	idp->top = NULL;
+	idp->layers = 0;
+}
+EXPORT_SYMBOL(idr_remove_all);
+
+/**
  * idr_destroy - release all cached layers within an idr tree
  * idp: idr handle
  */
@@ -437,6 +484,61 @@
 EXPORT_SYMBOL(idr_find);
 
 /**
+ * idr_for_each - iterate through all stored pointers
+ * @idp: idr handle
+ * @fn: function to be called for each pointer
+ * @data: data passed back to callback function
+ *
+ * Iterate over the pointers registered with the given idr.  The
+ * callback function will be called for each pointer currently
+ * registered, passing the id, the pointer and the data pointer passed
+ * to this function.  It is not safe to modify the idr tree while in
+ * the callback, so functions such as idr_get_new and idr_remove are
+ * not allowed.
+ *
+ * We check the return of @fn each time. If it returns anything other
+ * than 0, we break out and return that value.
+ *
+ * The caller must serialize idr_for_each() vs idr_get_new() and idr_remove().
+ */
+int idr_for_each(struct idr *idp,
+		 int (*fn)(int id, void *p, void *data), void *data)
+{
+	int n, id, max, error = 0;
+	struct idr_layer *p;
+	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer **paa = &pa[0];
+
+	n = idp->layers * IDR_BITS;
+	p = idp->top;
+	max = 1 << n;
+
+	id = 0;
+	while (id < max) {
+		while (n > 0 && p) {
+			n -= IDR_BITS;
+			*paa++ = p;
+			p = p->ary[(id >> n) & IDR_MASK];
+		}
+
+		if (p) {
+			error = fn(id, (void *)p, data);
+			if (error)
+				break;
+		}
+
+		id += 1 << n;
+		while (n < fls(id)) {
+			n += IDR_BITS;
+			p = *--paa;
+		}
+	}
+
+	return error;
+}
+EXPORT_SYMBOL(idr_for_each);
+
+/**
  * idr_replace - replace pointer for given id
  * @idp: idr handle
  * @ptr: pointer you want associated with the id
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 8504490..cf22c61 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -3,8 +3,17 @@
  */
 
 #include <linux/percpu_counter.h>
+#include <linux/notifier.h>
+#include <linux/mutex.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
 #include <linux/module.h>
 
+#ifdef CONFIG_HOTPLUG_CPU
+static LIST_HEAD(percpu_counters);
+static DEFINE_MUTEX(percpu_counters_lock);
+#endif
+
 void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
 {
 	long count;
@@ -36,7 +45,7 @@
 
 	spin_lock(&fbc->lock);
 	ret = fbc->count;
-	for_each_possible_cpu(cpu) {
+	for_each_online_cpu(cpu) {
 		s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
 		ret += *pcount;
 	}
@@ -44,3 +53,60 @@
 	return ret < 0 ? 0 : ret;
 }
 EXPORT_SYMBOL(percpu_counter_sum);
+
+void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
+{
+	spin_lock_init(&fbc->lock);
+	fbc->count = amount;
+	fbc->counters = alloc_percpu(s32);
+#ifdef CONFIG_HOTPLUG_CPU
+	mutex_lock(&percpu_counters_lock);
+	list_add(&fbc->list, &percpu_counters);
+	mutex_unlock(&percpu_counters_lock);
+#endif
+}
+EXPORT_SYMBOL(percpu_counter_init);
+
+void percpu_counter_destroy(struct percpu_counter *fbc)
+{
+	free_percpu(fbc->counters);
+#ifdef CONFIG_HOTPLUG_CPU
+	mutex_lock(&percpu_counters_lock);
+	list_del(&fbc->list);
+	mutex_unlock(&percpu_counters_lock);
+#endif
+}
+EXPORT_SYMBOL(percpu_counter_destroy);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb,
+					unsigned long action, void *hcpu)
+{
+	unsigned int cpu;
+	struct percpu_counter *fbc;
+
+	if (action != CPU_DEAD)
+		return NOTIFY_OK;
+
+	cpu = (unsigned long)hcpu;
+	mutex_lock(&percpu_counters_lock);
+	list_for_each_entry(fbc, &percpu_counters, list) {
+		s32 *pcount;
+
+		spin_lock(&fbc->lock);
+		pcount = per_cpu_ptr(fbc->counters, cpu);
+		fbc->count += *pcount;
+		*pcount = 0;
+		spin_unlock(&fbc->lock);
+	}
+	mutex_unlock(&percpu_counters_lock);
+	return NOTIFY_OK;
+}
+
+static int __init percpu_counter_startup(void)
+{
+	hotcpu_notifier(percpu_counter_hotcpu_callback, 0);
+	return 0;
+}
+module_init(percpu_counter_startup);
+#endif
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 0172902..6b6734d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -135,6 +135,103 @@
 	return i;
 }
 
+/* Decimal conversion is by far the most typical, and is used
+ * for /proc and /sys data. This directly impacts e.g. top performance
+ * with many processes running. We optimize it for speed
+ * using code from
+ * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
+ * (with permission from the author, Douglas W. Jones). */
+
+/* Formats correctly any integer in [0,99999].
+ * Outputs from one to five digits depending on input.
+ * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
+static char* put_dec_trunc(char *buf, unsigned q)
+{
+	unsigned d3, d2, d1, d0;
+	d1 = (q>>4) & 0xf;
+	d2 = (q>>8) & 0xf;
+	d3 = (q>>12);
+
+	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+	q = (d0 * 0xcd) >> 11;
+	d0 = d0 - 10*q;
+	*buf++ = d0 + '0'; /* least significant digit */
+	d1 = q + 9*d3 + 5*d2 + d1;
+	if (d1 != 0) {
+		q = (d1 * 0xcd) >> 11;
+		d1 = d1 - 10*q;
+		*buf++ = d1 + '0'; /* next digit */
+
+		d2 = q + 2*d2;
+		if ((d2 != 0) || (d3 != 0)) {
+			q = (d2 * 0xd) >> 7;
+			d2 = d2 - 10*q;
+			*buf++ = d2 + '0'; /* next digit */
+
+			d3 = q + 4*d3;
+			if (d3 != 0) {
+				q = (d3 * 0xcd) >> 11;
+				d3 = d3 - 10*q;
+				*buf++ = d3 + '0';  /* next digit */
+				if (q != 0)
+					*buf++ = q + '0';  /* most sign. digit */
+			}
+		}
+	}
+	return buf;
+}
+/* Same with if's removed. Always emits five digits */
+static char* put_dec_full(char *buf, unsigned q)
+{
+	/* BTW, if q is in [0,9999], 8-bit ints will be enough, */
+	/* but anyway, gcc produces better code with full-sized ints */
+	unsigned d3, d2, d1, d0;
+	d1 = (q>>4) & 0xf;
+	d2 = (q>>8) & 0xf;
+	d3 = (q>>12);
+
+	/* Possible ways to approx. divide by 10 */
+	/* gcc -O2 replaces multiply with shifts and adds */
+	// (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
+	// (x * 0x67) >> 10:  1100111
+	// (x * 0x34) >> 9:    110100 - same
+	// (x * 0x1a) >> 8:     11010 - same
+	// (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
+
+	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+	q = (d0 * 0xcd) >> 11;
+	d0 = d0 - 10*q;
+	*buf++ = d0 + '0';
+	d1 = q + 9*d3 + 5*d2 + d1;
+		q = (d1 * 0xcd) >> 11;
+		d1 = d1 - 10*q;
+		*buf++ = d1 + '0';
+
+		d2 = q + 2*d2;
+			q = (d2 * 0xd) >> 7;
+			d2 = d2 - 10*q;
+			*buf++ = d2 + '0';
+
+			d3 = q + 4*d3;
+				q = (d3 * 0xcd) >> 11; /* - shorter code */
+				/* q = (d3 * 0x67) >> 10; - would also work */
+				d3 = d3 - 10*q;
+				*buf++ = d3 + '0';
+					*buf++ = q + '0';
+	return buf;
+}
+/* No inlining helps gcc to use registers better */
+static noinline char* put_dec(char *buf, unsigned long long num)
+{
+	while (1) {
+		unsigned rem;
+		if (num < 100000)
+			return put_dec_trunc(buf, num);
+		rem = do_div(num, 100000);
+		buf = put_dec_full(buf, rem);
+	}
+}
+
 #define ZEROPAD	1		/* pad with zero */
 #define SIGN	2		/* unsigned/signed long */
 #define PLUS	4		/* show plus */
@@ -143,12 +240,14 @@
 #define SPECIAL	32		/* 0x */
 #define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
 
-static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
+static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
 {
-	char c,sign,tmp[66];
+	char sign,tmp[66];
 	const char *digits;
-	static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-	static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	/* we are called with base 8, 10 or 16, only, thus don't need "g..."  */
+	static const char small_digits[] = "0123456789abcdefx"; /* "ghijklmnopqrstuvwxyz"; */
+	static const char large_digits[] = "0123456789ABCDEFX"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+	int need_pfx = ((type & SPECIAL) && base != 10);
 	int i;
 
 	digits = (type & LARGE) ? large_digits : small_digits;
@@ -156,7 +255,6 @@
 		type &= ~ZEROPAD;
 	if (base < 2 || base > 36)
 		return NULL;
-	c = (type & ZEROPAD) ? '0' : ' ';
 	sign = 0;
 	if (type & SIGN) {
 		if ((signed long long) num < 0) {
@@ -171,64 +269,85 @@
 			size--;
 		}
 	}
-	if (type & SPECIAL) {
+	if (need_pfx) {
+		size--;
 		if (base == 16)
-			size -= 2;
-		else if (base == 8)
 			size--;
 	}
+
+	/* generate full string in tmp[], in reverse order */
 	i = 0;
 	if (num == 0)
-		tmp[i++]='0';
-	else while (num != 0)
+		tmp[i++] = '0';
+	/* Generic code, for any base:
+	else do {
 		tmp[i++] = digits[do_div(num,base)];
+	} while (num != 0);
+	*/
+	else if (base != 10) { /* 8 or 16 */
+		int mask = base - 1;
+		int shift = 3;
+		if (base == 16) shift = 4;
+		do {
+			tmp[i++] = digits[((unsigned char)num) & mask];
+			num >>= shift;
+		} while (num);
+	} else { /* base 10 */
+		i = put_dec(tmp, num) - tmp;
+	}
+
+	/* printing 100 using %2d gives "100", not "00" */
 	if (i > precision)
 		precision = i;
+	/* leading space padding */
 	size -= precision;
-	if (!(type&(ZEROPAD+LEFT))) {
-		while(size-->0) {
+	if (!(type & (ZEROPAD+LEFT))) {
+		while(--size >= 0) {
 			if (buf < end)
 				*buf = ' ';
 			++buf;
 		}
 	}
+	/* sign */
 	if (sign) {
 		if (buf < end)
 			*buf = sign;
 		++buf;
 	}
-	if (type & SPECIAL) {
-		if (base==8) {
+	/* "0x" / "0" prefix */
+	if (need_pfx) {
+		if (buf < end)
+			*buf = '0';
+		++buf;
+		if (base == 16) {
 			if (buf < end)
-				*buf = '0';
-			++buf;
-		} else if (base==16) {
-			if (buf < end)
-				*buf = '0';
-			++buf;
-			if (buf < end)
-				*buf = digits[33];
+				*buf = digits[16]; /* for arbitrary base: digits[33]; */
 			++buf;
 		}
 	}
+	/* zero or space padding */
 	if (!(type & LEFT)) {
-		while (size-- > 0) {
+		char c = (type & ZEROPAD) ? '0' : ' ';
+		while (--size >= 0) {
 			if (buf < end)
 				*buf = c;
 			++buf;
 		}
 	}
-	while (i < precision--) {
+	/* hmm even more zero padding? */
+	while (i <= --precision) {
 		if (buf < end)
 			*buf = '0';
 		++buf;
 	}
-	while (i-- > 0) {
+	/* actual digits of result */
+	while (--i >= 0) {
 		if (buf < end)
 			*buf = tmp[i];
 		++buf;
 	}
-	while (size-- > 0) {
+	/* trailing space padding */
+	while (--size >= 0) {
 		if (buf < end)
 			*buf = ' ';
 		++buf;
@@ -276,7 +395,7 @@
 	   used for unknown buffer sizes. */
 	if (unlikely((int) size < 0)) {
 		/* There can be only one.. */
-		static int warn = 1;
+		static char warn = 1;
 		WARN_ON(warn);
 		warn = 0;
 		return 0;
diff --git a/mm/Kconfig b/mm/Kconfig
index 8ac412b..8618722 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -117,7 +117,7 @@
 	bool "Allow for memory hot-add"
 	depends on SPARSEMEM || X86_64_ACPI_NUMA
 	depends on HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG
-	depends on (IA64 || X86 || PPC64)
+	depends on (IA64 || X86 || PPC64 || SUPERH)
 
 comment "Memory hotplug is currently incompatible with Software Suspend"
 	depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
@@ -163,8 +163,16 @@
 	default "0" if !ZONE_DMA
 	default "1"
 
+config BOUNCE
+	def_bool y
+	depends on BLOCK && MMU && (ZONE_DMA || HIGHMEM)
+
 config NR_QUICK
 	int
 	depends on QUICKLIST
 	default "2" if (SUPERH && !SUPERH64)
 	default "1"
+
+config VIRT_TO_BUS
+	def_bool y
+	depends on !ARCH_NO_VIRT_TO_BUS
diff --git a/mm/Makefile b/mm/Makefile
index a9148ea..245e33a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -13,9 +13,7 @@
 			   prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
 			   $(mmu-y)
 
-ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy)
-obj-y			+= bounce.o
-endif
+obj-$(CONFIG_BOUNCE)	+= bounce.o
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
index b2486cf..00b0262 100644
--- a/mm/allocpercpu.c
+++ b/mm/allocpercpu.c
@@ -53,12 +53,9 @@
 	int node = cpu_to_node(cpu);
 
 	BUG_ON(pdata->ptrs[cpu]);
-	if (node_online(node)) {
-		/* FIXME: kzalloc_node(size, gfp, node) */
-		pdata->ptrs[cpu] = kmalloc_node(size, gfp, node);
-		if (pdata->ptrs[cpu])
-			memset(pdata->ptrs[cpu], 0, size);
-	} else
+	if (node_online(node))
+		pdata->ptrs[cpu] = kmalloc_node(size, gfp|__GFP_ZERO, node);
+	else
 		pdata->ptrs[cpu] = kzalloc(size, gfp);
 	return pdata->ptrs[cpu];
 }
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e5de378..f50a281 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -55,22 +55,6 @@
 }
 EXPORT_SYMBOL(congestion_wait);
 
-long congestion_wait_interruptible(int rw, long timeout)
-{
-	long ret;
-	DEFINE_WAIT(wait);
-	wait_queue_head_t *wqh = &congestion_wqh[rw];
-
-	prepare_to_wait(wqh, &wait, TASK_INTERRUPTIBLE);
-	if (signal_pending(current))
-		ret = -ERESTARTSYS;
-	else
-		ret = io_schedule_timeout(timeout);
-	finish_wait(wqh, &wait);
-	return ret;
-}
-EXPORT_SYMBOL(congestion_wait_interruptible);
-
 /**
  * congestion_end - wake up sleepers on a congested backing_dev_info
  * @rw: READ or WRITE
diff --git a/mm/filemap.c b/mm/filemap.c
index c6ebd9f..5d5449f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -120,6 +120,7 @@
 	page->mapping = NULL;
 	mapping->nrpages--;
 	__dec_zone_page_state(page, NR_FILE_PAGES);
+	BUG_ON(page_mapped(page));
 }
 
 void remove_from_page_cache(struct page *page)
@@ -866,13 +867,11 @@
 {
 	struct inode *inode = mapping->host;
 	unsigned long index;
-	unsigned long end_index;
 	unsigned long offset;
 	unsigned long last_index;
 	unsigned long next_index;
 	unsigned long prev_index;
 	unsigned int prev_offset;
-	loff_t isize;
 	struct page *cached_page;
 	int error;
 	struct file_ra_state ra = *_ra;
@@ -885,27 +884,12 @@
 	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
-	isize = i_size_read(inode);
-	if (!isize)
-		goto out;
-
-	end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
 	for (;;) {
 		struct page *page;
+		unsigned long end_index;
+		loff_t isize;
 		unsigned long nr, ret;
 
-		/* nr is the maximum number of bytes to copy from this page */
-		nr = PAGE_CACHE_SIZE;
-		if (index >= end_index) {
-			if (index > end_index)
-				goto out;
-			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
-			if (nr <= offset) {
-				goto out;
-			}
-		}
-		nr = nr - offset;
-
 		cond_resched();
 		if (index == next_index)
 			next_index = page_cache_readahead(mapping, &ra, filp,
@@ -920,6 +904,32 @@
 		if (!PageUptodate(page))
 			goto page_not_up_to_date;
 page_ok:
+		/*
+		 * i_size must be checked after we know the page is Uptodate.
+		 *
+		 * Checking i_size after the check allows us to calculate
+		 * the correct value for "nr", which means the zero-filled
+		 * part of the page is not copied back to userspace (unless
+		 * another truncate extends the file - this is desired though).
+		 */
+
+		isize = i_size_read(inode);
+		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+		if (unlikely(!isize || index > end_index)) {
+			page_cache_release(page);
+			goto out;
+		}
+
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index == end_index) {
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				page_cache_release(page);
+				goto out;
+			}
+		}
+		nr = nr - offset;
 
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
@@ -1006,31 +1016,6 @@
 			unlock_page(page);
 		}
 
-		/*
-		 * i_size must be checked after we have done ->readpage.
-		 *
-		 * Checking i_size after the readpage allows us to calculate
-		 * the correct value for "nr", which means the zero-filled
-		 * part of the page is not copied back to userspace (unless
-		 * another truncate extends the file - this is desired though).
-		 */
-		isize = i_size_read(inode);
-		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
-		if (unlikely(!isize || index > end_index)) {
-			page_cache_release(page);
-			goto out;
-		}
-
-		/* nr is the maximum number of bytes to copy from this page */
-		nr = PAGE_CACHE_SIZE;
-		if (index == end_index) {
-			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
-			if (nr <= offset) {
-				page_cache_release(page);
-				goto out;
-			}
-		}
-		nr = nr - offset;
 		goto page_ok;
 
 readpage_error:
@@ -1218,6 +1203,8 @@
 				retval = retval ?: desc.error;
 				break;
 			}
+			if (desc.count > 0)
+				break;
 		}
 	}
 out:
@@ -1964,7 +1951,6 @@
 	if (unlikely(*pos + *count > MAX_NON_LFS &&
 				!(file->f_flags & O_LARGEFILE))) {
 		if (*pos >= MAX_NON_LFS) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 		if (*count > MAX_NON_LFS - (unsigned long)*pos) {
@@ -1982,7 +1968,6 @@
 	if (likely(!isblk)) {
 		if (unlikely(*pos >= inode->i_sb->s_maxbytes)) {
 			if (*count || *pos > inode->i_sb->s_maxbytes) {
-				send_sig(SIGXFSZ, current, 0);
 				return -EFBIG;
 			}
 			/* zero-length writes at ->s_maxbytes are OK */
diff --git a/mm/highmem.c b/mm/highmem.c
index be8f8d3..7a967bc 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -46,9 +46,14 @@
 	pg_data_t *pgdat;
 	unsigned int pages = 0;
 
-	for_each_online_pgdat(pgdat)
+	for_each_online_pgdat(pgdat) {
 		pages += zone_page_state(&pgdat->node_zones[ZONE_HIGHMEM],
 			NR_FREE_PAGES);
+		if (zone_movable_is_highmem())
+			pages += zone_page_state(
+					&pgdat->node_zones[ZONE_MOVABLE],
+					NR_FREE_PAGES);
+	}
 
 	return pages;
 }
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index a45d1f0..6912bbf 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -27,6 +27,9 @@
 static struct list_head hugepage_freelists[MAX_NUMNODES];
 static unsigned int nr_huge_pages_node[MAX_NUMNODES];
 static unsigned int free_huge_pages_node[MAX_NUMNODES];
+static gfp_t htlb_alloc_mask = GFP_HIGHUSER;
+unsigned long hugepages_treat_as_movable;
+
 /*
  * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
  */
@@ -66,14 +69,15 @@
 static struct page *dequeue_huge_page(struct vm_area_struct *vma,
 				unsigned long address)
 {
-	int nid = numa_node_id();
+	int nid;
 	struct page *page = NULL;
-	struct zonelist *zonelist = huge_zonelist(vma, address);
+	struct zonelist *zonelist = huge_zonelist(vma, address,
+						htlb_alloc_mask);
 	struct zone **z;
 
 	for (z = zonelist->zones; *z; z++) {
 		nid = zone_to_nid(*z);
-		if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
+		if (cpuset_zone_allowed_softwall(*z, htlb_alloc_mask) &&
 		    !list_empty(&hugepage_freelists[nid]))
 			break;
 	}
@@ -101,13 +105,20 @@
 
 static int alloc_fresh_huge_page(void)
 {
-	static int nid = 0;
+	static int prev_nid;
 	struct page *page;
-	page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN,
-					HUGETLB_PAGE_ORDER);
-	nid = next_node(nid, node_online_map);
+	static DEFINE_SPINLOCK(nid_lock);
+	int nid;
+
+	spin_lock(&nid_lock);
+	nid = next_node(prev_nid, node_online_map);
 	if (nid == MAX_NUMNODES)
 		nid = first_node(node_online_map);
+	prev_nid = nid;
+	spin_unlock(&nid_lock);
+
+	page = alloc_pages_node(nid, htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
+					HUGETLB_PAGE_ORDER);
 	if (page) {
 		set_compound_page_dtor(page, free_huge_page);
 		spin_lock(&hugetlb_lock);
@@ -256,6 +267,19 @@
 	max_huge_pages = set_max_huge_pages(max_huge_pages);
 	return 0;
 }
+
+int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
+			struct file *file, void __user *buffer,
+			size_t *length, loff_t *ppos)
+{
+	proc_dointvec(table, write, file, buffer, length, ppos);
+	if (hugepages_treat_as_movable)
+		htlb_alloc_mask = GFP_HIGHUSER_MOVABLE;
+	else
+		htlb_alloc_mask = GFP_HIGHUSER;
+	return 0;
+}
+
 #endif /* CONFIG_SYSCTL */
 
 int hugetlb_report_meminfo(char *buf)
@@ -474,7 +498,7 @@
 	return VM_FAULT_MINOR;
 }
 
-int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
+static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long address, pte_t *ptep, int write_access)
 {
 	int ret = VM_FAULT_SIGBUS;
diff --git a/mm/madvise.c b/mm/madvise.c
index 60542d0..93ee375 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -287,9 +287,11 @@
 	struct vm_area_struct * vma, *prev;
 	int unmapped_error = 0;
 	int error = -EINVAL;
+	int write;
 	size_t len;
 
-	if (madvise_need_mmap_write(behavior))
+	write = madvise_need_mmap_write(behavior);
+	if (write)
 		down_write(&current->mm->mmap_sem);
 	else
 		down_read(&current->mm->mmap_sem);
@@ -354,7 +356,7 @@
 			vma = find_vma(current->mm, start);
 	}
 out:
-	if (madvise_need_mmap_write(behavior))
+	if (write)
 		up_write(&current->mm->mmap_sem);
 	else
 		up_read(&current->mm->mmap_sem);
diff --git a/mm/memory.c b/mm/memory.c
index f64cbf9..9c6ff7f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -78,11 +78,9 @@
  * and ZONE_HIGHMEM.
  */
 void * high_memory;
-unsigned long vmalloc_earlyreserve;
 
 EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(high_memory);
-EXPORT_SYMBOL(vmalloc_earlyreserve);
 
 int randomize_va_space __read_mostly = 1;
 
@@ -1055,6 +1053,14 @@
 		do {
 			struct page *page;
 
+			/*
+			 * If tsk is ooming, cut off its access to large memory
+			 * allocations. It has a pending SIGKILL, but it can't
+			 * be processed until returning to user space.
+			 */
+			if (unlikely(test_tsk_thread_flag(tsk, TIF_MEMDIE)))
+				return -ENOMEM;
+
 			if (write)
 				foll_flags |= FOLL_WRITE;
 
@@ -1709,11 +1715,11 @@
 	if (unlikely(anon_vma_prepare(vma)))
 		goto oom;
 	if (old_page == ZERO_PAGE(address)) {
-		new_page = alloc_zeroed_user_highpage(vma, address);
+		new_page = alloc_zeroed_user_highpage_movable(vma, address);
 		if (!new_page)
 			goto oom;
 	} else {
-		new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+		new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
 		if (!new_page)
 			goto oom;
 		cow_user_page(new_page, old_page, address, vma);
@@ -2231,7 +2237,7 @@
 
 		if (unlikely(anon_vma_prepare(vma)))
 			goto oom;
-		page = alloc_zeroed_user_highpage(vma, address);
+		page = alloc_zeroed_user_highpage_movable(vma, address);
 		if (!page)
 			goto oom;
 
@@ -2334,7 +2340,8 @@
 
 			if (unlikely(anon_vma_prepare(vma)))
 				goto oom;
-			page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+			page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+						vma, address);
 			if (!page)
 				goto oom;
 			copy_user_highpage(page, new_page, address, vma);
@@ -2673,7 +2680,7 @@
 	write = (vma->vm_flags & VM_WRITE) != 0;
 	BUG_ON(addr >= end);
 	BUG_ON(end > vma->vm_end);
-	len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
+	len = DIV_ROUND_UP(end, PAGE_SIZE) - addr/PAGE_SIZE;
 	ret = get_user_pages(current, current->mm, addr,
 			len, write, 0, NULL, NULL);
 	if (ret < 0)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d76e8eb..9f4e9b9 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -101,8 +101,6 @@
 static struct kmem_cache *policy_cache;
 static struct kmem_cache *sn_cache;
 
-#define PDprintk(fmt...)
-
 /* Highest zone. An specific allocation for a zone below that is not
    policied. */
 enum zone_type policy_zone = 0;
@@ -175,7 +173,9 @@
 {
 	struct mempolicy *policy;
 
-	PDprintk("setting mode %d nodes[0] %lx\n", mode, nodes_addr(*nodes)[0]);
+	pr_debug("setting mode %d nodes[0] %lx\n",
+		 mode, nodes ? nodes_addr(*nodes)[0] : -1);
+
 	if (mode == MPOL_DEFAULT)
 		return NULL;
 	policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
@@ -379,7 +379,7 @@
 	int err = 0;
 	struct mempolicy *old = vma->vm_policy;
 
-	PDprintk("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
+	pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
 		 vma->vm_start, vma->vm_end, vma->vm_pgoff,
 		 vma->vm_ops, vma->vm_file,
 		 vma->vm_ops ? vma->vm_ops->set_policy : NULL);
@@ -594,7 +594,7 @@
 
 static struct page *new_node_page(struct page *page, unsigned long node, int **x)
 {
-	return alloc_pages_node(node, GFP_HIGHUSER, 0);
+	return alloc_pages_node(node, GFP_HIGHUSER_MOVABLE, 0);
 }
 
 /*
@@ -710,7 +710,8 @@
 {
 	struct vm_area_struct *vma = (struct vm_area_struct *)private;
 
-	return alloc_page_vma(GFP_HIGHUSER, vma, page_address_in_vma(page, vma));
+	return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
+					page_address_in_vma(page, vma));
 }
 #else
 
@@ -776,8 +777,8 @@
 	if (!new)
 		flags |= MPOL_MF_DISCONTIG_OK;
 
-	PDprintk("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
-			mode,nodes_addr(nodes)[0]);
+	pr_debug("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
+		 mode, nmask ? nodes_addr(*nmask)[0] : -1);
 
 	down_write(&mm->mmap_sem);
 	vma = check_range(mm, start, end, nmask,
@@ -1202,7 +1203,8 @@
 
 #ifdef CONFIG_HUGETLBFS
 /* Return a zonelist suitable for a huge page allocation. */
-struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
+struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
+							gfp_t gfp_flags)
 {
 	struct mempolicy *pol = get_vma_policy(current, vma, addr);
 
@@ -1210,7 +1212,7 @@
 		unsigned nid;
 
 		nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
-		return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+		return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags);
 	}
 	return zonelist_policy(GFP_HIGHUSER, pol);
 }
@@ -1434,7 +1436,7 @@
 	}
 	rb_link_node(&new->nd, parent, p);
 	rb_insert_color(&new->nd, &sp->root);
-	PDprintk("inserting %lx-%lx: %d\n", new->start, new->end,
+	pr_debug("inserting %lx-%lx: %d\n", new->start, new->end,
 		 new->policy ? new->policy->policy : 0);
 }
 
@@ -1459,7 +1461,7 @@
 
 static void sp_delete(struct shared_policy *sp, struct sp_node *n)
 {
-	PDprintk("deleting %lx-l%x\n", n->start, n->end);
+	pr_debug("deleting %lx-l%lx\n", n->start, n->end);
 	rb_erase(&n->nd, &sp->root);
 	mpol_free(n->policy);
 	kmem_cache_free(sn_cache, n);
@@ -1558,10 +1560,10 @@
 	struct sp_node *new = NULL;
 	unsigned long sz = vma_pages(vma);
 
-	PDprintk("set_shared_policy %lx sz %lu %d %lx\n",
+	pr_debug("set_shared_policy %lx sz %lu %d %lx\n",
 		 vma->vm_pgoff,
 		 sz, npol? npol->policy : -1,
-		npol ? nodes_addr(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);
@@ -1597,6 +1599,10 @@
 /* assumes fs == KERNEL_DS */
 void __init numa_policy_init(void)
 {
+	nodemask_t interleave_nodes;
+	unsigned long largest = 0;
+	int nid, prefer = 0;
+
 	policy_cache = kmem_cache_create("numa_policy",
 					 sizeof(struct mempolicy),
 					 0, SLAB_PANIC, NULL, NULL);
@@ -1605,10 +1611,31 @@
 				     sizeof(struct sp_node),
 				     0, SLAB_PANIC, NULL, NULL);
 
-	/* Set interleaving policy for system init. This way not all
-	   the data structures allocated at system boot end up in node zero. */
+	/*
+	 * Set interleaving policy for system init. Interleaving is only
+	 * enabled across suitably sized nodes (default is >= 16MB), or
+	 * fall back to the largest node if they're all smaller.
+	 */
+	nodes_clear(interleave_nodes);
+	for_each_online_node(nid) {
+		unsigned long total_pages = node_present_pages(nid);
 
-	if (do_set_mempolicy(MPOL_INTERLEAVE, &node_online_map))
+		/* Preserve the largest node */
+		if (largest < total_pages) {
+			largest = total_pages;
+			prefer = nid;
+		}
+
+		/* Interleave this node? */
+		if ((total_pages << PAGE_SHIFT) >= (16 << 20))
+			node_set(nid, interleave_nodes);
+	}
+
+	/* All too small, use the largest */
+	if (unlikely(nodes_empty(interleave_nodes)))
+		node_set(prefer, interleave_nodes);
+
+	if (do_set_mempolicy(MPOL_INTERLEAVE, &interleave_nodes))
 		printk("numa_policy_init: interleaving failed\n");
 }
 
diff --git a/mm/mempool.c b/mm/mempool.c
index cc1ca86..02d5ec3 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -62,10 +62,9 @@
 			mempool_free_t *free_fn, void *pool_data, int node_id)
 {
 	mempool_t *pool;
-	pool = kmalloc_node(sizeof(*pool), GFP_KERNEL, node_id);
+	pool = kmalloc_node(sizeof(*pool), GFP_KERNEL | __GFP_ZERO, node_id);
 	if (!pool)
 		return NULL;
-	memset(pool, 0, sizeof(*pool));
 	pool->elements = kmalloc_node(min_nr * sizeof(void *),
 					GFP_KERNEL, node_id);
 	if (!pool->elements) {
@@ -263,6 +262,9 @@
 {
 	unsigned long flags;
 
+	if (unlikely(element == NULL))
+		return;
+
 	smp_mb();
 	if (pool->curr_nr < pool->min_nr) {
 		spin_lock_irqsave(&pool->lock, flags);
diff --git a/mm/migrate.c b/mm/migrate.c
index a91ca00..34d8ada 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -761,7 +761,8 @@
 
 	*result = &pm->status;
 
-	return alloc_pages_node(pm->node, GFP_HIGHUSER | GFP_THISNODE, 0);
+	return alloc_pages_node(pm->node,
+				GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0);
 }
 
 /*
diff --git a/mm/mlock.c b/mm/mlock.c
index 4d3fea2..7b26560 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -244,9 +244,12 @@
 
 	locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	if (lock_limit == RLIM_INFINITY)
+		allowed = 1;
 	lock_limit >>= PAGE_SHIFT;
 	spin_lock(&shmlock_user_lock);
-	if (locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
+	if (!allowed &&
+	    locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
 		goto out;
 	get_uid(user);
 	user->locked_shm += locked;
diff --git a/mm/mmap.c b/mm/mmap.c
index 9f70c8e..144b4a2 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -894,14 +894,11 @@
 			unsigned long flags, unsigned long pgoff)
 {
 	struct mm_struct * mm = current->mm;
-	struct vm_area_struct * vma, * prev;
 	struct inode *inode;
 	unsigned int vm_flags;
-	int correct_wcount = 0;
 	int error;
-	struct rb_node ** rb_link, * rb_parent;
 	int accountable = 1;
-	unsigned long charged = 0, reqprot = prot;
+	unsigned long reqprot = prot;
 
 	/*
 	 * Does the application expect PROT_READ to imply PROT_EXEC?
@@ -1027,6 +1024,24 @@
 	if (error)
 		return error;
 
+	return mmap_region(file, addr, len, flags, vm_flags, pgoff,
+			   accountable);
+}
+EXPORT_SYMBOL(do_mmap_pgoff);
+
+unsigned long mmap_region(struct file *file, unsigned long addr,
+			  unsigned long len, unsigned long flags,
+			  unsigned int vm_flags, unsigned long pgoff,
+			  int accountable)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma, *prev;
+	int correct_wcount = 0;
+	int error;
+	struct rb_node **rb_link, *rb_parent;
+	unsigned long charged = 0;
+	struct inode *inode =  file ? file->f_path.dentry->d_inode : NULL;
+
 	/* Clear old maps */
 	error = -ENOMEM;
 munmap_back:
@@ -1175,8 +1190,6 @@
 	return error;
 }
 
-EXPORT_SYMBOL(do_mmap_pgoff);
-
 /* Get an address range which is currently unmapped.
  * For shmat() with addr=0.
  *
diff --git a/mm/nommu.c b/mm/nommu.c
index 989e2e9..8bbbf14 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -367,6 +367,11 @@
 	return find_vma(mm, addr);
 }
 
+int expand_stack(struct vm_area_struct *vma, unsigned long address)
+{
+	return -ENOMEM;
+}
+
 /*
  * look up the first VMA exactly that exactly matches addr
  * - should be called with mm->mmap_sem at least held readlocked
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index eec1481..886ea0d 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -476,15 +476,13 @@
  * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs
  */
 int dirty_writeback_centisecs_handler(ctl_table *table, int write,
-		struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+	struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
 {
 	proc_dointvec_userhz_jiffies(table, write, file, buffer, length, ppos);
-	if (dirty_writeback_interval) {
-		mod_timer(&wb_timer,
-			jiffies + dirty_writeback_interval);
-		} else {
+	if (dirty_writeback_interval)
+		mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
+	else
 		del_timer(&wb_timer);
-	}
 	return 0;
 }
 
@@ -826,6 +824,7 @@
 		mapping2 = page_mapping(page);
 		if (mapping2) { /* Race with truncate? */
 			BUG_ON(mapping2 != mapping);
+			WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
 			if (mapping_cap_account_dirty(mapping)) {
 				__inc_zone_page_state(page, NR_FILE_DIRTY);
 				task_io_account_write(PAGE_CACHE_SIZE);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 05ace44..e2a10b9 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -80,8 +80,9 @@
 	 256,
 #endif
 #ifdef CONFIG_HIGHMEM
-	 32
+	 32,
 #endif
+	 32,
 };
 
 EXPORT_SYMBOL(totalram_pages);
@@ -95,8 +96,9 @@
 #endif
 	 "Normal",
 #ifdef CONFIG_HIGHMEM
-	 "HighMem"
+	 "HighMem",
 #endif
+	 "Movable",
 };
 
 int min_free_kbytes = 1024;
@@ -126,14 +128,21 @@
     #endif
   #endif
 
-  struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
-  int __meminitdata nr_nodemap_entries;
-  unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
-  unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
+  static struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
+  static int __meminitdata nr_nodemap_entries;
+  static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
+  static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
 #ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
-  unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES];
-  unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES];
+  static unsigned long __meminitdata node_boundary_start_pfn[MAX_NUMNODES];
+  static unsigned long __meminitdata node_boundary_end_pfn[MAX_NUMNODES];
 #endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
+  unsigned long __initdata required_kernelcore;
+  unsigned long __initdata required_movablecore;
+  unsigned long __initdata zone_movable_pfn[MAX_NUMNODES];
+
+  /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
+  int movable_zone;
+  EXPORT_SYMBOL(movable_zone);
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
 #if MAX_NUMNODES > 1
@@ -900,11 +909,13 @@
 
 	u32 ignore_gfp_highmem;
 	u32 ignore_gfp_wait;
+	u32 min_order;
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
 
 	struct dentry *ignore_gfp_highmem_file;
 	struct dentry *ignore_gfp_wait_file;
+	struct dentry *min_order_file;
 
 #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
 
@@ -912,6 +923,7 @@
 	.attr = FAULT_ATTR_INITIALIZER,
 	.ignore_gfp_wait = 1,
 	.ignore_gfp_highmem = 1,
+	.min_order = 1,
 };
 
 static int __init setup_fail_page_alloc(char *str)
@@ -922,6 +934,8 @@
 
 static int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
 {
+	if (order < fail_page_alloc.min_order)
+		return 0;
 	if (gfp_mask & __GFP_NOFAIL)
 		return 0;
 	if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM))
@@ -953,12 +967,17 @@
 	fail_page_alloc.ignore_gfp_highmem_file =
 		debugfs_create_bool("ignore-gfp-highmem", mode, dir,
 				      &fail_page_alloc.ignore_gfp_highmem);
+	fail_page_alloc.min_order_file =
+		debugfs_create_u32("min-order", mode, dir,
+				   &fail_page_alloc.min_order);
 
 	if (!fail_page_alloc.ignore_gfp_wait_file ||
-			!fail_page_alloc.ignore_gfp_highmem_file) {
+            !fail_page_alloc.ignore_gfp_highmem_file ||
+            !fail_page_alloc.min_order_file) {
 		err = -ENOMEM;
 		debugfs_remove(fail_page_alloc.ignore_gfp_wait_file);
 		debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file);
+		debugfs_remove(fail_page_alloc.min_order_file);
 		cleanup_fault_attr_dentries(&fail_page_alloc.attr);
 	}
 
@@ -1314,7 +1333,7 @@
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;
 
-	did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask);
+	did_some_progress = try_to_free_pages(zonelist->zones, order, gfp_mask);
 
 	p->reclaim_state = NULL;
 	p->flags &= ~PF_MEMALLOC;
@@ -1351,7 +1370,8 @@
 	 */
 	do_retry = 0;
 	if (!(gfp_mask & __GFP_NORETRY)) {
-		if ((order <= 3) || (gfp_mask & __GFP_REPEAT))
+		if ((order <= PAGE_ALLOC_COSTLY_ORDER) ||
+						(gfp_mask & __GFP_REPEAT))
 			do_retry = 1;
 		if (gfp_mask & __GFP_NOFAIL)
 			do_retry = 1;
@@ -1464,13 +1484,14 @@
 {
 	return nr_free_zone_pages(gfp_zone(GFP_USER));
 }
+EXPORT_SYMBOL_GPL(nr_free_buffer_pages);
 
 /*
  * Amount of free RAM allocatable within all zones
  */
 unsigned int nr_free_pagecache_pages(void)
 {
-	return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER));
+	return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER_MOVABLE));
 }
 
 static inline void show_node(struct zone *zone)
@@ -1621,8 +1642,8 @@
  *
  * Add all populated zones of a node to the zonelist.
  */
-static int __meminit build_zonelists_node(pg_data_t *pgdat,
-			struct zonelist *zonelist, int nr_zones, enum zone_type zone_type)
+static int build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist,
+				int nr_zones, enum zone_type zone_type)
 {
 	struct zone *zone;
 
@@ -1641,9 +1662,102 @@
 	return nr_zones;
 }
 
+
+/*
+ *  zonelist_order:
+ *  0 = automatic detection of better ordering.
+ *  1 = order by ([node] distance, -zonetype)
+ *  2 = order by (-zonetype, [node] distance)
+ *
+ *  If not NUMA, ZONELIST_ORDER_ZONE and ZONELIST_ORDER_NODE will create
+ *  the same zonelist. So only NUMA can configure this param.
+ */
+#define ZONELIST_ORDER_DEFAULT  0
+#define ZONELIST_ORDER_NODE     1
+#define ZONELIST_ORDER_ZONE     2
+
+/* zonelist order in the kernel.
+ * set_zonelist_order() will set this to NODE or ZONE.
+ */
+static int current_zonelist_order = ZONELIST_ORDER_DEFAULT;
+static char zonelist_order_name[3][8] = {"Default", "Node", "Zone"};
+
+
 #ifdef CONFIG_NUMA
+/* The value user specified ....changed by config */
+static int user_zonelist_order = ZONELIST_ORDER_DEFAULT;
+/* string for sysctl */
+#define NUMA_ZONELIST_ORDER_LEN	16
+char numa_zonelist_order[16] = "default";
+
+/*
+ * interface for configure zonelist ordering.
+ * command line option "numa_zonelist_order"
+ *	= "[dD]efault	- default, automatic configuration.
+ *	= "[nN]ode 	- order by node locality, then by zone within node
+ *	= "[zZ]one      - order by zone, then by locality within zone
+ */
+
+static int __parse_numa_zonelist_order(char *s)
+{
+	if (*s == 'd' || *s == 'D') {
+		user_zonelist_order = ZONELIST_ORDER_DEFAULT;
+	} else if (*s == 'n' || *s == 'N') {
+		user_zonelist_order = ZONELIST_ORDER_NODE;
+	} else if (*s == 'z' || *s == 'Z') {
+		user_zonelist_order = ZONELIST_ORDER_ZONE;
+	} else {
+		printk(KERN_WARNING
+			"Ignoring invalid numa_zonelist_order value:  "
+			"%s\n", s);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static __init int setup_numa_zonelist_order(char *s)
+{
+	if (s)
+		return __parse_numa_zonelist_order(s);
+	return 0;
+}
+early_param("numa_zonelist_order", setup_numa_zonelist_order);
+
+/*
+ * sysctl handler for numa_zonelist_order
+ */
+int numa_zonelist_order_handler(ctl_table *table, int write,
+		struct file *file, void __user *buffer, size_t *length,
+		loff_t *ppos)
+{
+	char saved_string[NUMA_ZONELIST_ORDER_LEN];
+	int ret;
+
+	if (write)
+		strncpy(saved_string, (char*)table->data,
+			NUMA_ZONELIST_ORDER_LEN);
+	ret = proc_dostring(table, write, file, buffer, length, ppos);
+	if (ret)
+		return ret;
+	if (write) {
+		int oldval = user_zonelist_order;
+		if (__parse_numa_zonelist_order((char*)table->data)) {
+			/*
+			 * bogus value.  restore saved string
+			 */
+			strncpy((char*)table->data, saved_string,
+				NUMA_ZONELIST_ORDER_LEN);
+			user_zonelist_order = oldval;
+		} else if (oldval != user_zonelist_order)
+			build_all_zonelists();
+	}
+	return 0;
+}
+
+
 #define MAX_NODE_LOAD (num_online_nodes())
-static int __meminitdata node_load[MAX_NUMNODES];
+static int node_load[MAX_NUMNODES];
+
 /**
  * find_next_best_node - find the next node that should appear in a given node's fallback list
  * @node: node whose fallback list we're appending
@@ -1658,7 +1772,7 @@
  * on them otherwise.
  * It returns -1 if no node is found.
  */
-static int __meminit find_next_best_node(int node, nodemask_t *used_node_mask)
+static int find_next_best_node(int node, nodemask_t *used_node_mask)
 {
 	int n, val;
 	int min_val = INT_MAX;
@@ -1704,13 +1818,129 @@
 	return best_node;
 }
 
-static void __meminit build_zonelists(pg_data_t *pgdat)
+
+/*
+ * Build zonelists ordered by node and zones within node.
+ * This results in maximum locality--normal zone overflows into local
+ * DMA zone, if any--but risks exhausting DMA zone.
+ */
+static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
 {
-	int j, node, local_node;
 	enum zone_type i;
-	int prev_node, load;
+	int j;
 	struct zonelist *zonelist;
+
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		zonelist = pgdat->node_zonelists + i;
+		for (j = 0; zonelist->zones[j] != NULL; j++)
+			;
+ 		j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
+		zonelist->zones[j] = NULL;
+	}
+}
+
+/*
+ * Build zonelists ordered by zone and nodes within zones.
+ * This results in conserving DMA zone[s] until all Normal memory is
+ * exhausted, but results in overflowing to remote node while memory
+ * may still exist in local DMA zone.
+ */
+static int node_order[MAX_NUMNODES];
+
+static void build_zonelists_in_zone_order(pg_data_t *pgdat, int nr_nodes)
+{
+	enum zone_type i;
+	int pos, j, node;
+	int zone_type;		/* needs to be signed */
+	struct zone *z;
+	struct zonelist *zonelist;
+
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		zonelist = pgdat->node_zonelists + i;
+		pos = 0;
+		for (zone_type = i; zone_type >= 0; zone_type--) {
+			for (j = 0; j < nr_nodes; j++) {
+				node = node_order[j];
+				z = &NODE_DATA(node)->node_zones[zone_type];
+				if (populated_zone(z)) {
+					zonelist->zones[pos++] = z;
+					check_highest_zone(zone_type);
+				}
+			}
+		}
+		zonelist->zones[pos] = NULL;
+	}
+}
+
+static int default_zonelist_order(void)
+{
+	int nid, zone_type;
+	unsigned long low_kmem_size,total_size;
+	struct zone *z;
+	int average_size;
+	/*
+         * ZONE_DMA and ZONE_DMA32 can be very small area in the sytem.
+	 * If they are really small and used heavily, the system can fall
+	 * into OOM very easily.
+	 * This function detect ZONE_DMA/DMA32 size and confgigures zone order.
+	 */
+	/* Is there ZONE_NORMAL ? (ex. ppc has only DMA zone..) */
+	low_kmem_size = 0;
+	total_size = 0;
+	for_each_online_node(nid) {
+		for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) {
+			z = &NODE_DATA(nid)->node_zones[zone_type];
+			if (populated_zone(z)) {
+				if (zone_type < ZONE_NORMAL)
+					low_kmem_size += z->present_pages;
+				total_size += z->present_pages;
+			}
+		}
+	}
+	if (!low_kmem_size ||  /* there are no DMA area. */
+	    low_kmem_size > total_size/2) /* DMA/DMA32 is big. */
+		return ZONELIST_ORDER_NODE;
+	/*
+	 * look into each node's config.
+  	 * If there is a node whose DMA/DMA32 memory is very big area on
+ 	 * local memory, NODE_ORDER may be suitable.
+         */
+	average_size = total_size / (num_online_nodes() + 1);
+	for_each_online_node(nid) {
+		low_kmem_size = 0;
+		total_size = 0;
+		for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) {
+			z = &NODE_DATA(nid)->node_zones[zone_type];
+			if (populated_zone(z)) {
+				if (zone_type < ZONE_NORMAL)
+					low_kmem_size += z->present_pages;
+				total_size += z->present_pages;
+			}
+		}
+		if (low_kmem_size &&
+		    total_size > average_size && /* ignore small node */
+		    low_kmem_size > total_size * 70/100)
+			return ZONELIST_ORDER_NODE;
+	}
+	return ZONELIST_ORDER_ZONE;
+}
+
+static void set_zonelist_order(void)
+{
+	if (user_zonelist_order == ZONELIST_ORDER_DEFAULT)
+		current_zonelist_order = default_zonelist_order();
+	else
+		current_zonelist_order = user_zonelist_order;
+}
+
+static void build_zonelists(pg_data_t *pgdat)
+{
+	int j, node, load;
+	enum zone_type i;
 	nodemask_t used_mask;
+	int local_node, prev_node;
+	struct zonelist *zonelist;
+	int order = current_zonelist_order;
 
 	/* initialize zonelists */
 	for (i = 0; i < MAX_NR_ZONES; i++) {
@@ -1723,6 +1953,11 @@
 	load = num_online_nodes();
 	prev_node = local_node;
 	nodes_clear(used_mask);
+
+	memset(node_load, 0, sizeof(node_load));
+	memset(node_order, 0, sizeof(node_order));
+	j = 0;
+
 	while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
 		int distance = node_distance(local_node, node);
 
@@ -1738,23 +1973,25 @@
 		 * So adding penalty to the first node in same
 		 * distance group to make it round-robin.
 		 */
-
 		if (distance != node_distance(local_node, prev_node))
-			node_load[node] += load;
+			node_load[node] = load;
+
 		prev_node = node;
 		load--;
-		for (i = 0; i < MAX_NR_ZONES; i++) {
-			zonelist = pgdat->node_zonelists + i;
-			for (j = 0; zonelist->zones[j] != NULL; j++);
+		if (order == ZONELIST_ORDER_NODE)
+			build_zonelists_in_node_order(pgdat, node);
+		else
+			node_order[j++] = node;	/* remember order */
+	}
 
-	 		j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
-			zonelist->zones[j] = NULL;
-		}
+	if (order == ZONELIST_ORDER_ZONE) {
+		/* calculate node order -- i.e., DMA last! */
+		build_zonelists_in_zone_order(pgdat, j);
 	}
 }
 
 /* Construct the zonelist performance cache - see further mmzone.h */
-static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+static void build_zonelist_cache(pg_data_t *pgdat)
 {
 	int i;
 
@@ -1771,9 +2008,15 @@
 	}
 }
 
+
 #else	/* CONFIG_NUMA */
 
-static void __meminit build_zonelists(pg_data_t *pgdat)
+static void set_zonelist_order(void)
+{
+	current_zonelist_order = ZONELIST_ORDER_ZONE;
+}
+
+static void build_zonelists(pg_data_t *pgdat)
 {
 	int node, local_node;
 	enum zone_type i,j;
@@ -1809,7 +2052,7 @@
 }
 
 /* non-NUMA variant of zonelist performance cache - just NULL zlcache_ptr */
-static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+static void build_zonelist_cache(pg_data_t *pgdat)
 {
 	int i;
 
@@ -1820,7 +2063,7 @@
 #endif	/* CONFIG_NUMA */
 
 /* return values int ....just for stop_machine_run() */
-static int __meminit __build_all_zonelists(void *dummy)
+static int __build_all_zonelists(void *dummy)
 {
 	int nid;
 
@@ -1831,8 +2074,10 @@
 	return 0;
 }
 
-void __meminit build_all_zonelists(void)
+void build_all_zonelists(void)
 {
+	set_zonelist_order();
+
 	if (system_state == SYSTEM_BOOTING) {
 		__build_all_zonelists(NULL);
 		cpuset_init_current_mems_allowed();
@@ -1843,8 +2088,13 @@
 		/* cpuset refresh routine should be here */
 	}
 	vm_total_pages = nr_free_pagecache_pages();
-	printk("Built %i zonelists.  Total pages: %ld\n",
-			num_online_nodes(), vm_total_pages);
+	printk("Built %i zonelists in %s order.  Total pages: %ld\n",
+			num_online_nodes(),
+			zonelist_order_name[current_zonelist_order],
+			vm_total_pages);
+#ifdef CONFIG_NUMA
+	printk("Policy zone: %s\n", zone_names[policy_zone]);
+#endif
 }
 
 /*
@@ -1953,8 +2203,8 @@
 	}
 }
 
-void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
-				unsigned long size)
+static void __meminit zone_init_free_lists(struct pglist_data *pgdat,
+				struct zone *zone, unsigned long size)
 {
 	int order;
 	for (order = 0; order < MAX_ORDER ; order++) {
@@ -2370,7 +2620,7 @@
 }
 
 /* If necessary, push the node boundary out for reserve hotadd */
-static void __init account_node_boundary(unsigned int nid,
+static void __meminit account_node_boundary(unsigned int nid,
 		unsigned long *start_pfn, unsigned long *end_pfn)
 {
 	printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n",
@@ -2390,7 +2640,7 @@
 void __init push_node_boundaries(unsigned int nid,
 		unsigned long start_pfn, unsigned long end_pfn) {}
 
-static void __init account_node_boundary(unsigned int nid,
+static void __meminit account_node_boundary(unsigned int nid,
 		unsigned long *start_pfn, unsigned long *end_pfn) {}
 #endif
 
@@ -2428,10 +2678,67 @@
 }
 
 /*
+ * This finds a zone that can be used for ZONE_MOVABLE pages. The
+ * assumption is made that zones within a node are ordered in monotonic
+ * increasing memory addresses so that the "highest" populated zone is used
+ */
+void __init find_usable_zone_for_movable(void)
+{
+	int zone_index;
+	for (zone_index = MAX_NR_ZONES - 1; zone_index >= 0; zone_index--) {
+		if (zone_index == ZONE_MOVABLE)
+			continue;
+
+		if (arch_zone_highest_possible_pfn[zone_index] >
+				arch_zone_lowest_possible_pfn[zone_index])
+			break;
+	}
+
+	VM_BUG_ON(zone_index == -1);
+	movable_zone = zone_index;
+}
+
+/*
+ * The zone ranges provided by the architecture do not include ZONE_MOVABLE
+ * because it is sized independant of architecture. Unlike the other zones,
+ * the starting point for ZONE_MOVABLE is not fixed. It may be different
+ * in each node depending on the size of each node and how evenly kernelcore
+ * is distributed. This helper function adjusts the zone ranges
+ * provided by the architecture for a given node by using the end of the
+ * highest usable zone for ZONE_MOVABLE. This preserves the assumption that
+ * zones within a node are in order of monotonic increases memory addresses
+ */
+void __meminit adjust_zone_range_for_zone_movable(int nid,
+					unsigned long zone_type,
+					unsigned long node_start_pfn,
+					unsigned long node_end_pfn,
+					unsigned long *zone_start_pfn,
+					unsigned long *zone_end_pfn)
+{
+	/* Only adjust if ZONE_MOVABLE is on this node */
+	if (zone_movable_pfn[nid]) {
+		/* Size ZONE_MOVABLE */
+		if (zone_type == ZONE_MOVABLE) {
+			*zone_start_pfn = zone_movable_pfn[nid];
+			*zone_end_pfn = min(node_end_pfn,
+				arch_zone_highest_possible_pfn[movable_zone]);
+
+		/* Adjust for ZONE_MOVABLE starting within this range */
+		} else if (*zone_start_pfn < zone_movable_pfn[nid] &&
+				*zone_end_pfn > zone_movable_pfn[nid]) {
+			*zone_end_pfn = zone_movable_pfn[nid];
+
+		/* Check if this whole range is within ZONE_MOVABLE */
+		} else if (*zone_start_pfn >= zone_movable_pfn[nid])
+			*zone_start_pfn = *zone_end_pfn;
+	}
+}
+
+/*
  * Return the number of pages a zone spans in a node, including holes
  * present_pages = zone_spanned_pages_in_node() - zone_absent_pages_in_node()
  */
-unsigned long __meminit zone_spanned_pages_in_node(int nid,
+static unsigned long __meminit zone_spanned_pages_in_node(int nid,
 					unsigned long zone_type,
 					unsigned long *ignored)
 {
@@ -2442,6 +2749,9 @@
 	get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
 	zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
 	zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
+	adjust_zone_range_for_zone_movable(nid, zone_type,
+				node_start_pfn, node_end_pfn,
+				&zone_start_pfn, &zone_end_pfn);
 
 	/* Check that this node has pages within the zone's required range */
 	if (zone_end_pfn < node_start_pfn || zone_start_pfn > node_end_pfn)
@@ -2519,7 +2829,7 @@
 }
 
 /* Return the number of page frames in holes in a zone on a node */
-unsigned long __meminit zone_absent_pages_in_node(int nid,
+static unsigned long __meminit zone_absent_pages_in_node(int nid,
 					unsigned long zone_type,
 					unsigned long *ignored)
 {
@@ -2532,18 +2842,21 @@
 	zone_end_pfn = min(arch_zone_highest_possible_pfn[zone_type],
 							node_end_pfn);
 
+	adjust_zone_range_for_zone_movable(nid, zone_type,
+			node_start_pfn, node_end_pfn,
+			&zone_start_pfn, &zone_end_pfn);
 	return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
 }
 
 #else
-static inline unsigned long zone_spanned_pages_in_node(int nid,
+static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
 					unsigned long zone_type,
 					unsigned long *zones_size)
 {
 	return zones_size[zone_type];
 }
 
-static inline unsigned long zone_absent_pages_in_node(int nid,
+static inline unsigned long __meminit zone_absent_pages_in_node(int nid,
 						unsigned long zone_type,
 						unsigned long *zholes_size)
 {
@@ -2909,6 +3222,157 @@
 	return max_pfn;
 }
 
+unsigned long __init early_calculate_totalpages(void)
+{
+	int i;
+	unsigned long totalpages = 0;
+
+	for (i = 0; i < nr_nodemap_entries; i++)
+		totalpages += early_node_map[i].end_pfn -
+						early_node_map[i].start_pfn;
+
+	return totalpages;
+}
+
+/*
+ * Find the PFN the Movable zone begins in each node. Kernel memory
+ * is spread evenly between nodes as long as the nodes have enough
+ * memory. When they don't, some nodes will have more kernelcore than
+ * others
+ */
+void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
+{
+	int i, nid;
+	unsigned long usable_startpfn;
+	unsigned long kernelcore_node, kernelcore_remaining;
+	int usable_nodes = num_online_nodes();
+
+	/*
+	 * If movablecore was specified, calculate what size of
+	 * kernelcore that corresponds so that memory usable for
+	 * any allocation type is evenly spread. If both kernelcore
+	 * and movablecore are specified, then the value of kernelcore
+	 * will be used for required_kernelcore if it's greater than
+	 * what movablecore would have allowed.
+	 */
+	if (required_movablecore) {
+		unsigned long totalpages = early_calculate_totalpages();
+		unsigned long corepages;
+
+		/*
+		 * Round-up so that ZONE_MOVABLE is at least as large as what
+		 * was requested by the user
+		 */
+		required_movablecore =
+			roundup(required_movablecore, MAX_ORDER_NR_PAGES);
+		corepages = totalpages - required_movablecore;
+
+		required_kernelcore = max(required_kernelcore, corepages);
+	}
+
+	/* If kernelcore was not specified, there is no ZONE_MOVABLE */
+	if (!required_kernelcore)
+		return;
+
+	/* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */
+	find_usable_zone_for_movable();
+	usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone];
+
+restart:
+	/* Spread kernelcore memory as evenly as possible throughout nodes */
+	kernelcore_node = required_kernelcore / usable_nodes;
+	for_each_online_node(nid) {
+		/*
+		 * Recalculate kernelcore_node if the division per node
+		 * now exceeds what is necessary to satisfy the requested
+		 * amount of memory for the kernel
+		 */
+		if (required_kernelcore < kernelcore_node)
+			kernelcore_node = required_kernelcore / usable_nodes;
+
+		/*
+		 * As the map is walked, we track how much memory is usable
+		 * by the kernel using kernelcore_remaining. When it is
+		 * 0, the rest of the node is usable by ZONE_MOVABLE
+		 */
+		kernelcore_remaining = kernelcore_node;
+
+		/* Go through each range of PFNs within this node */
+		for_each_active_range_index_in_nid(i, nid) {
+			unsigned long start_pfn, end_pfn;
+			unsigned long size_pages;
+
+			start_pfn = max(early_node_map[i].start_pfn,
+						zone_movable_pfn[nid]);
+			end_pfn = early_node_map[i].end_pfn;
+			if (start_pfn >= end_pfn)
+				continue;
+
+			/* Account for what is only usable for kernelcore */
+			if (start_pfn < usable_startpfn) {
+				unsigned long kernel_pages;
+				kernel_pages = min(end_pfn, usable_startpfn)
+								- start_pfn;
+
+				kernelcore_remaining -= min(kernel_pages,
+							kernelcore_remaining);
+				required_kernelcore -= min(kernel_pages,
+							required_kernelcore);
+
+				/* Continue if range is now fully accounted */
+				if (end_pfn <= usable_startpfn) {
+
+					/*
+					 * Push zone_movable_pfn to the end so
+					 * that if we have to rebalance
+					 * kernelcore across nodes, we will
+					 * not double account here
+					 */
+					zone_movable_pfn[nid] = end_pfn;
+					continue;
+				}
+				start_pfn = usable_startpfn;
+			}
+
+			/*
+			 * The usable PFN range for ZONE_MOVABLE is from
+			 * start_pfn->end_pfn. Calculate size_pages as the
+			 * number of pages used as kernelcore
+			 */
+			size_pages = end_pfn - start_pfn;
+			if (size_pages > kernelcore_remaining)
+				size_pages = kernelcore_remaining;
+			zone_movable_pfn[nid] = start_pfn + size_pages;
+
+			/*
+			 * Some kernelcore has been met, update counts and
+			 * break if the kernelcore for this node has been
+			 * satisified
+			 */
+			required_kernelcore -= min(required_kernelcore,
+								size_pages);
+			kernelcore_remaining -= size_pages;
+			if (!kernelcore_remaining)
+				break;
+		}
+	}
+
+	/*
+	 * If there is still required_kernelcore, we do another pass with one
+	 * less node in the count. This will push zone_movable_pfn[nid] further
+	 * along on the nodes that still have memory until kernelcore is
+	 * satisified
+	 */
+	usable_nodes--;
+	if (usable_nodes && required_kernelcore > usable_nodes)
+		goto restart;
+
+	/* Align start of ZONE_MOVABLE on all nids to MAX_ORDER_NR_PAGES */
+	for (nid = 0; nid < MAX_NUMNODES; nid++)
+		zone_movable_pfn[nid] =
+			roundup(zone_movable_pfn[nid], MAX_ORDER_NR_PAGES);
+}
+
 /**
  * free_area_init_nodes - Initialise all pg_data_t and zone data
  * @max_zone_pfn: an array of max PFNs for each zone
@@ -2938,19 +3402,37 @@
 	arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
 	arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
 	for (i = 1; i < MAX_NR_ZONES; i++) {
+		if (i == ZONE_MOVABLE)
+			continue;
 		arch_zone_lowest_possible_pfn[i] =
 			arch_zone_highest_possible_pfn[i-1];
 		arch_zone_highest_possible_pfn[i] =
 			max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
 	}
+	arch_zone_lowest_possible_pfn[ZONE_MOVABLE] = 0;
+	arch_zone_highest_possible_pfn[ZONE_MOVABLE] = 0;
+
+	/* Find the PFNs that ZONE_MOVABLE begins at in each node */
+	memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn));
+	find_zone_movable_pfns_for_nodes(zone_movable_pfn);
 
 	/* Print out the zone ranges */
 	printk("Zone PFN ranges:\n");
-	for (i = 0; i < MAX_NR_ZONES; i++)
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		if (i == ZONE_MOVABLE)
+			continue;
 		printk("  %-8s %8lu -> %8lu\n",
 				zone_names[i],
 				arch_zone_lowest_possible_pfn[i],
 				arch_zone_highest_possible_pfn[i]);
+	}
+
+	/* Print out the PFNs ZONE_MOVABLE begins at in each node */
+	printk("Movable zone start PFN for each node\n");
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		if (zone_movable_pfn[i])
+			printk("  Node %d: %lu\n", i, zone_movable_pfn[i]);
+	}
 
 	/* Print out the early_node_map[] */
 	printk("early_node_map[%d] active PFN ranges\n", nr_nodemap_entries);
@@ -2967,6 +3449,43 @@
 				find_min_pfn_for_node(nid), NULL);
 	}
 }
+
+static int __init cmdline_parse_core(char *p, unsigned long *core)
+{
+	unsigned long long coremem;
+	if (!p)
+		return -EINVAL;
+
+	coremem = memparse(p, &p);
+	*core = coremem >> PAGE_SHIFT;
+
+	/* Paranoid check that UL is enough for the coremem value */
+	WARN_ON((coremem >> PAGE_SHIFT) > ULONG_MAX);
+
+	return 0;
+}
+
+/*
+ * kernelcore=size sets the amount of memory for use for allocations that
+ * cannot be reclaimed or migrated.
+ */
+static int __init cmdline_parse_kernelcore(char *p)
+{
+	return cmdline_parse_core(p, &required_kernelcore);
+}
+
+/*
+ * movablecore=size sets the amount of memory for use for allocations that
+ * can be reclaimed or migrated.
+ */
+static int __init cmdline_parse_movablecore(char *p)
+{
+	return cmdline_parse_core(p, &required_movablecore);
+}
+
+early_param("kernelcore", cmdline_parse_kernelcore);
+early_param("movablecore", cmdline_parse_movablecore);
+
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
 /**
@@ -3355,13 +3874,28 @@
 			for (order = 0; ((1UL << order) << PAGE_SHIFT) < size; order++)
 				;
 			table = (void*) __get_free_pages(GFP_ATOMIC, order);
+			/*
+			 * If bucketsize is not a power-of-two, we may free
+			 * some pages at the end of hash table.
+			 */
+			if (table) {
+				unsigned long alloc_end = (unsigned long)table +
+						(PAGE_SIZE << order);
+				unsigned long used = (unsigned long)table +
+						PAGE_ALIGN(size);
+				split_page(virt_to_page(table), order);
+				while (used < alloc_end) {
+					free_page(used);
+					used += PAGE_SIZE;
+				}
+			}
 		}
 	} while (!table && size > PAGE_SIZE && --log2qty);
 
 	if (!table)
 		panic("Failed to allocate %s hash table\n", tablename);
 
-	printk("%s hash table entries: %d (order: %d, %lu bytes)\n",
+	printk(KERN_INFO "%s hash table entries: %d (order: %d, %lu bytes)\n",
 	       tablename,
 	       (1U << log2qty),
 	       ilog2(size) - PAGE_SHIFT,
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 8ce0900..8f6ee07 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -92,6 +92,7 @@
 static int __pdflush(struct pdflush_work *my_work)
 {
 	current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+	set_freezable();
 	my_work->fn = NULL;
 	my_work->who = current;
 	INIT_LIST_HEAD(&my_work->list);
diff --git a/mm/shmem.c b/mm/shmem.c
index 0493e4d..96fa79f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/xattr.h>
+#include <linux/exportfs.h>
 #include <linux/generic_acl.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
@@ -93,8 +94,11 @@
 	 * The above definition of ENTRIES_PER_PAGE, and the use of
 	 * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
 	 * might be reconsidered if it ever diverges from PAGE_SIZE.
+	 *
+	 * __GFP_MOVABLE is masked out as swap vectors cannot move
 	 */
-	return alloc_pages(gfp_mask, PAGE_CACHE_SHIFT-PAGE_SHIFT);
+	return alloc_pages((gfp_mask & ~__GFP_MOVABLE) | __GFP_ZERO,
+				PAGE_CACHE_SHIFT-PAGE_SHIFT);
 }
 
 static inline void shmem_dir_free(struct page *page)
@@ -372,7 +376,7 @@
 		}
 
 		spin_unlock(&info->lock);
-		page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
+		page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
 		if (page)
 			set_page_private(page, 0);
 		spin_lock(&info->lock);
diff --git a/mm/slab.c b/mm/slab.c
index b344e67..96d30ee 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -775,6 +775,9 @@
 	 */
 	BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
 #endif
+	if (!size)
+		return ZERO_SIZE_PTR;
+
 	while (size > csizep->cs_size)
 		csizep++;
 
@@ -929,7 +932,7 @@
  * the CPUs getting into lockstep and contending for the global cache chain
  * lock.
  */
-static void __devinit start_cpu_timer(int cpu)
+static void __cpuinit start_cpu_timer(int cpu)
 {
 	struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
 
@@ -2351,7 +2354,7 @@
 		 * this should not happen at all.
 		 * But leave a BUG_ON for some lucky dude.
 		 */
-		BUG_ON(!cachep->slabp_cache);
+		BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
 	}
 	cachep->ctor = ctor;
 	cachep->name = name;
@@ -2743,7 +2746,7 @@
 	 * Be lazy and only check for valid flags here,  keeping it out of the
 	 * critical path in kmem_cache_alloc().
 	 */
-	BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
+	BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
 
 	local_flags = (flags & GFP_LEVEL_MASK);
 	/* Take the l3 list lock to change the colour_next on this node */
@@ -3389,6 +3392,9 @@
 	local_irq_restore(save_flags);
 	ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
 
+	if (unlikely((flags & __GFP_ZERO) && ptr))
+		memset(ptr, 0, obj_size(cachep));
+
 	return ptr;
 }
 
@@ -3440,6 +3446,9 @@
 	objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
 	prefetchw(objp);
 
+	if (unlikely((flags & __GFP_ZERO) && objp))
+		memset(objp, 0, obj_size(cachep));
+
 	return objp;
 }
 
@@ -3581,23 +3590,6 @@
 EXPORT_SYMBOL(kmem_cache_alloc);
 
 /**
- * kmem_cache_zalloc - Allocate an object. The memory is set to zero.
- * @cache: The cache to allocate from.
- * @flags: See kmalloc().
- *
- * Allocate an object from this cache and set the allocated memory to zero.
- * The flags are only relevant if the cache has no available objects.
- */
-void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags)
-{
-	void *ret = __cache_alloc(cache, flags, __builtin_return_address(0));
-	if (ret)
-		memset(ret, 0, obj_size(cache));
-	return ret;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
-
-/**
  * kmem_ptr_validate - check if an untrusted pointer might
  *	be a slab entry.
  * @cachep: the cache we're checking against
@@ -3653,8 +3645,8 @@
 	struct kmem_cache *cachep;
 
 	cachep = kmem_find_general_cachep(size, flags);
-	if (unlikely(cachep == NULL))
-		return NULL;
+	if (unlikely(ZERO_OR_NULL_PTR(cachep)))
+		return cachep;
 	return kmem_cache_alloc_node(cachep, flags, node);
 }
 
@@ -3726,52 +3718,6 @@
 #endif
 
 /**
- * krealloc - reallocate memory. The contents will remain unchanged.
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
- */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
-{
-	struct kmem_cache *cache, *new_cache;
-	void *ret;
-
-	if (unlikely(!p))
-		return kmalloc_track_caller(new_size, flags);
-
-	if (unlikely(!new_size)) {
-		kfree(p);
-		return NULL;
-	}
-
-	cache = virt_to_cache(p);
-	new_cache = __find_general_cachep(new_size, flags);
-
-	/*
- 	 * If new size fits in the current cache, bail out.
- 	 */
-	if (likely(cache == new_cache))
-		return (void *)p;
-
-	/*
- 	 * We are on the slow-path here so do not use __cache_alloc
- 	 * because it bloats kernel text.
- 	 */
-	ret = kmalloc_track_caller(new_size, flags);
-	if (ret) {
-		memcpy(ret, p, min(new_size, ksize(p)));
-		kfree(p);
-	}
-	return ret;
-}
-EXPORT_SYMBOL(krealloc);
-
-/**
  * kmem_cache_free - Deallocate an object
  * @cachep: The cache the allocation was from.
  * @objp: The previously allocated object.
@@ -3806,7 +3752,7 @@
 	struct kmem_cache *c;
 	unsigned long flags;
 
-	if (unlikely(!objp))
+	if (unlikely(ZERO_OR_NULL_PTR(objp)))
 		return;
 	local_irq_save(flags);
 	kfree_debugcheck(objp);
@@ -4157,26 +4103,17 @@
 static void *s_start(struct seq_file *m, loff_t *pos)
 {
 	loff_t n = *pos;
-	struct list_head *p;
 
 	mutex_lock(&cache_chain_mutex);
 	if (!n)
 		print_slabinfo_header(m);
-	p = cache_chain.next;
-	while (n--) {
-		p = p->next;
-		if (p == &cache_chain)
-			return NULL;
-	}
-	return list_entry(p, struct kmem_cache, next);
+
+	return seq_list_start(&cache_chain, *pos);
 }
 
 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	struct kmem_cache *cachep = p;
-	++*pos;
-	return cachep->next.next == &cache_chain ?
-		NULL : list_entry(cachep->next.next, struct kmem_cache, next);
+	return seq_list_next(p, &cache_chain, pos);
 }
 
 static void s_stop(struct seq_file *m, void *p)
@@ -4186,7 +4123,7 @@
 
 static int s_show(struct seq_file *m, void *p)
 {
-	struct kmem_cache *cachep = p;
+	struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
 	struct slab *slabp;
 	unsigned long active_objs;
 	unsigned long num_objs;
@@ -4355,17 +4292,8 @@
 
 static void *leaks_start(struct seq_file *m, loff_t *pos)
 {
-	loff_t n = *pos;
-	struct list_head *p;
-
 	mutex_lock(&cache_chain_mutex);
-	p = cache_chain.next;
-	while (n--) {
-		p = p->next;
-		if (p == &cache_chain)
-			return NULL;
-	}
-	return list_entry(p, struct kmem_cache, next);
+	return seq_list_start(&cache_chain, *pos);
 }
 
 static inline int add_caller(unsigned long *n, unsigned long v)
@@ -4416,7 +4344,7 @@
 {
 #ifdef CONFIG_KALLSYMS
 	unsigned long offset, size;
-	char modname[MODULE_NAME_LEN + 1], name[KSYM_NAME_LEN + 1];
+	char modname[MODULE_NAME_LEN], name[KSYM_NAME_LEN];
 
 	if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) {
 		seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
@@ -4430,7 +4358,7 @@
 
 static int leaks_show(struct seq_file *m, void *p)
 {
-	struct kmem_cache *cachep = p;
+	struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
 	struct slab *slabp;
 	struct kmem_list3 *l3;
 	const char *name;
@@ -4511,7 +4439,7 @@
  */
 size_t ksize(const void *objp)
 {
-	if (unlikely(objp == NULL))
+	if (unlikely(ZERO_OR_NULL_PTR(objp)))
 		return 0;
 
 	return obj_size(virt_to_cache(objp));
diff --git a/mm/slob.c b/mm/slob.c
index 71976c5..c89ef11 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -3,57 +3,159 @@
  *
  * Matt Mackall <mpm@selenic.com> 12/30/03
  *
+ * NUMA support by Paul Mundt, 2007.
+ *
  * How SLOB works:
  *
  * The core of SLOB is a traditional K&R style heap allocator, with
  * support for returning aligned objects. The granularity of this
- * allocator is 8 bytes on x86, though it's perhaps possible to reduce
- * this to 4 if it's deemed worth the effort. The slob heap is a
- * singly-linked list of pages from __get_free_page, grown on demand
- * and allocation from the heap is currently first-fit.
+ * allocator is as little as 2 bytes, however typically most architectures
+ * will require 4 bytes on 32-bit and 8 bytes on 64-bit.
+ *
+ * The slob heap is a linked list of pages from alloc_pages(), and
+ * within each page, there is a singly-linked list of free blocks (slob_t).
+ * The heap is grown on demand and allocation from the heap is currently
+ * first-fit.
  *
  * Above this is an implementation of kmalloc/kfree. Blocks returned
- * from kmalloc are 8-byte aligned and prepended with a 8-byte header.
+ * from kmalloc are prepended with a 4-byte header with the kmalloc size.
  * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
- * __get_free_pages directly so that it can return page-aligned blocks
- * and keeps a linked list of such pages and their orders. These
- * objects are detected in kfree() by their page alignment.
+ * alloc_pages() directly, allocating compound pages so the page order
+ * does not have to be separately tracked, and also stores the exact
+ * allocation size in page->private so that it can be used to accurately
+ * provide ksize(). These objects are detected in kfree() because slob_page()
+ * is false for them.
  *
  * SLAB is emulated on top of SLOB by simply calling constructors and
- * destructors for every SLAB allocation. Objects are returned with
- * the 8-byte alignment unless the SLAB_HWCACHE_ALIGN flag is
- * set, in which case the low-level allocator will fragment blocks to
- * create the proper alignment. Again, objects of page-size or greater
- * are allocated by calling __get_free_pages. As SLAB objects know
- * their size, no separate size bookkeeping is necessary and there is
- * essentially no allocation space overhead.
+ * destructors for every SLAB allocation. Objects are returned with the
+ * 4-byte alignment unless the SLAB_HWCACHE_ALIGN flag is set, in which
+ * case the low-level allocator will fragment blocks to create the proper
+ * alignment. Again, objects of page-size or greater are allocated by
+ * calling alloc_pages(). As SLAB objects know their size, no separate
+ * size bookkeeping is necessary and there is essentially no allocation
+ * space overhead, and compound pages aren't needed for multi-page
+ * allocations.
+ *
+ * NUMA support in SLOB is fairly simplistic, pushing most of the real
+ * logic down to the page allocator, and simply doing the node accounting
+ * on the upper levels. In the event that a node id is explicitly
+ * provided, alloc_pages_node() with the specified node id is used
+ * instead. The common case (or when the node id isn't explicitly provided)
+ * will default to the current node, as per numa_node_id().
+ *
+ * Node aware pages are still inserted in to the global freelist, and
+ * these are scanned for by matching against the node id encoded in the
+ * page flags. As a result, block allocations that can be satisfied from
+ * the freelist will only be done so on pages residing on the same node,
+ * in order to prevent random node placement.
  */
 
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/cache.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/timer.h>
 #include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <asm/atomic.h>
+
+/*
+ * slob_block has a field 'units', which indicates size of block if +ve,
+ * or offset of next block if -ve (in SLOB_UNITs).
+ *
+ * Free blocks of size 1 unit simply contain the offset of the next block.
+ * Those with larger size contain their size in the first SLOB_UNIT of
+ * memory, and the offset of the next free block in the second SLOB_UNIT.
+ */
+#if PAGE_SIZE <= (32767 * 2)
+typedef s16 slobidx_t;
+#else
+typedef s32 slobidx_t;
+#endif
 
 struct slob_block {
-	int units;
-	struct slob_block *next;
+	slobidx_t units;
 };
 typedef struct slob_block slob_t;
 
+/*
+ * We use struct page fields to manage some slob allocation aspects,
+ * however to avoid the horrible mess in include/linux/mm_types.h, we'll
+ * just define our own struct page type variant here.
+ */
+struct slob_page {
+	union {
+		struct {
+			unsigned long flags;	/* mandatory */
+			atomic_t _count;	/* mandatory */
+			slobidx_t units;	/* free units left in page */
+			unsigned long pad[2];
+			slob_t *free;		/* first free slob_t in page */
+			struct list_head list;	/* linked list of free pages */
+		};
+		struct page page;
+	};
+};
+static inline void struct_slob_page_wrong_size(void)
+{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); }
+
+/*
+ * free_slob_page: call before a slob_page is returned to the page allocator.
+ */
+static inline void free_slob_page(struct slob_page *sp)
+{
+	reset_page_mapcount(&sp->page);
+	sp->page.mapping = NULL;
+}
+
+/*
+ * All (partially) free slob pages go on this list.
+ */
+static LIST_HEAD(free_slob_pages);
+
+/*
+ * slob_page: True for all slob pages (false for bigblock pages)
+ */
+static inline int slob_page(struct slob_page *sp)
+{
+	return test_bit(PG_active, &sp->flags);
+}
+
+static inline void set_slob_page(struct slob_page *sp)
+{
+	__set_bit(PG_active, &sp->flags);
+}
+
+static inline void clear_slob_page(struct slob_page *sp)
+{
+	__clear_bit(PG_active, &sp->flags);
+}
+
+/*
+ * slob_page_free: true for pages on free_slob_pages list.
+ */
+static inline int slob_page_free(struct slob_page *sp)
+{
+	return test_bit(PG_private, &sp->flags);
+}
+
+static inline void set_slob_page_free(struct slob_page *sp)
+{
+	list_add(&sp->list, &free_slob_pages);
+	__set_bit(PG_private, &sp->flags);
+}
+
+static inline void clear_slob_page_free(struct slob_page *sp)
+{
+	list_del(&sp->list);
+	__clear_bit(PG_private, &sp->flags);
+}
+
 #define SLOB_UNIT sizeof(slob_t)
 #define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT)
 #define SLOB_ALIGN L1_CACHE_BYTES
 
-struct bigblock {
-	int order;
-	void *pages;
-	struct bigblock *next;
-};
-typedef struct bigblock bigblock_t;
-
 /*
  * struct slob_rcu is inserted at the tail of allocated slob blocks, which
  * were created with a SLAB_DESTROY_BY_RCU slab. slob_rcu is used to free
@@ -64,215 +166,321 @@
 	int size;
 };
 
-static slob_t arena = { .next = &arena, .units = 1 };
-static slob_t *slobfree = &arena;
-static bigblock_t *bigblocks;
+/*
+ * slob_lock protects all slob allocator structures.
+ */
 static DEFINE_SPINLOCK(slob_lock);
-static DEFINE_SPINLOCK(block_lock);
 
-static void slob_free(void *b, int size);
-static void slob_timer_cbk(void);
+/*
+ * Encode the given size and next info into a free slob block s.
+ */
+static void set_slob(slob_t *s, slobidx_t size, slob_t *next)
+{
+	slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+	slobidx_t offset = next - base;
 
+	if (size > 1) {
+		s[0].units = size;
+		s[1].units = offset;
+	} else
+		s[0].units = -offset;
+}
 
-static void *slob_alloc(size_t size, gfp_t gfp, int align)
+/*
+ * Return the size of a slob block.
+ */
+static slobidx_t slob_units(slob_t *s)
+{
+	if (s->units > 0)
+		return s->units;
+	return 1;
+}
+
+/*
+ * Return the next free slob block pointer after this one.
+ */
+static slob_t *slob_next(slob_t *s)
+{
+	slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+	slobidx_t next;
+
+	if (s[0].units < 0)
+		next = -s[0].units;
+	else
+		next = s[1].units;
+	return base+next;
+}
+
+/*
+ * Returns true if s is the last free block in its page.
+ */
+static int slob_last(slob_t *s)
+{
+	return !((unsigned long)slob_next(s) & ~PAGE_MASK);
+}
+
+static void *slob_new_page(gfp_t gfp, int order, int node)
+{
+	void *page;
+
+#ifdef CONFIG_NUMA
+	if (node != -1)
+		page = alloc_pages_node(node, gfp, order);
+	else
+#endif
+		page = alloc_pages(gfp, order);
+
+	if (!page)
+		return NULL;
+
+	return page_address(page);
+}
+
+/*
+ * Allocate a slob block within a given slob_page sp.
+ */
+static void *slob_page_alloc(struct slob_page *sp, size_t size, int align)
 {
 	slob_t *prev, *cur, *aligned = 0;
 	int delta = 0, units = SLOB_UNITS(size);
-	unsigned long flags;
 
-	spin_lock_irqsave(&slob_lock, flags);
-	prev = slobfree;
-	for (cur = prev->next; ; prev = cur, cur = cur->next) {
+	for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) {
+		slobidx_t avail = slob_units(cur);
+
 		if (align) {
 			aligned = (slob_t *)ALIGN((unsigned long)cur, align);
 			delta = aligned - cur;
 		}
-		if (cur->units >= units + delta) { /* room enough? */
+		if (avail >= units + delta) { /* room enough? */
+			slob_t *next;
+
 			if (delta) { /* need to fragment head to align? */
-				aligned->units = cur->units - delta;
-				aligned->next = cur->next;
-				cur->next = aligned;
-				cur->units = delta;
+				next = slob_next(cur);
+				set_slob(aligned, avail - delta, next);
+				set_slob(cur, delta, aligned);
 				prev = cur;
 				cur = aligned;
+				avail = slob_units(cur);
 			}
 
-			if (cur->units == units) /* exact fit? */
-				prev->next = cur->next; /* unlink */
-			else { /* fragment */
-				prev->next = cur + units;
-				prev->next->units = cur->units - units;
-				prev->next->next = cur->next;
-				cur->units = units;
+			next = slob_next(cur);
+			if (avail == units) { /* exact fit? unlink. */
+				if (prev)
+					set_slob(prev, slob_units(prev), next);
+				else
+					sp->free = next;
+			} else { /* fragment */
+				if (prev)
+					set_slob(prev, slob_units(prev), cur + units);
+				else
+					sp->free = cur + units;
+				set_slob(cur + units, avail - units, next);
 			}
 
-			slobfree = prev;
-			spin_unlock_irqrestore(&slob_lock, flags);
+			sp->units -= units;
+			if (!sp->units)
+				clear_slob_page_free(sp);
 			return cur;
 		}
-		if (cur == slobfree) {
-			spin_unlock_irqrestore(&slob_lock, flags);
-
-			if (size == PAGE_SIZE) /* trying to shrink arena? */
-				return 0;
-
-			cur = (slob_t *)__get_free_page(gfp);
-			if (!cur)
-				return 0;
-
-			slob_free(cur, PAGE_SIZE);
-			spin_lock_irqsave(&slob_lock, flags);
-			cur = slobfree;
-		}
+		if (slob_last(cur))
+			return NULL;
 	}
 }
 
-static void slob_free(void *block, int size)
+/*
+ * slob_alloc: entry point into the slob allocator.
+ */
+static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
 {
-	slob_t *cur, *b = (slob_t *)block;
+	struct slob_page *sp;
+	slob_t *b = NULL;
 	unsigned long flags;
 
-	if (!block)
-		return;
-
-	if (size)
-		b->units = SLOB_UNITS(size);
-
-	/* Find reinsertion point */
 	spin_lock_irqsave(&slob_lock, flags);
-	for (cur = slobfree; !(b > cur && b < cur->next); cur = cur->next)
-		if (cur >= cur->next && (b > cur || b < cur->next))
-			break;
+	/* Iterate through each partially free page, try to find room */
+	list_for_each_entry(sp, &free_slob_pages, list) {
+#ifdef CONFIG_NUMA
+		/*
+		 * If there's a node specification, search for a partial
+		 * page with a matching node id in the freelist.
+		 */
+		if (node != -1 && page_to_nid(&sp->page) != node)
+			continue;
+#endif
 
-	if (b + b->units == cur->next) {
-		b->units += cur->next->units;
-		b->next = cur->next->next;
-	} else
-		b->next = cur->next;
+		if (sp->units >= SLOB_UNITS(size)) {
+			b = slob_page_alloc(sp, size, align);
+			if (b)
+				break;
+		}
+	}
+	spin_unlock_irqrestore(&slob_lock, flags);
 
-	if (cur + cur->units == b) {
-		cur->units += b->units;
-		cur->next = b->next;
-	} else
-		cur->next = b;
+	/* Not enough space: must allocate a new page */
+	if (!b) {
+		b = slob_new_page(gfp, 0, node);
+		if (!b)
+			return 0;
+		sp = (struct slob_page *)virt_to_page(b);
+		set_slob_page(sp);
 
-	slobfree = cur;
+		spin_lock_irqsave(&slob_lock, flags);
+		sp->units = SLOB_UNITS(PAGE_SIZE);
+		sp->free = b;
+		INIT_LIST_HEAD(&sp->list);
+		set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
+		set_slob_page_free(sp);
+		b = slob_page_alloc(sp, size, align);
+		BUG_ON(!b);
+		spin_unlock_irqrestore(&slob_lock, flags);
+	}
+	if (unlikely((gfp & __GFP_ZERO) && b))
+		memset(b, 0, size);
+	return b;
+}
 
+/*
+ * slob_free: entry point into the slob allocator.
+ */
+static void slob_free(void *block, int size)
+{
+	struct slob_page *sp;
+	slob_t *prev, *next, *b = (slob_t *)block;
+	slobidx_t units;
+	unsigned long flags;
+
+	if (ZERO_OR_NULL_PTR(block))
+		return;
+	BUG_ON(!size);
+
+	sp = (struct slob_page *)virt_to_page(block);
+	units = SLOB_UNITS(size);
+
+	spin_lock_irqsave(&slob_lock, flags);
+
+	if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
+		/* Go directly to page allocator. Do not pass slob allocator */
+		if (slob_page_free(sp))
+			clear_slob_page_free(sp);
+		clear_slob_page(sp);
+		free_slob_page(sp);
+		free_page((unsigned long)b);
+		goto out;
+	}
+
+	if (!slob_page_free(sp)) {
+		/* This slob page is about to become partially free. Easy! */
+		sp->units = units;
+		sp->free = b;
+		set_slob(b, units,
+			(void *)((unsigned long)(b +
+					SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
+		set_slob_page_free(sp);
+		goto out;
+	}
+
+	/*
+	 * Otherwise the page is already partially free, so find reinsertion
+	 * point.
+	 */
+	sp->units += units;
+
+	if (b < sp->free) {
+		set_slob(b, units, sp->free);
+		sp->free = b;
+	} else {
+		prev = sp->free;
+		next = slob_next(prev);
+		while (b > next) {
+			prev = next;
+			next = slob_next(prev);
+		}
+
+		if (!slob_last(prev) && b + units == next) {
+			units += slob_units(next);
+			set_slob(b, units, slob_next(next));
+		} else
+			set_slob(b, units, next);
+
+		if (prev + slob_units(prev) == b) {
+			units = slob_units(b) + slob_units(prev);
+			set_slob(prev, units, slob_next(b));
+		} else
+			set_slob(prev, slob_units(prev), b);
+	}
+out:
 	spin_unlock_irqrestore(&slob_lock, flags);
 }
 
-void *__kmalloc(size_t size, gfp_t gfp)
-{
-	slob_t *m;
-	bigblock_t *bb;
-	unsigned long flags;
-
-	if (size < PAGE_SIZE - SLOB_UNIT) {
-		m = slob_alloc(size + SLOB_UNIT, gfp, 0);
-		return m ? (void *)(m + 1) : 0;
-	}
-
-	bb = slob_alloc(sizeof(bigblock_t), gfp, 0);
-	if (!bb)
-		return 0;
-
-	bb->order = get_order(size);
-	bb->pages = (void *)__get_free_pages(gfp, bb->order);
-
-	if (bb->pages) {
-		spin_lock_irqsave(&block_lock, flags);
-		bb->next = bigblocks;
-		bigblocks = bb;
-		spin_unlock_irqrestore(&block_lock, flags);
-		return bb->pages;
-	}
-
-	slob_free(bb, sizeof(bigblock_t));
-	return 0;
-}
-EXPORT_SYMBOL(__kmalloc);
-
-/**
- * krealloc - reallocate memory. The contents will remain unchanged.
- *
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
+/*
+ * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
  */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
+
+#ifndef ARCH_KMALLOC_MINALIGN
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long)
+#endif
+
+#ifndef ARCH_SLAB_MINALIGN
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long)
+#endif
+
+void *__kmalloc_node(size_t size, gfp_t gfp, int node)
 {
-	void *ret;
+	unsigned int *m;
+	int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
 
-	if (unlikely(!p))
-		return kmalloc_track_caller(new_size, flags);
+	if (size < PAGE_SIZE - align) {
+		if (!size)
+			return ZERO_SIZE_PTR;
 
-	if (unlikely(!new_size)) {
-		kfree(p);
-		return NULL;
+		m = slob_alloc(size + align, gfp, align, node);
+		if (m)
+			*m = size;
+		return (void *)m + align;
+	} else {
+		void *ret;
+
+		ret = slob_new_page(gfp | __GFP_COMP, get_order(size), node);
+		if (ret) {
+			struct page *page;
+			page = virt_to_page(ret);
+			page->private = size;
+		}
+		return ret;
 	}
-
-	ret = kmalloc_track_caller(new_size, flags);
-	if (ret) {
-		memcpy(ret, p, min(new_size, ksize(p)));
-		kfree(p);
-	}
-	return ret;
 }
-EXPORT_SYMBOL(krealloc);
+EXPORT_SYMBOL(__kmalloc_node);
 
 void kfree(const void *block)
 {
-	bigblock_t *bb, **last = &bigblocks;
-	unsigned long flags;
+	struct slob_page *sp;
 
-	if (!block)
+	if (ZERO_OR_NULL_PTR(block))
 		return;
 
-	if (!((unsigned long)block & (PAGE_SIZE-1))) {
-		/* might be on the big block list */
-		spin_lock_irqsave(&block_lock, flags);
-		for (bb = bigblocks; bb; last = &bb->next, bb = bb->next) {
-			if (bb->pages == block) {
-				*last = bb->next;
-				spin_unlock_irqrestore(&block_lock, flags);
-				free_pages((unsigned long)block, bb->order);
-				slob_free(bb, sizeof(bigblock_t));
-				return;
-			}
-		}
-		spin_unlock_irqrestore(&block_lock, flags);
-	}
-
-	slob_free((slob_t *)block - 1, 0);
-	return;
+	sp = (struct slob_page *)virt_to_page(block);
+	if (slob_page(sp)) {
+		int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+		unsigned int *m = (unsigned int *)(block - align);
+		slob_free(m, *m + align);
+	} else
+		put_page(&sp->page);
 }
-
 EXPORT_SYMBOL(kfree);
 
+/* can't use ksize for kmem_cache_alloc memory, only kmalloc */
 size_t ksize(const void *block)
 {
-	bigblock_t *bb;
-	unsigned long flags;
+	struct slob_page *sp;
 
-	if (!block)
+	if (ZERO_OR_NULL_PTR(block))
 		return 0;
 
-	if (!((unsigned long)block & (PAGE_SIZE-1))) {
-		spin_lock_irqsave(&block_lock, flags);
-		for (bb = bigblocks; bb; bb = bb->next)
-			if (bb->pages == block) {
-				spin_unlock_irqrestore(&slob_lock, flags);
-				return PAGE_SIZE << bb->order;
-			}
-		spin_unlock_irqrestore(&block_lock, flags);
-	}
-
-	return ((slob_t *)block - 1)->units * SLOB_UNIT;
+	sp = (struct slob_page *)virt_to_page(block);
+	if (slob_page(sp))
+		return ((slob_t *)block - 1)->units + SLOB_UNIT;
+	else
+		return sp->page.private;
 }
 
 struct kmem_cache {
@@ -289,7 +497,7 @@
 {
 	struct kmem_cache *c;
 
-	c = slob_alloc(sizeof(struct kmem_cache), flags, 0);
+	c = slob_alloc(sizeof(struct kmem_cache), flags, 0, -1);
 
 	if (c) {
 		c->name = name;
@@ -302,6 +510,8 @@
 		c->ctor = ctor;
 		/* ignore alignment unless it's forced */
 		c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+		if (c->align < ARCH_SLAB_MINALIGN)
+			c->align = ARCH_SLAB_MINALIGN;
 		if (c->align < align)
 			c->align = align;
 	} else if (flags & SLAB_PANIC)
@@ -317,31 +527,21 @@
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
-void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)
+void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 {
 	void *b;
 
 	if (c->size < PAGE_SIZE)
-		b = slob_alloc(c->size, flags, c->align);
+		b = slob_alloc(c->size, flags, c->align, node);
 	else
-		b = (void *)__get_free_pages(flags, get_order(c->size));
+		b = slob_new_page(flags, get_order(c->size), node);
 
 	if (c->ctor)
 		c->ctor(b, c, 0);
 
 	return b;
 }
-EXPORT_SYMBOL(kmem_cache_alloc);
-
-void *kmem_cache_zalloc(struct kmem_cache *c, gfp_t flags)
-{
-	void *ret = kmem_cache_alloc(c, flags);
-	if (ret)
-		memset(ret, 0, c->size);
-
-	return ret;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
+EXPORT_SYMBOL(kmem_cache_alloc_node);
 
 static void __kmem_cache_free(void *b, int size)
 {
@@ -385,9 +585,6 @@
 }
 EXPORT_SYMBOL(kmem_cache_name);
 
-static struct timer_list slob_timer = TIMER_INITIALIZER(
-	(void (*)(unsigned long))slob_timer_cbk, 0, 0);
-
 int kmem_cache_shrink(struct kmem_cache *d)
 {
 	return 0;
@@ -399,17 +596,14 @@
 	return 0;
 }
 
-void __init kmem_cache_init(void)
+static unsigned int slob_ready __read_mostly;
+
+int slab_is_available(void)
 {
-	slob_timer_cbk();
+	return slob_ready;
 }
 
-static void slob_timer_cbk(void)
+void __init kmem_cache_init(void)
 {
-	void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
-
-	if (p)
-		free_page((unsigned long)p);
-
-	mod_timer(&slob_timer, jiffies + HZ);
+	slob_ready = 1;
 }
diff --git a/mm/slub.c b/mm/slub.c
index e0cf621..52a4f44 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -205,6 +205,11 @@
 #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
 #endif
 
+/*
+ * The page->inuse field is 16 bit thus we have this limitation
+ */
+#define MAX_OBJECTS_PER_SLAB 65535
+
 /* Internal SLUB flags */
 #define __OBJECT_POISON 0x80000000	/* Poison object */
 
@@ -228,7 +233,7 @@
 
 /* A list of all slab caches on the system */
 static DECLARE_RWSEM(slub_lock);
-LIST_HEAD(slab_caches);
+static LIST_HEAD(slab_caches);
 
 /*
  * Tracking user of a slab.
@@ -247,9 +252,10 @@
 static int sysfs_slab_alias(struct kmem_cache *, const char *);
 static void sysfs_slab_remove(struct kmem_cache *);
 #else
-static int sysfs_slab_add(struct kmem_cache *s) { return 0; }
-static int sysfs_slab_alias(struct kmem_cache *s, const char *p) { return 0; }
-static void sysfs_slab_remove(struct kmem_cache *s) {}
+static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
+static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
+							{ return 0; }
+static inline void sysfs_slab_remove(struct kmem_cache *s) {}
 #endif
 
 /********************************************************************
@@ -323,7 +329,11 @@
 /*
  * Debug settings:
  */
+#ifdef CONFIG_SLUB_DEBUG_ON
+static int slub_debug = DEBUG_DEFAULT_FLAGS;
+#else
 static int slub_debug;
+#endif
 
 static char *slub_debug_slabs;
 
@@ -340,7 +350,7 @@
 
 	for (i = 0; i < length; i++) {
 		if (newline) {
-			printk(KERN_ERR "%10s 0x%p: ", text, addr + i);
+			printk(KERN_ERR "%8s 0x%p: ", text, addr + i);
 			newline = 0;
 		}
 		printk(" %02x", addr[i]);
@@ -397,10 +407,11 @@
 
 static void init_tracking(struct kmem_cache *s, void *object)
 {
-	if (s->flags & SLAB_STORE_USER) {
-		set_track(s, object, TRACK_FREE, NULL);
-		set_track(s, object, TRACK_ALLOC, NULL);
-	}
+	if (!(s->flags & SLAB_STORE_USER))
+		return;
+
+	set_track(s, object, TRACK_FREE, NULL);
+	set_track(s, object, TRACK_ALLOC, NULL);
 }
 
 static void print_track(const char *s, struct track *t)
@@ -408,65 +419,106 @@
 	if (!t->addr)
 		return;
 
-	printk(KERN_ERR "%s: ", s);
+	printk(KERN_ERR "INFO: %s in ", s);
 	__print_symbol("%s", (unsigned long)t->addr);
-	printk(" jiffies_ago=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+	printk(" age=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
 }
 
-static void print_trailer(struct kmem_cache *s, u8 *p)
+static void print_tracking(struct kmem_cache *s, void *object)
+{
+	if (!(s->flags & SLAB_STORE_USER))
+		return;
+
+	print_track("Allocated", get_track(s, object, TRACK_ALLOC));
+	print_track("Freed", get_track(s, object, TRACK_FREE));
+}
+
+static void print_page_info(struct page *page)
+{
+	printk(KERN_ERR "INFO: Slab 0x%p used=%u fp=0x%p flags=0x%04lx\n",
+		page, page->inuse, page->freelist, page->flags);
+
+}
+
+static void slab_bug(struct kmem_cache *s, char *fmt, ...)
+{
+	va_list args;
+	char buf[100];
+
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	printk(KERN_ERR "========================================"
+			"=====================================\n");
+	printk(KERN_ERR "BUG %s: %s\n", s->name, buf);
+	printk(KERN_ERR "----------------------------------------"
+			"-------------------------------------\n\n");
+}
+
+static void slab_fix(struct kmem_cache *s, char *fmt, ...)
+{
+	va_list args;
+	char buf[100];
+
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	printk(KERN_ERR "FIX %s: %s\n", s->name, buf);
+}
+
+static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
 {
 	unsigned int off;	/* Offset of last byte */
+	u8 *addr = page_address(page);
+
+	print_tracking(s, p);
+
+	print_page_info(page);
+
+	printk(KERN_ERR "INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
+			p, p - addr, get_freepointer(s, p));
+
+	if (p > addr + 16)
+		print_section("Bytes b4", p - 16, 16);
+
+	print_section("Object", p, min(s->objsize, 128));
 
 	if (s->flags & SLAB_RED_ZONE)
 		print_section("Redzone", p + s->objsize,
 			s->inuse - s->objsize);
 
-	printk(KERN_ERR "FreePointer 0x%p -> 0x%p\n",
-			p + s->offset,
-			get_freepointer(s, p));
-
 	if (s->offset)
 		off = s->offset + sizeof(void *);
 	else
 		off = s->inuse;
 
-	if (s->flags & SLAB_STORE_USER) {
-		print_track("Last alloc", get_track(s, p, TRACK_ALLOC));
-		print_track("Last free ", get_track(s, p, TRACK_FREE));
+	if (s->flags & SLAB_STORE_USER)
 		off += 2 * sizeof(struct track);
-	}
 
 	if (off != s->size)
 		/* Beginning of the filler is the free pointer */
-		print_section("Filler", p + off, s->size - off);
+		print_section("Padding", p + off, s->size - off);
+
+	dump_stack();
 }
 
 static void object_err(struct kmem_cache *s, struct page *page,
 			u8 *object, char *reason)
 {
-	u8 *addr = page_address(page);
-
-	printk(KERN_ERR "*** SLUB %s: %s@0x%p slab 0x%p\n",
-			s->name, reason, object, page);
-	printk(KERN_ERR "    offset=%tu flags=0x%04lx inuse=%u freelist=0x%p\n",
-		object - addr, page->flags, page->inuse, page->freelist);
-	if (object > addr + 16)
-		print_section("Bytes b4", object - 16, 16);
-	print_section("Object", object, min(s->objsize, 128));
-	print_trailer(s, object);
-	dump_stack();
+	slab_bug(s, reason);
+	print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page, char *reason, ...)
+static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
 {
 	va_list args;
 	char buf[100];
 
-	va_start(args, reason);
-	vsnprintf(buf, sizeof(buf), reason, args);
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
-	printk(KERN_ERR "*** SLUB %s: %s in slab @0x%p\n", s->name, buf,
-		page);
+	slab_bug(s, fmt);
+	print_page_info(page);
 	dump_stack();
 }
 
@@ -485,15 +537,46 @@
 			s->inuse - s->objsize);
 }
 
-static int check_bytes(u8 *start, unsigned int value, unsigned int bytes)
+static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
 {
 	while (bytes) {
 		if (*start != (u8)value)
-			return 0;
+			return start;
 		start++;
 		bytes--;
 	}
-	return 1;
+	return NULL;
+}
+
+static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
+						void *from, void *to)
+{
+	slab_fix(s, "Restoring 0x%p-0x%p=0x%x\n", from, to - 1, data);
+	memset(from, data, to - from);
+}
+
+static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
+			u8 *object, char *what,
+			u8* start, unsigned int value, unsigned int bytes)
+{
+	u8 *fault;
+	u8 *end;
+
+	fault = check_bytes(start, value, bytes);
+	if (!fault)
+		return 1;
+
+	end = start + bytes;
+	while (end > fault && end[-1] == value)
+		end--;
+
+	slab_bug(s, "%s overwritten", what);
+	printk(KERN_ERR "INFO: 0x%p-0x%p. First byte 0x%x instead of 0x%x\n",
+					fault, end - 1, fault[0], value);
+	print_trailer(s, page, object);
+
+	restore_bytes(s, what, value, fault, end);
+	return 0;
 }
 
 /*
@@ -534,14 +617,6 @@
  * may be used with merged slabcaches.
  */
 
-static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
-						void *from, void *to)
-{
-	printk(KERN_ERR "@@@ SLUB %s: Restoring %s (0x%x) from 0x%p-0x%p\n",
-		s->name, message, data, from, to - 1);
-	memset(from, data, to - from);
-}
-
 static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
 {
 	unsigned long off = s->inuse;	/* The end of info */
@@ -557,39 +632,39 @@
 	if (s->size == off)
 		return 1;
 
-	if (check_bytes(p + off, POISON_INUSE, s->size - off))
-		return 1;
-
-	object_err(s, page, p, "Object padding check fails");
-
-	/*
-	 * Restore padding
-	 */
-	restore_bytes(s, "object padding", POISON_INUSE, p + off, p + s->size);
-	return 0;
+	return check_bytes_and_report(s, page, p, "Object padding",
+				p + off, POISON_INUSE, s->size - off);
 }
 
 static int slab_pad_check(struct kmem_cache *s, struct page *page)
 {
-	u8 *p;
-	int length, remainder;
+	u8 *start;
+	u8 *fault;
+	u8 *end;
+	int length;
+	int remainder;
 
 	if (!(s->flags & SLAB_POISON))
 		return 1;
 
-	p = page_address(page);
+	start = page_address(page);
+	end = start + (PAGE_SIZE << s->order);
 	length = s->objects * s->size;
-	remainder = (PAGE_SIZE << s->order) - length;
+	remainder = end - (start + length);
 	if (!remainder)
 		return 1;
 
-	if (!check_bytes(p + length, POISON_INUSE, remainder)) {
-		slab_err(s, page, "Padding check failed");
-		restore_bytes(s, "slab padding", POISON_INUSE, p + length,
-			p + length + remainder);
-		return 0;
-	}
-	return 1;
+	fault = check_bytes(start + length, POISON_INUSE, remainder);
+	if (!fault)
+		return 1;
+	while (end > fault && end[-1] == POISON_INUSE)
+		end--;
+
+	slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
+	print_section("Padding", start, length);
+
+	restore_bytes(s, "slab padding", POISON_INUSE, start, end);
+	return 0;
 }
 
 static int check_object(struct kmem_cache *s, struct page *page,
@@ -602,41 +677,22 @@
 		unsigned int red =
 			active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE;
 
-		if (!check_bytes(endobject, red, s->inuse - s->objsize)) {
-			object_err(s, page, object,
-			active ? "Redzone Active" : "Redzone Inactive");
-			restore_bytes(s, "redzone", red,
-				endobject, object + s->inuse);
+		if (!check_bytes_and_report(s, page, object, "Redzone",
+			endobject, red, s->inuse - s->objsize))
 			return 0;
-		}
 	} else {
-		if ((s->flags & SLAB_POISON) && s->objsize < s->inuse &&
-			!check_bytes(endobject, POISON_INUSE,
-					s->inuse - s->objsize)) {
-		object_err(s, page, p, "Alignment padding check fails");
-		/*
-		 * Fix it so that there will not be another report.
-		 *
-		 * Hmmm... We may be corrupting an object that now expects
-		 * to be longer than allowed.
-		 */
-		restore_bytes(s, "alignment padding", POISON_INUSE,
-			endobject, object + s->inuse);
-		}
+		if ((s->flags & SLAB_POISON) && s->objsize < s->inuse)
+			check_bytes_and_report(s, page, p, "Alignment padding", endobject,
+				POISON_INUSE, s->inuse - s->objsize);
 	}
 
 	if (s->flags & SLAB_POISON) {
 		if (!active && (s->flags & __OBJECT_POISON) &&
-			(!check_bytes(p, POISON_FREE, s->objsize - 1) ||
-				p[s->objsize - 1] != POISON_END)) {
-
-			object_err(s, page, p, "Poison check failed");
-			restore_bytes(s, "Poison", POISON_FREE,
-						p, p + s->objsize -1);
-			restore_bytes(s, "Poison", POISON_END,
-					p + s->objsize - 1, p + s->objsize);
+			(!check_bytes_and_report(s, page, p, "Poison", p,
+					POISON_FREE, s->objsize - 1) ||
+			 !check_bytes_and_report(s, page, p, "Poison",
+			 	p + s->objsize -1, POISON_END, 1)))
 			return 0;
-		}
 		/*
 		 * check_pad_bytes cleans up on its own.
 		 */
@@ -669,25 +725,17 @@
 	VM_BUG_ON(!irqs_disabled());
 
 	if (!PageSlab(page)) {
-		slab_err(s, page, "Not a valid slab page flags=%lx "
-			"mapping=0x%p count=%d", page->flags, page->mapping,
-			page_count(page));
+		slab_err(s, page, "Not a valid slab page");
 		return 0;
 	}
 	if (page->offset * sizeof(void *) != s->offset) {
-		slab_err(s, page, "Corrupted offset %lu flags=0x%lx "
-			"mapping=0x%p count=%d",
-			(unsigned long)(page->offset * sizeof(void *)),
-			page->flags,
-			page->mapping,
-			page_count(page));
+		slab_err(s, page, "Corrupted offset %lu",
+			(unsigned long)(page->offset * sizeof(void *)));
 		return 0;
 	}
 	if (page->inuse > s->objects) {
-		slab_err(s, page, "inuse %u > max %u @0x%p flags=%lx "
-			"mapping=0x%p count=%d",
-			s->name, page->inuse, s->objects, page->flags,
-			page->mapping, page_count(page));
+		slab_err(s, page, "inuse %u > max %u",
+			s->name, page->inuse, s->objects);
 		return 0;
 	}
 	/* Slab_pad_check fixes things up after itself */
@@ -715,13 +763,10 @@
 				set_freepointer(s, object, NULL);
 				break;
 			} else {
-				slab_err(s, page, "Freepointer 0x%p corrupt",
-									fp);
+				slab_err(s, page, "Freepointer corrupt");
 				page->freelist = NULL;
 				page->inuse = s->objects;
-				printk(KERN_ERR "@@@ SLUB %s: Freelist "
-					"cleared. Slab 0x%p\n",
-					s->name, page);
+				slab_fix(s, "Freelist cleared");
 				return 0;
 			}
 			break;
@@ -733,11 +778,9 @@
 
 	if (page->inuse != s->objects - nr) {
 		slab_err(s, page, "Wrong object count. Counter is %d but "
-			"counted were %d", s, page, page->inuse,
-							s->objects - nr);
+			"counted were %d", page->inuse, s->objects - nr);
 		page->inuse = s->objects - nr;
-		printk(KERN_ERR "@@@ SLUB %s: Object count adjusted. "
-			"Slab @0x%p\n", s->name, page);
+		slab_fix(s, "Object count adjusted.");
 	}
 	return search == NULL;
 }
@@ -799,7 +842,7 @@
 		goto bad;
 
 	if (object && !on_freelist(s, page, object)) {
-		slab_err(s, page, "Object 0x%p already allocated", object);
+		object_err(s, page, object, "Object already allocated");
 		goto bad;
 	}
 
@@ -825,8 +868,7 @@
 		 * to avoid issues in the future. Marking all objects
 		 * as used avoids touching the remaining objects.
 		 */
-		printk(KERN_ERR "@@@ SLUB: %s slab 0x%p. Marking all objects used.\n",
-			s->name, page);
+		slab_fix(s, "Marking all objects used");
 		page->inuse = s->objects;
 		page->freelist = NULL;
 		/* Fix up fields that may be corrupted */
@@ -847,7 +889,7 @@
 	}
 
 	if (on_freelist(s, page, object)) {
-		slab_err(s, page, "Object 0x%p already free", object);
+		object_err(s, page, object, "Object already free");
 		goto fail;
 	}
 
@@ -866,8 +908,8 @@
 			dump_stack();
 		}
 		else
-			slab_err(s, page, "object at 0x%p belongs "
-				"to slab %s", object, page->slab->name);
+			object_err(s, page, object,
+					"page slab pointer corrupt.");
 		goto fail;
 	}
 
@@ -881,45 +923,63 @@
 	return 1;
 
 fail:
-	printk(KERN_ERR "@@@ SLUB: %s slab 0x%p object at 0x%p not freed.\n",
-		s->name, page, object);
+	slab_fix(s, "Object at 0x%p not freed", object);
 	return 0;
 }
 
 static int __init setup_slub_debug(char *str)
 {
-	if (!str || *str != '=')
-		slub_debug = DEBUG_DEFAULT_FLAGS;
-	else {
-		str++;
-		if (*str == 0 || *str == ',')
-			slub_debug = DEBUG_DEFAULT_FLAGS;
-		else
-		for( ;*str && *str != ','; str++)
-			switch (*str) {
-			case 'f' : case 'F' :
-				slub_debug |= SLAB_DEBUG_FREE;
-				break;
-			case 'z' : case 'Z' :
-				slub_debug |= SLAB_RED_ZONE;
-				break;
-			case 'p' : case 'P' :
-				slub_debug |= SLAB_POISON;
-				break;
-			case 'u' : case 'U' :
-				slub_debug |= SLAB_STORE_USER;
-				break;
-			case 't' : case 'T' :
-				slub_debug |= SLAB_TRACE;
-				break;
-			default:
-				printk(KERN_ERR "slub_debug option '%c' "
-					"unknown. skipped\n",*str);
-			}
-	}
+	slub_debug = DEBUG_DEFAULT_FLAGS;
+	if (*str++ != '=' || !*str)
+		/*
+		 * No options specified. Switch on full debugging.
+		 */
+		goto out;
 
 	if (*str == ',')
+		/*
+		 * No options but restriction on slabs. This means full
+		 * debugging for slabs matching a pattern.
+		 */
+		goto check_slabs;
+
+	slub_debug = 0;
+	if (*str == '-')
+		/*
+		 * Switch off all debugging measures.
+		 */
+		goto out;
+
+	/*
+	 * Determine which debug features should be switched on
+	 */
+	for ( ;*str && *str != ','; str++) {
+		switch (tolower(*str)) {
+		case 'f':
+			slub_debug |= SLAB_DEBUG_FREE;
+			break;
+		case 'z':
+			slub_debug |= SLAB_RED_ZONE;
+			break;
+		case 'p':
+			slub_debug |= SLAB_POISON;
+			break;
+		case 'u':
+			slub_debug |= SLAB_STORE_USER;
+			break;
+		case 't':
+			slub_debug |= SLAB_TRACE;
+			break;
+		default:
+			printk(KERN_ERR "slub_debug option '%c' "
+				"unknown. skipped\n",*str);
+		}
+	}
+
+check_slabs:
+	if (*str == ',')
 		slub_debug_slabs = str + 1;
+out:
 	return 1;
 }
 
@@ -1018,7 +1078,7 @@
 	void *last;
 	void *p;
 
-	BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
+	BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
 
 	if (flags & __GFP_WAIT)
 		local_irq_enable();
@@ -1336,7 +1396,7 @@
 	unfreeze_slab(s, page);
 }
 
-static void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
+static inline void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
 {
 	slab_lock(page);
 	deactivate_slab(s, page, cpu);
@@ -1346,7 +1406,7 @@
  * Flush cpu slab.
  * Called from IPI handler with interrupts disabled.
  */
-static void __flush_cpu_slab(struct kmem_cache *s, int cpu)
+static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu)
 {
 	struct page *page = s->cpu_slab[cpu];
 
@@ -1481,7 +1541,7 @@
  * Otherwise we can simply pick the next object from the lockless free list.
  */
 static void __always_inline *slab_alloc(struct kmem_cache *s,
-				gfp_t gfpflags, int node, void *addr)
+		gfp_t gfpflags, int node, void *addr)
 {
 	struct page *page;
 	void **object;
@@ -1499,6 +1559,10 @@
 		page->lockless_freelist = object[page->offset];
 	}
 	local_irq_restore(flags);
+
+	if (unlikely((gfpflags & __GFP_ZERO) && object))
+		memset(object, 0, s->objsize);
+
 	return object;
 }
 
@@ -1682,8 +1746,17 @@
 {
 	int order;
 	int rem;
+	int min_order = slub_min_order;
 
-	for (order = max(slub_min_order,
+	/*
+	 * If we would create too many object per slab then reduce
+	 * the slab order even if it goes below slub_min_order.
+	 */
+	while (min_order > 0 &&
+		(PAGE_SIZE << min_order) >= MAX_OBJECTS_PER_SLAB * size)
+			min_order--;
+
+	for (order = max(min_order,
 				fls(min_objects * size - 1) - PAGE_SHIFT);
 			order <= max_order; order++) {
 
@@ -1697,6 +1770,9 @@
 		if (rem <= slab_size / fract_leftover)
 			break;
 
+		/* If the next size is too high then exit now */
+		if (slab_size * 2 >= MAX_OBJECTS_PER_SLAB * size)
+			break;
 	}
 
 	return order;
@@ -1777,7 +1853,9 @@
 	atomic_long_set(&n->nr_slabs, 0);
 	spin_lock_init(&n->list_lock);
 	INIT_LIST_HEAD(&n->partial);
+#ifdef CONFIG_SLUB_DEBUG
 	INIT_LIST_HEAD(&n->full);
+#endif
 }
 
 #ifdef CONFIG_NUMA
@@ -1805,7 +1883,10 @@
 	page->freelist = get_freepointer(kmalloc_caches, n);
 	page->inuse++;
 	kmalloc_caches->node[node] = n;
-	setup_object_debug(kmalloc_caches, page, n);
+#ifdef CONFIG_SLUB_DEBUG
+	init_object(kmalloc_caches, n, 1);
+	init_tracking(kmalloc_caches, n);
+#endif
 	init_kmem_cache_node(n);
 	atomic_long_inc(&n->nr_slabs);
 	add_partial(n, page);
@@ -1983,7 +2064,7 @@
 	 * The page->inuse field is only 16 bit wide! So we cannot have
 	 * more than 64k objects per slab.
 	 */
-	if (!s->objects || s->objects > 65535)
+	if (!s->objects || s->objects > MAX_OBJECTS_PER_SLAB)
 		return 0;
 	return 1;
 
@@ -2087,7 +2168,7 @@
 /*
  * Release all resources used by a slab cache.
  */
-static int kmem_cache_close(struct kmem_cache *s)
+static inline int kmem_cache_close(struct kmem_cache *s)
 {
 	int node;
 
@@ -2115,12 +2196,13 @@
 	s->refcount--;
 	if (!s->refcount) {
 		list_del(&s->list);
+		up_write(&slub_lock);
 		if (kmem_cache_close(s))
 			WARN_ON(1);
 		sysfs_slab_remove(s);
 		kfree(s);
-	}
-	up_write(&slub_lock);
+	} else
+		up_write(&slub_lock);
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
@@ -2193,47 +2275,92 @@
 	panic("Creation of kmalloc slab %s size=%d failed.\n", name, size);
 }
 
-static struct kmem_cache *get_slab(size_t size, gfp_t flags)
-{
-	int index = kmalloc_index(size);
-
-	if (!index)
-		return NULL;
-
-	/* Allocation too large? */
-	BUG_ON(index < 0);
-
 #ifdef CONFIG_ZONE_DMA
-	if ((flags & SLUB_DMA)) {
-		struct kmem_cache *s;
-		struct kmem_cache *x;
-		char *text;
-		size_t realsize;
+static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags)
+{
+	struct kmem_cache *s;
+	struct kmem_cache *x;
+	char *text;
+	size_t realsize;
 
-		s = kmalloc_caches_dma[index];
-		if (s)
-			return s;
+	s = kmalloc_caches_dma[index];
+	if (s)
+		return s;
 
-		/* Dynamically create dma cache */
-		x = kmalloc(kmem_size, flags & ~SLUB_DMA);
-		if (!x)
-			panic("Unable to allocate memory for dma cache\n");
+	/* Dynamically create dma cache */
+	x = kmalloc(kmem_size, flags & ~SLUB_DMA);
+	if (!x)
+		panic("Unable to allocate memory for dma cache\n");
 
-		if (index <= KMALLOC_SHIFT_HIGH)
-			realsize = 1 << index;
-		else {
-			if (index == 1)
-				realsize = 96;
-			else
-				realsize = 192;
-		}
-
-		text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
-				(unsigned int)realsize);
-		s = create_kmalloc_cache(x, text, realsize, flags);
+	realsize = kmalloc_caches[index].objsize;
+	text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
+			(unsigned int)realsize);
+	s = create_kmalloc_cache(x, text, realsize, flags);
+	down_write(&slub_lock);
+	if (!kmalloc_caches_dma[index]) {
 		kmalloc_caches_dma[index] = s;
+		up_write(&slub_lock);
 		return s;
 	}
+	up_write(&slub_lock);
+	kmem_cache_destroy(s);
+	return kmalloc_caches_dma[index];
+}
+#endif
+
+/*
+ * Conversion table for small slabs sizes / 8 to the index in the
+ * kmalloc array. This is necessary for slabs < 192 since we have non power
+ * of two cache sizes there. The size of larger slabs can be determined using
+ * fls.
+ */
+static s8 size_index[24] = {
+	3,	/* 8 */
+	4,	/* 16 */
+	5,	/* 24 */
+	5,	/* 32 */
+	6,	/* 40 */
+	6,	/* 48 */
+	6,	/* 56 */
+	6,	/* 64 */
+	1,	/* 72 */
+	1,	/* 80 */
+	1,	/* 88 */
+	1,	/* 96 */
+	7,	/* 104 */
+	7,	/* 112 */
+	7,	/* 120 */
+	7,	/* 128 */
+	2,	/* 136 */
+	2,	/* 144 */
+	2,	/* 152 */
+	2,	/* 160 */
+	2,	/* 168 */
+	2,	/* 176 */
+	2,	/* 184 */
+	2	/* 192 */
+};
+
+static struct kmem_cache *get_slab(size_t size, gfp_t flags)
+{
+	int index;
+
+	if (size <= 192) {
+		if (!size)
+			return ZERO_SIZE_PTR;
+
+		index = size_index[(size - 1) / 8];
+	} else {
+		if (size > KMALLOC_MAX_SIZE)
+			return NULL;
+
+		index = fls(size - 1);
+	}
+
+#ifdef CONFIG_ZONE_DMA
+	if (unlikely((flags & SLUB_DMA)))
+		return dma_kmalloc_cache(index, flags);
+
 #endif
 	return &kmalloc_caches[index];
 }
@@ -2242,9 +2369,10 @@
 {
 	struct kmem_cache *s = get_slab(size, flags);
 
-	if (s)
-		return slab_alloc(s, flags, -1, __builtin_return_address(0));
-	return ZERO_SIZE_PTR;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
+
+	return slab_alloc(s, flags, -1, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(__kmalloc);
 
@@ -2253,9 +2381,10 @@
 {
 	struct kmem_cache *s = get_slab(size, flags);
 
-	if (s)
-		return slab_alloc(s, flags, node, __builtin_return_address(0));
-	return ZERO_SIZE_PTR;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
+
+	return slab_alloc(s, flags, node, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(__kmalloc_node);
 #endif
@@ -2306,7 +2435,7 @@
 	 * this comparison would be true for all "negative" pointers
 	 * (which would cover the whole upper half of the address space).
 	 */
-	if ((unsigned long)x <= (unsigned long)ZERO_SIZE_PTR)
+	if (ZERO_OR_NULL_PTR(x))
 		return;
 
 	page = virt_to_head_page(x);
@@ -2395,43 +2524,6 @@
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
-/**
- * krealloc - reallocate memory. The contents will remain unchanged.
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
- */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
-{
-	void *ret;
-	size_t ks;
-
-	if (unlikely(!p || p == ZERO_SIZE_PTR))
-		return kmalloc(new_size, flags);
-
-	if (unlikely(!new_size)) {
-		kfree(p);
-		return ZERO_SIZE_PTR;
-	}
-
-	ks = ksize(p);
-	if (ks >= new_size)
-		return (void *)p;
-
-	ret = kmalloc(new_size, flags);
-	if (ret) {
-		memcpy(ret, p, min(new_size, ks));
-		kfree(p);
-	}
-	return ret;
-}
-EXPORT_SYMBOL(krealloc);
-
 /********************************************************************
  *			Basic setup of slabs
  *******************************************************************/
@@ -2474,6 +2566,24 @@
 		caches++;
 	}
 
+
+	/*
+	 * Patch up the size_index table if we have strange large alignment
+	 * requirements for the kmalloc array. This is only the case for
+	 * mips it seems. The standard arches will not generate any code here.
+	 *
+	 * Largest permitted alignment is 256 bytes due to the way we
+	 * handle the index determination for the smaller caches.
+	 *
+	 * Make sure that nothing crazy happens if someone starts tinkering
+	 * around with ARCH_KMALLOC_MINALIGN
+	 */
+	BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
+		(KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
+
+	for (i = 8; i < KMALLOC_MIN_SIZE; i += 8)
+		size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW;
+
 	slab_state = UP;
 
 	/* Provide the correct kmalloc names now that the caches are up */
@@ -2519,7 +2629,7 @@
 		size_t align, unsigned long flags,
 		void (*ctor)(void *, struct kmem_cache *, unsigned long))
 {
-	struct list_head *h;
+	struct kmem_cache *s;
 
 	if (slub_nomerge || (flags & SLUB_NEVER_MERGE))
 		return NULL;
@@ -2531,10 +2641,7 @@
 	align = calculate_alignment(flags, align, size);
 	size = ALIGN(size, align);
 
-	list_for_each(h, &slab_caches) {
-		struct kmem_cache *s =
-			container_of(h, struct kmem_cache, list);
-
+	list_for_each_entry(s, &slab_caches, list) {
 		if (slab_unmergeable(s))
 			continue;
 
@@ -2577,25 +2684,26 @@
 		 */
 		s->objsize = max(s->objsize, (int)size);
 		s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
+		up_write(&slub_lock);
 		if (sysfs_slab_alias(s, name))
 			goto err;
-	} else {
-		s = kmalloc(kmem_size, GFP_KERNEL);
-		if (s && kmem_cache_open(s, GFP_KERNEL, name,
+		return s;
+	}
+	s = kmalloc(kmem_size, GFP_KERNEL);
+	if (s) {
+		if (kmem_cache_open(s, GFP_KERNEL, name,
 				size, align, flags, ctor)) {
-			if (sysfs_slab_add(s)) {
-				kfree(s);
-				goto err;
-			}
 			list_add(&s->list, &slab_caches);
-		} else
-			kfree(s);
+			up_write(&slub_lock);
+			if (sysfs_slab_add(s))
+				goto err;
+			return s;
+		}
+		kfree(s);
 	}
 	up_write(&slub_lock);
-	return s;
 
 err:
-	up_write(&slub_lock);
 	if (flags & SLAB_PANIC)
 		panic("Cannot create slabcache %s\n", name);
 	else
@@ -2604,45 +2712,7 @@
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
-void *kmem_cache_zalloc(struct kmem_cache *s, gfp_t flags)
-{
-	void *x;
-
-	x = slab_alloc(s, flags, -1, __builtin_return_address(0));
-	if (x)
-		memset(x, 0, s->objsize);
-	return x;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
-
 #ifdef CONFIG_SMP
-static void for_all_slabs(void (*func)(struct kmem_cache *, int), int cpu)
-{
-	struct list_head *h;
-
-	down_read(&slub_lock);
-	list_for_each(h, &slab_caches) {
-		struct kmem_cache *s =
-			container_of(h, struct kmem_cache, list);
-
-		func(s, cpu);
-	}
-	up_read(&slub_lock);
-}
-
-/*
- * Version of __flush_cpu_slab for the case that interrupts
- * are enabled.
- */
-static void cpu_slab_flush(struct kmem_cache *s, int cpu)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	__flush_cpu_slab(s, cpu);
-	local_irq_restore(flags);
-}
-
 /*
  * Use the cpu notifier to insure that the cpu slabs are flushed when
  * necessary.
@@ -2651,13 +2721,21 @@
 		unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
+	struct kmem_cache *s;
+	unsigned long flags;
 
 	switch (action) {
 	case CPU_UP_CANCELED:
 	case CPU_UP_CANCELED_FROZEN:
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
-		for_all_slabs(cpu_slab_flush, cpu);
+		down_read(&slub_lock);
+		list_for_each_entry(s, &slab_caches, list) {
+			local_irq_save(flags);
+			__flush_cpu_slab(s, cpu);
+			local_irq_restore(flags);
+		}
+		up_read(&slub_lock);
 		break;
 	default:
 		break;
@@ -2674,8 +2752,8 @@
 {
 	struct kmem_cache *s = get_slab(size, gfpflags);
 
-	if (!s)
-		return ZERO_SIZE_PTR;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
 
 	return slab_alloc(s, gfpflags, -1, caller);
 }
@@ -2685,18 +2763,18 @@
 {
 	struct kmem_cache *s = get_slab(size, gfpflags);
 
-	if (!s)
-		return ZERO_SIZE_PTR;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
 
 	return slab_alloc(s, gfpflags, node, caller);
 }
 
 #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
-static int validate_slab(struct kmem_cache *s, struct page *page)
+static int validate_slab(struct kmem_cache *s, struct page *page,
+						unsigned long *map)
 {
 	void *p;
 	void *addr = page_address(page);
-	DECLARE_BITMAP(map, s->objects);
 
 	if (!check_slab(s, page) ||
 			!on_freelist(s, page, NULL))
@@ -2718,10 +2796,11 @@
 	return 1;
 }
 
-static void validate_slab_slab(struct kmem_cache *s, struct page *page)
+static void validate_slab_slab(struct kmem_cache *s, struct page *page,
+						unsigned long *map)
 {
 	if (slab_trylock(page)) {
-		validate_slab(s, page);
+		validate_slab(s, page, map);
 		slab_unlock(page);
 	} else
 		printk(KERN_INFO "SLUB %s: Skipped busy slab 0x%p\n",
@@ -2738,7 +2817,8 @@
 	}
 }
 
-static int validate_slab_node(struct kmem_cache *s, struct kmem_cache_node *n)
+static int validate_slab_node(struct kmem_cache *s,
+		struct kmem_cache_node *n, unsigned long *map)
 {
 	unsigned long count = 0;
 	struct page *page;
@@ -2747,7 +2827,7 @@
 	spin_lock_irqsave(&n->list_lock, flags);
 
 	list_for_each_entry(page, &n->partial, lru) {
-		validate_slab_slab(s, page);
+		validate_slab_slab(s, page, map);
 		count++;
 	}
 	if (count != n->nr_partial)
@@ -2758,7 +2838,7 @@
 		goto out;
 
 	list_for_each_entry(page, &n->full, lru) {
-		validate_slab_slab(s, page);
+		validate_slab_slab(s, page, map);
 		count++;
 	}
 	if (count != atomic_long_read(&n->nr_slabs))
@@ -2771,17 +2851,23 @@
 	return count;
 }
 
-static unsigned long validate_slab_cache(struct kmem_cache *s)
+static long validate_slab_cache(struct kmem_cache *s)
 {
 	int node;
 	unsigned long count = 0;
+	unsigned long *map = kmalloc(BITS_TO_LONGS(s->objects) *
+				sizeof(unsigned long), GFP_KERNEL);
+
+	if (!map)
+		return -ENOMEM;
 
 	flush_all(s);
 	for_each_online_node(node) {
 		struct kmem_cache_node *n = get_node(s, node);
 
-		count += validate_slab_node(s, n);
+		count += validate_slab_node(s, n, map);
 	}
+	kfree(map);
 	return count;
 }
 
@@ -2870,18 +2956,14 @@
 			get_order(sizeof(struct location) * t->max));
 }
 
-static int alloc_loc_track(struct loc_track *t, unsigned long max)
+static int alloc_loc_track(struct loc_track *t, unsigned long max, gfp_t flags)
 {
 	struct location *l;
 	int order;
 
-	if (!max)
-		max = PAGE_SIZE / sizeof(struct location);
-
 	order = get_order(sizeof(struct location) * max);
 
-	l = (void *)__get_free_pages(GFP_ATOMIC, order);
-
+	l = (void *)__get_free_pages(flags, order);
 	if (!l)
 		return 0;
 
@@ -2947,7 +3029,7 @@
 	/*
 	 * Not found. Insert new tracking element.
 	 */
-	if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max))
+	if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max, GFP_ATOMIC))
 		return 0;
 
 	l = t->loc + pos;
@@ -2990,11 +3072,12 @@
 {
 	int n = 0;
 	unsigned long i;
-	struct loc_track t;
+	struct loc_track t = { 0, 0, NULL };
 	int node;
 
-	t.count = 0;
-	t.max = 0;
+	if (!alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location),
+			GFP_KERNEL))
+		return sprintf(buf, "Out of memory\n");
 
 	/* Push back cpu slabs */
 	flush_all(s);
@@ -3398,11 +3481,14 @@
 static ssize_t validate_store(struct kmem_cache *s,
 			const char *buf, size_t length)
 {
-	if (buf[0] == '1')
-		validate_slab_cache(s);
-	else
-		return -EINVAL;
-	return length;
+	int ret = -EINVAL;
+
+	if (buf[0] == '1') {
+		ret = validate_slab_cache(s);
+		if (ret >= 0)
+			ret = length;
+	}
+	return ret;
 }
 SLAB_ATTR(validate);
 
@@ -3556,7 +3642,7 @@
 	.filter = uevent_filter,
 };
 
-decl_subsys(slab, &slab_ktype, &slab_uevent_ops);
+static decl_subsys(slab, &slab_ktype, &slab_uevent_ops);
 
 #define ID_STR_LENGTH 64
 
@@ -3654,7 +3740,7 @@
 	struct saved_alias *next;
 };
 
-struct saved_alias *alias_list;
+static struct saved_alias *alias_list;
 
 static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
 {
@@ -3682,7 +3768,7 @@
 
 static int __init slab_sysfs_init(void)
 {
-	struct list_head *h;
+	struct kmem_cache *s;
 	int err;
 
 	err = subsystem_register(&slab_subsys);
@@ -3693,10 +3779,7 @@
 
 	slab_state = SYSFS;
 
-	list_for_each(h, &slab_caches) {
-		struct kmem_cache *s =
-			container_of(h, struct kmem_cache, list);
-
+	list_for_each_entry(s, &slab_caches, list) {
 		err = sysfs_slab_add(s);
 		BUG_ON(err);
 	}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 5f7cf2a..67daecb 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -21,7 +21,7 @@
 
 /*
  * swapper_space is a fiction, retained to simplify the path through
- * vmscan's shrink_list, to make sync_page look nicer, and to allow
+ * vmscan's shrink_page_list, to make sync_page look nicer, and to allow
  * future use of radix_tree tags in the swap cache.
  */
 static const struct address_space_operations swap_aops = {
@@ -334,7 +334,8 @@
 		 * Get a new page to read into from swap.
 		 */
 		if (!new_page) {
-			new_page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
+			new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+								vma, addr);
 			if (!new_page)
 				break;		/* Out of memory */
 		}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index acc172c..7ff0a81 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -885,7 +885,7 @@
 		/*
 		 * So we could skip searching mms once swap count went
 		 * to 1, we did not mark any present ptes as dirty: must
-		 * mark page dirty so shrink_list will preserve it.
+		 * mark page dirty so shrink_page_list will preserve it.
 		 */
 		SetPageDirty(page);
 		unlock_page(page);
diff --git a/mm/truncate.c b/mm/truncate.c
index 4fbe1a2..f47e46d 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -100,9 +100,9 @@
 	if (PagePrivate(page))
 		do_invalidatepage(page, 0);
 
+	remove_from_page_cache(page);
 	ClearPageUptodate(page);
 	ClearPageMappedToDisk(page);
-	remove_from_page_cache(page);
 	page_cache_release(page);	/* pagecache ref */
 }
 
@@ -253,21 +253,8 @@
 }
 EXPORT_SYMBOL(truncate_inode_pages);
 
-/**
- * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
- * @mapping: the address_space which holds the pages to invalidate
- * @start: the offset 'from' which to invalidate
- * @end: the offset 'to' which to invalidate (inclusive)
- *
- * This function only removes the unlocked pages, if you want to
- * remove all the pages of one inode, you must call truncate_inode_pages.
- *
- * invalidate_mapping_pages() will not block on IO activity. It will not
- * invalidate pages which are dirty, locked, under writeback or mapped into
- * pagetables.
- */
-unsigned long invalidate_mapping_pages(struct address_space *mapping,
-				pgoff_t start, pgoff_t end)
+unsigned long __invalidate_mapping_pages(struct address_space *mapping,
+				pgoff_t start, pgoff_t end, bool be_atomic)
 {
 	struct pagevec pvec;
 	pgoff_t next = start;
@@ -308,17 +295,38 @@
 				break;
 		}
 		pagevec_release(&pvec);
+		if (likely(!be_atomic))
+			cond_resched();
 	}
 	return ret;
 }
+
+/**
+ * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
+ * @mapping: the address_space which holds the pages to invalidate
+ * @start: the offset 'from' which to invalidate
+ * @end: the offset 'to' which to invalidate (inclusive)
+ *
+ * This function only removes the unlocked pages, if you want to
+ * remove all the pages of one inode, you must call truncate_inode_pages.
+ *
+ * invalidate_mapping_pages() will not block on IO activity. It will not
+ * invalidate pages which are dirty, locked, under writeback or mapped into
+ * pagetables.
+ */
+unsigned long invalidate_mapping_pages(struct address_space *mapping,
+				pgoff_t start, pgoff_t end)
+{
+	return __invalidate_mapping_pages(mapping, start, end, false);
+}
 EXPORT_SYMBOL(invalidate_mapping_pages);
 
 /*
  * This is like invalidate_complete_page(), except it ignores the page's
  * refcount.  We do this because invalidate_inode_pages2() needs stronger
  * invalidation guarantees, and cannot afford to leave pages behind because
- * shrink_list() has a temp ref on them, or because they're transiently sitting
- * in the lru_cache_add() pagevecs.
+ * shrink_page_list() has a temp ref on them, or because they're transiently
+ * sitting in the lru_cache_add() pagevecs.
  */
 static int
 invalidate_complete_page2(struct address_space *mapping, struct page *page)
diff --git a/mm/util.c b/mm/util.c
index ace2aea..78f3783 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -5,20 +5,6 @@
 #include <asm/uaccess.h>
 
 /**
- * __kzalloc - allocate memory. The memory is set to zero.
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- */
-void *__kzalloc(size_t size, gfp_t flags)
-{
-	void *ret = kmalloc_track_caller(size, flags);
-	if (ret)
-		memset(ret, 0, size);
-	return ret;
-}
-EXPORT_SYMBOL(__kzalloc);
-
-/*
  * kstrdup - allocate space for and copy an existing string
  *
  * @s: the string to duplicate
@@ -58,6 +44,40 @@
 }
 EXPORT_SYMBOL(kmemdup);
 
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.  If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+	void *ret;
+	size_t ks;
+
+	if (unlikely(!new_size)) {
+		kfree(p);
+		return ZERO_SIZE_PTR;
+	}
+
+	ks = ksize(p);
+	if (ks >= new_size)
+		return (void *)p;
+
+	ret = kmalloc_track_caller(new_size, flags);
+	if (ret) {
+		memcpy(ret, p, min(new_size, ks));
+		kfree(p);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(krealloc);
+
 /*
  * strndup_user - duplicate an existing string from user space
  *
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d3a9c53..8e05a11 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -68,12 +68,12 @@
 	} while (pud++, addr = next, addr != end);
 }
 
-void unmap_vm_area(struct vm_struct *area)
+void unmap_kernel_range(unsigned long addr, unsigned long size)
 {
 	pgd_t *pgd;
 	unsigned long next;
-	unsigned long addr = (unsigned long) area->addr;
-	unsigned long end = addr + area->size;
+	unsigned long start = addr;
+	unsigned long end = addr + size;
 
 	BUG_ON(addr >= end);
 	pgd = pgd_offset_k(addr);
@@ -84,7 +84,12 @@
 			continue;
 		vunmap_pud_range(pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
-	flush_tlb_kernel_range((unsigned long) area->addr, end);
+	flush_tlb_kernel_range(start, end);
+}
+
+static void unmap_vm_area(struct vm_struct *area)
+{
+	unmap_kernel_range((unsigned long)area->addr, area->size);
 }
 
 static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
@@ -427,11 +432,12 @@
 	area->nr_pages = nr_pages;
 	/* Please note that the recursion is strictly bounded. */
 	if (array_size > PAGE_SIZE) {
-		pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node);
+		pages = __vmalloc_node(array_size, gfp_mask | __GFP_ZERO,
+					PAGE_KERNEL, node);
 		area->flags |= VM_VPAGES;
 	} else {
 		pages = kmalloc_node(array_size,
-				(gfp_mask & GFP_LEVEL_MASK),
+				(gfp_mask & GFP_LEVEL_MASK) | __GFP_ZERO,
 				node);
 	}
 	area->pages = pages;
@@ -440,7 +446,6 @@
 		kfree(area);
 		return NULL;
 	}
-	memset(area->pages, 0, array_size);
 
 	for (i = 0; i < area->nr_pages; i++) {
 		if (node < 0)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 1be5a63..d419e10 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -66,17 +66,8 @@
 	int swappiness;
 
 	int all_unreclaimable;
-};
 
-/*
- * The list of shrinker callbacks used by to apply pressure to
- * ageable caches.
- */
-struct shrinker {
-	shrinker_t		shrinker;
-	struct list_head	list;
-	int			seeks;	/* seeks to recreate an obj */
-	long			nr;	/* objs pending delete */
+	int order;
 };
 
 #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
@@ -121,34 +112,25 @@
 /*
  * Add a shrinker callback to be called from the vm
  */
-struct shrinker *set_shrinker(int seeks, shrinker_t theshrinker)
+void register_shrinker(struct shrinker *shrinker)
 {
-        struct shrinker *shrinker;
-
-        shrinker = kmalloc(sizeof(*shrinker), GFP_KERNEL);
-        if (shrinker) {
-	        shrinker->shrinker = theshrinker;
-	        shrinker->seeks = seeks;
-	        shrinker->nr = 0;
-	        down_write(&shrinker_rwsem);
-	        list_add_tail(&shrinker->list, &shrinker_list);
-	        up_write(&shrinker_rwsem);
-	}
-	return shrinker;
+	shrinker->nr = 0;
+	down_write(&shrinker_rwsem);
+	list_add_tail(&shrinker->list, &shrinker_list);
+	up_write(&shrinker_rwsem);
 }
-EXPORT_SYMBOL(set_shrinker);
+EXPORT_SYMBOL(register_shrinker);
 
 /*
  * Remove one
  */
-void remove_shrinker(struct shrinker *shrinker)
+void unregister_shrinker(struct shrinker *shrinker)
 {
 	down_write(&shrinker_rwsem);
 	list_del(&shrinker->list);
 	up_write(&shrinker_rwsem);
-	kfree(shrinker);
 }
-EXPORT_SYMBOL(remove_shrinker);
+EXPORT_SYMBOL(unregister_shrinker);
 
 #define SHRINK_BATCH 128
 /*
@@ -185,7 +167,7 @@
 	list_for_each_entry(shrinker, &shrinker_list, list) {
 		unsigned long long delta;
 		unsigned long total_scan;
-		unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask);
+		unsigned long max_pass = (*shrinker->shrink)(0, gfp_mask);
 
 		delta = (4 * scanned) / shrinker->seeks;
 		delta *= max_pass;
@@ -213,8 +195,8 @@
 			int shrink_ret;
 			int nr_before;
 
-			nr_before = (*shrinker->shrinker)(0, gfp_mask);
-			shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
+			nr_before = (*shrinker->shrink)(0, gfp_mask);
+			shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask);
 			if (shrink_ret == -1)
 				break;
 			if (shrink_ret < nr_before)
@@ -481,7 +463,8 @@
 
 		referenced = page_referenced(page, 1);
 		/* In active use or really unfreeable?  Activate it. */
-		if (referenced && page_mapping_inuse(page))
+		if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
+					referenced && page_mapping_inuse(page))
 			goto activate_locked;
 
 #ifdef CONFIG_SWAP
@@ -514,7 +497,7 @@
 		}
 
 		if (PageDirty(page)) {
-			if (referenced)
+			if (sc->order <= PAGE_ALLOC_COSTLY_ORDER && referenced)
 				goto keep_locked;
 			if (!may_enter_fs)
 				goto keep_locked;
@@ -598,6 +581,51 @@
 	return nr_reclaimed;
 }
 
+/* LRU Isolation modes. */
+#define ISOLATE_INACTIVE 0	/* Isolate inactive pages. */
+#define ISOLATE_ACTIVE 1	/* Isolate active pages. */
+#define ISOLATE_BOTH 2		/* Isolate both active and inactive pages. */
+
+/*
+ * Attempt to remove the specified page from its LRU.  Only take this page
+ * if it is of the appropriate PageActive status.  Pages which are being
+ * freed elsewhere are also ignored.
+ *
+ * page:	page to consider
+ * mode:	one of the LRU isolation modes defined above
+ *
+ * returns 0 on success, -ve errno on failure.
+ */
+static int __isolate_lru_page(struct page *page, int mode)
+{
+	int ret = -EINVAL;
+
+	/* Only take pages on the LRU. */
+	if (!PageLRU(page))
+		return ret;
+
+	/*
+	 * When checking the active state, we need to be sure we are
+	 * dealing with comparible boolean values.  Take the logical not
+	 * of each.
+	 */
+	if (mode != ISOLATE_BOTH && (!PageActive(page) != !mode))
+		return ret;
+
+	ret = -EBUSY;
+	if (likely(get_page_unless_zero(page))) {
+		/*
+		 * Be careful not to clear PageLRU until after we're
+		 * sure the page is not being freed elsewhere -- the
+		 * page release code relies on it.
+		 */
+		ClearPageLRU(page);
+		ret = 0;
+	}
+
+	return ret;
+}
+
 /*
  * zone->lru_lock is heavily contended.  Some of the functions that
  * shrink the lists perform better by taking out a batch of pages
@@ -612,38 +640,90 @@
  * @src:	The LRU list to pull pages off.
  * @dst:	The temp list to put pages on to.
  * @scanned:	The number of pages that were scanned.
+ * @order:	The caller's attempted allocation order
+ * @mode:	One of the LRU isolation modes
  *
  * returns how many pages were moved onto *@dst.
  */
 static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
 		struct list_head *src, struct list_head *dst,
-		unsigned long *scanned)
+		unsigned long *scanned, int order, int mode)
 {
 	unsigned long nr_taken = 0;
-	struct page *page;
 	unsigned long scan;
 
 	for (scan = 0; scan < nr_to_scan && !list_empty(src); scan++) {
-		struct list_head *target;
+		struct page *page;
+		unsigned long pfn;
+		unsigned long end_pfn;
+		unsigned long page_pfn;
+		int zone_id;
+
 		page = lru_to_page(src);
 		prefetchw_prev_lru_page(page, src, flags);
 
 		VM_BUG_ON(!PageLRU(page));
 
-		list_del(&page->lru);
-		target = src;
-		if (likely(get_page_unless_zero(page))) {
-			/*
-			 * Be careful not to clear PageLRU until after we're
-			 * sure the page is not being freed elsewhere -- the
-			 * page release code relies on it.
-			 */
-			ClearPageLRU(page);
-			target = dst;
+		switch (__isolate_lru_page(page, mode)) {
+		case 0:
+			list_move(&page->lru, dst);
 			nr_taken++;
-		} /* else it is being freed elsewhere */
+			break;
 
-		list_add(&page->lru, target);
+		case -EBUSY:
+			/* else it is being freed elsewhere */
+			list_move(&page->lru, src);
+			continue;
+
+		default:
+			BUG();
+		}
+
+		if (!order)
+			continue;
+
+		/*
+		 * Attempt to take all pages in the order aligned region
+		 * surrounding the tag page.  Only take those pages of
+		 * the same active state as that tag page.  We may safely
+		 * round the target page pfn down to the requested order
+		 * as the mem_map is guarenteed valid out to MAX_ORDER,
+		 * where that page is in a different zone we will detect
+		 * it from its zone id and abort this block scan.
+		 */
+		zone_id = page_zone_id(page);
+		page_pfn = page_to_pfn(page);
+		pfn = page_pfn & ~((1 << order) - 1);
+		end_pfn = pfn + (1 << order);
+		for (; pfn < end_pfn; pfn++) {
+			struct page *cursor_page;
+
+			/* The target page is in the block, ignore it. */
+			if (unlikely(pfn == page_pfn))
+				continue;
+
+			/* Avoid holes within the zone. */
+			if (unlikely(!pfn_valid_within(pfn)))
+				break;
+
+			cursor_page = pfn_to_page(pfn);
+			/* Check that we have not crossed a zone boundary. */
+			if (unlikely(page_zone_id(cursor_page) != zone_id))
+				continue;
+			switch (__isolate_lru_page(cursor_page, mode)) {
+			case 0:
+				list_move(&cursor_page->lru, dst);
+				nr_taken++;
+				scan++;
+				break;
+
+			case -EBUSY:
+				/* else it is being freed elsewhere */
+				list_move(&cursor_page->lru, src);
+			default:
+				break;
+			}
+		}
 	}
 
 	*scanned = scan;
@@ -651,6 +731,24 @@
 }
 
 /*
+ * clear_active_flags() is a helper for shrink_active_list(), clearing
+ * any active bits from the pages in the list.
+ */
+static unsigned long clear_active_flags(struct list_head *page_list)
+{
+	int nr_active = 0;
+	struct page *page;
+
+	list_for_each_entry(page, page_list, lru)
+		if (PageActive(page)) {
+			ClearPageActive(page);
+			nr_active++;
+		}
+
+	return nr_active;
+}
+
+/*
  * shrink_inactive_list() is a helper for shrink_zone().  It returns the number
  * of reclaimed pages
  */
@@ -671,11 +769,18 @@
 		unsigned long nr_taken;
 		unsigned long nr_scan;
 		unsigned long nr_freed;
+		unsigned long nr_active;
 
 		nr_taken = isolate_lru_pages(sc->swap_cluster_max,
-					     &zone->inactive_list,
-					     &page_list, &nr_scan);
-		__mod_zone_page_state(zone, NR_INACTIVE, -nr_taken);
+			     &zone->inactive_list,
+			     &page_list, &nr_scan, sc->order,
+			     (sc->order > PAGE_ALLOC_COSTLY_ORDER)?
+					     ISOLATE_BOTH : ISOLATE_INACTIVE);
+		nr_active = clear_active_flags(&page_list);
+
+		__mod_zone_page_state(zone, NR_ACTIVE, -nr_active);
+		__mod_zone_page_state(zone, NR_INACTIVE,
+						-(nr_taken - nr_active));
 		zone->pages_scanned += nr_scan;
 		spin_unlock_irq(&zone->lru_lock);
 
@@ -820,7 +925,7 @@
 	lru_add_drain();
 	spin_lock_irq(&zone->lru_lock);
 	pgmoved = isolate_lru_pages(nr_pages, &zone->active_list,
-				    &l_hold, &pgscanned);
+			    &l_hold, &pgscanned, sc->order, ISOLATE_ACTIVE);
 	zone->pages_scanned += pgscanned;
 	__mod_zone_page_state(zone, NR_ACTIVE, -pgmoved);
 	spin_unlock_irq(&zone->lru_lock);
@@ -1011,7 +1116,7 @@
  * holds filesystem locks which prevent writeout this might not work, and the
  * allocation attempt will fail.
  */
-unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
+unsigned long try_to_free_pages(struct zone **zones, int order, gfp_t gfp_mask)
 {
 	int priority;
 	int ret = 0;
@@ -1026,6 +1131,7 @@
 		.swap_cluster_max = SWAP_CLUSTER_MAX,
 		.may_swap = 1,
 		.swappiness = vm_swappiness,
+		.order = order,
 	};
 
 	count_vm_event(ALLOCSTALL);
@@ -1131,6 +1237,7 @@
 		.may_swap = 1,
 		.swap_cluster_max = SWAP_CLUSTER_MAX,
 		.swappiness = vm_swappiness,
+		.order = order,
 	};
 	/*
 	 * temp_priority is used to remember the scanning priority at which
@@ -1314,6 +1421,7 @@
 	 * trying to free the first piece of memory in the first place).
 	 */
 	tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+	set_freezable();
 
 	order = 0;
 	for ( ; ; ) {
diff --git a/mm/vmstat.c b/mm/vmstat.c
index eceaf49..fadf791 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -472,7 +472,7 @@
 #endif
 
 #define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
-					TEXT_FOR_HIGHMEM(xx)
+					TEXT_FOR_HIGHMEM(xx) xx "_movable",
 
 static const char * const vmstat_text[] = {
 	/* Zoned VM counters */
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 1c8f4a0..1f78c3e 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -36,6 +36,7 @@
 #include <linux/signal.h>
 #include <linux/init.h>
 #include <linux/wait.h>
+#include <linux/freezer.h>
 #include <linux/errno.h>
 #include <linux/net.h>
 #include <net/sock.h>
@@ -474,7 +475,6 @@
 
 	daemonize("kbnepd %s", dev->name);
 	set_user_nice(current, -15);
-	current->flags |= PF_NOFREEZE;
 
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(sk->sk_sleep, &wait);
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 66bef1c..ca60a45 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
+#include <linux/freezer.h>
 #include <linux/skbuff.h>
 #include <linux/socket.h>
 #include <linux/ioctl.h>
@@ -287,7 +288,6 @@
 
 	daemonize("kcmtpd_ctr_%d", session->num);
 	set_user_nice(current, -15);
-	current->flags |= PF_NOFREEZE;
 
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(sk->sk_sleep, &wait);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 450eb02..64d89ca 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/freezer.h>
 #include <linux/fcntl.h>
 #include <linux/skbuff.h>
 #include <linux/socket.h>
@@ -547,7 +548,6 @@
 
 	daemonize("khidpd_%04x%04x", vendor, product);
 	set_user_nice(current, -15);
-	current->flags |= PF_NOFREEZE;
 
 	init_waitqueue_entry(&ctrl_wait, current);
 	init_waitqueue_entry(&intr_wait, current);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 52e04df..bb72207 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -33,6 +33,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/init.h>
+#include <linux/freezer.h>
 #include <linux/wait.h>
 #include <linux/device.h>
 #include <linux/net.h>
@@ -1940,7 +1941,6 @@
 
 	daemonize("krfcommd");
 	set_user_nice(current, -10);
-	current->flags |= PF_NOFREEZE;
 
 	BT_DBG("");
 
diff --git a/net/compat.c b/net/compat.c
index 9a0f5f2..d74d821 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -276,7 +276,8 @@
 		err = security_file_receive(fp[i]);
 		if (err)
 			break;
-		err = get_unused_fd();
+		err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags
+					  ? O_CLOEXEC : 0);
 		if (err < 0)
 			break;
 		new_fd = err;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index d1264e9..de1b26a 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -124,13 +124,6 @@
 	if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
 	    npinfo->poll_owner != smp_processor_id() &&
 	    spin_trylock(&npinfo->poll_lock)) {
-		/* When calling dev->poll from poll_napi, we may end up in
-		 * netif_rx_complete. However, only the CPU to which the
-		 * device was queued is allowed to remove it from poll_list.
-		 * Setting POLL_LIST_FROZEN tells netif_rx_complete
-		 * to leave the NAPI state alone.
-		 */
-		set_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
 		npinfo->rx_flags |= NETPOLL_RX_DROP;
 		atomic_inc(&trapped);
 
@@ -138,7 +131,6 @@
 
 		atomic_dec(&trapped);
 		npinfo->rx_flags &= ~NETPOLL_RX_DROP;
-		clear_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
 		spin_unlock(&npinfo->poll_lock);
 	}
 }
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 7521533..bca787f 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3465,6 +3465,8 @@
 
 	set_current_state(TASK_INTERRUPTIBLE);
 
+	set_freezable();
+
 	while (!kthread_should_stop()) {
 		pkt_dev = next_to_run(t);
 
diff --git a/net/core/scm.c b/net/core/scm.c
index 292ad8d..44c4ec2 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -228,7 +228,8 @@
 		err = security_file_receive(fp[i]);
 		if (err)
 			break;
-		err = get_unused_fd();
+		err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags
+					  ? O_CLOEXEC : 0);
 		if (err < 0)
 			break;
 		new_fd = err;
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index cc8110b..afb6c66 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -271,8 +271,11 @@
 			 */
 			dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
 			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
-			if (ieee80211softmac_start_scan(mac))
+			if (ieee80211softmac_start_scan(mac)) {
 				dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
+				mac->associnfo.associating = 0;
+				mac->associnfo.associated = 0;
+			}
 			goto out;
 		} else {
 			mac->associnfo.associating = 0;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 42f12bd..89dcc48 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -46,10 +46,6 @@
 #include "netlabel_cipso_v4.h"
 #include "netlabel_user.h"
 
-/* do not do any auditing if audit_enabled == 0, see kernel/audit.c for
- * details */
-extern int audit_enabled;
-
 /*
  * NetLabel NETLINK Setup Functions
  */
diff --git a/net/socket.c b/net/socket.c
index f453019..b711142 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1939,9 +1939,7 @@
 	total_len = err;
 
 	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-	if (MSG_CMSG_COMPAT & flags)
-		msg_sys.msg_flags = MSG_CMSG_COMPAT;
+	msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
 
 	if (sock->file->f_flags & O_NONBLOCK)
 		flags |= MSG_DONTWAIT;
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index aa55d0a..29a8ecc 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -543,17 +543,18 @@
 		test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
 }
 
-
-static struct shrinker *rpc_cred_shrinker;
+static struct shrinker rpc_cred_shrinker = {
+	.shrink = rpcauth_cache_shrinker,
+	.seeks = DEFAULT_SEEKS,
+};
 
 void __init rpcauth_init_module(void)
 {
 	rpc_init_authunix();
-	rpc_cred_shrinker = set_shrinker(DEFAULT_SEEKS, rpcauth_cache_shrinker);
+	register_shrinker(&rpc_cred_shrinker);
 }
 
 void __exit rpcauth_remove_module(void)
 {
-	if (rpc_cred_shrinker != NULL)
-		remove_shrinker(rpc_cred_shrinker);
+	unregister_shrinker(&rpc_cred_shrinker);
 }
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index baf4096d..abfda33 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -43,6 +43,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 71b9dae..9843eac 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -231,6 +231,7 @@
 static struct gss_api_mech gss_kerberos_mech = {
 	.gm_name	= "krb5",
 	.gm_owner	= THIS_MODULE,
+	.gm_oid		= {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
 	.gm_ops		= &gss_kerberos_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
 	.gm_pfs		= gss_kerberos_pfs,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 2687251..61801a0 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -194,6 +194,20 @@
 EXPORT_SYMBOL(gss_mech_get_by_pseudoflavor);
 
 u32
+gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service)
+{
+	int i;
+
+	for (i = 0; i < gm->gm_pf_num; i++) {
+		if (gm->gm_pfs[i].service == service) {
+			return gm->gm_pfs[i].pseudoflavor;
+		}
+	}
+	return RPC_AUTH_MAXFLAVOR; /* illegal value */
+}
+EXPORT_SYMBOL(gss_svc_to_pseudoflavor);
+
+u32
 gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
 {
 	int i;
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 577d590..5deb4b6 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -217,6 +217,7 @@
 static struct gss_api_mech gss_spkm3_mech = {
 	.gm_name	= "spkm3",
 	.gm_owner	= THIS_MODULE,
+	.gm_oid		= {7, "\053\006\001\005\005\001\003"},
 	.gm_ops		= &gss_spkm3_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_spkm3_pfs),
 	.gm_pfs		= gss_spkm3_pfs,
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index c094583..4906975 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -743,6 +743,15 @@
 
 static struct auth_ops svcauthops_gss;
 
+u32 svcauth_gss_flavor(struct auth_domain *dom)
+{
+	struct gss_domain *gd = container_of(dom, struct gss_domain, h);
+
+	return gd->pseudoflavor;
+}
+
+EXPORT_SYMBOL(svcauth_gss_flavor);
+
 int
 svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
 {
@@ -913,10 +922,23 @@
 	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
 	struct rsc *rsci = svcdata->rsci;
 	struct rpc_gss_wire_cred *gc = &svcdata->clcred;
+	int stat;
 
-	rqstp->rq_client = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
-	if (rqstp->rq_client == NULL)
+	/*
+	 * A gss export can be specified either by:
+	 * 	export	*(sec=krb5,rw)
+	 * or by
+	 * 	export gss/krb5(rw)
+	 * The latter is deprecated; but for backwards compatibility reasons
+	 * the nfsd code will still fall back on trying it if the former
+	 * doesn't work; so we try to make both available to nfsd, below.
+	 */
+	rqstp->rq_gssclient = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
+	if (rqstp->rq_gssclient == NULL)
 		return SVC_DENIED;
+	stat = svcauth_unix_set_client(rqstp);
+	if (stat == SVC_DROP)
+		return stat;
 	return SVC_OK;
 }
 
@@ -1088,7 +1110,6 @@
 			svc_putnl(resv, GSS_SEQ_WIN);
 			if (svc_safe_putnetobj(resv, &rsip->out_token))
 				goto drop;
-			rqstp->rq_client = NULL;
 		}
 		goto complete;
 	case RPC_GSS_PROC_DESTROY:
@@ -1131,6 +1152,8 @@
 		}
 		svcdata->rsci = rsci;
 		cache_get(&rsci->h);
+		rqstp->rq_flavor = gss_svc_to_pseudoflavor(
+					rsci->mechctx->mech_type, gc->gc_svc);
 		ret = SVC_OK;
 		goto out;
 	}
@@ -1317,6 +1340,9 @@
 	if (rqstp->rq_client)
 		auth_domain_put(rqstp->rq_client);
 	rqstp->rq_client = NULL;
+	if (rqstp->rq_gssclient)
+		auth_domain_put(rqstp->rq_gssclient);
+	rqstp->rq_gssclient = NULL;
 	if (rqstp->rq_cred.cr_group_info)
 		put_group_info(rqstp->rq_cred.cr_group_info);
 	rqstp->rq_cred.cr_group_info = NULL;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 07dcd20..4114794 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -5,6 +5,7 @@
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/svcauth.h>
+#include <linux/sunrpc/gss_api.h>
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/hash.h>
@@ -637,7 +638,7 @@
 	}
 }
 
-static int
+int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
 	struct sockaddr_in *sin = svc_addr_in(rqstp);
@@ -672,6 +673,8 @@
 	return SVC_OK;
 }
 
+EXPORT_SYMBOL(svcauth_unix_set_client);
+
 static int
 svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
@@ -707,6 +710,7 @@
 	svc_putnl(resv, RPC_AUTH_NULL);
 	svc_putnl(resv, 0);
 
+	rqstp->rq_flavor = RPC_AUTH_NULL;
 	return SVC_OK;
 }
 
@@ -784,6 +788,7 @@
 	svc_putnl(resv, RPC_AUTH_NULL);
 	svc_putnl(resv, 0);
 
+	rqstp->rq_flavor = RPC_AUTH_UNIX;
 	return SVC_OK;
 
 badcred:
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 277c326..25e20a2 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -9,7 +9,7 @@
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.06';
+my $V = '0.07';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -246,6 +246,19 @@
 	return $vet;
 }
 
+sub ERROR {
+	print "ERROR: $_[0]\n";
+	our $clean = 0;
+}
+sub WARN {
+	print "WARNING: $_[0]\n";
+	our $clean = 0;
+}
+sub CHK {
+	print "CHECK: $_[0]\n";
+	our $clean = 0;
+}
+
 sub process {
 	my $filename = shift;
 	my @lines = @_;
@@ -259,7 +272,7 @@
 	my $previndent=0;
 	my $stashindent=0;
 
-	my $clean = 1;
+	our $clean = 1;
 	my $signoff = 0;
 	my $is_patch = 0;
 
@@ -290,8 +303,11 @@
 					long\s+int|
 					long\s+long|
 					long\s+long\s+int|
+					u8|u16|u32|u64|
+					s8|s16|s32|s64|
 					struct\s+$Ident|
 					union\s+$Ident|
+					enum\s+$Ident|
 					${Ident}_t
 				)
 				(?:\s+$Sparse)*
@@ -304,6 +320,23 @@
 	my $Declare	= qr{(?:$Storage\s+)?$Type};
 	my $Attribute	= qr{__read_mostly|__init|__initdata};
 
+	# Pre-scan the patch looking for any __setup documentation.
+	my @setup_docs = ();
+	my $setup_docs = 0;
+	foreach my $line (@lines) {
+		if ($line=~/^\+\+\+\s+(\S+)/) {
+			$setup_docs = 0;
+			if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
+				$setup_docs = 1;
+			}
+			next;
+		}
+
+		if ($setup_docs && $line =~ /^\+/) {
+			push(@setup_docs, $line);
+		}
+	}
+
 	foreach my $line (@lines) {
 		$linenr++;
 
@@ -369,30 +402,42 @@
 		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
 
 		my $hereline = "$here\n$line\n";
-		my $herecurr = "$here\n$line\n\n";
-		my $hereprev = "$here\n$prevline\n$line\n\n";
+		my $herecurr = "$here\n$line\n";
+		my $hereprev = "$here\n$prevline\n$line\n";
 
 #check the patch for a signoff:
 		if ($line =~ /^\s*signed-off-by:/i) {
 			# This is a signoff, if ugly, so do not double report.
 			$signoff++;
 			if (!($line =~ /^\s*Signed-off-by:/)) {
-				print "Signed-off-by: is the preferred form\n";
-				print "$herecurr";
-				$clean = 0;
+				WARN("Signed-off-by: is the preferred form\n" .
+					$herecurr);
 			}
 			if ($line =~ /^\s*signed-off-by:\S/i) {
-				print "need space after Signed-off-by:\n";
-				print "$herecurr";
-				$clean = 0;
+				WARN("need space after Signed-off-by:\n" .
+					$herecurr);
 			}
 		}
 
 # Check for wrappage within a valid hunk of the file
 		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
-			print "patch seems to be corrupt (line wrapped?) [$realcnt]\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("patch seems to be corrupt (line wrapped?)\n" .
+				$herecurr);
+		}
+
+# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
+		if (($realfile =~ /^$/ || $line =~ /^\+/) &&
+		     !($line =~ m/^(
+				[\x09\x0A\x0D\x20-\x7E]              # ASCII
+				| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
+				|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
+				| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
+				|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
+				|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
+				| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
+				|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
+				)*$/x )) {
+			ERROR("Invalid UTF-8\n" . $herecurr);
 		}
 
 #ignore lines being removed
@@ -403,16 +448,12 @@
 
 #trailing whitespace
 		if ($line =~ /^\+.*\S\s+$/ || $line =~ /^\+\s+$/) {
-			my $herevet = "$here\n" . cat_vet($line) . "\n\n";
-			print "trailing whitespace\n";
-			print "$herevet";
-			$clean = 0;
+			my $herevet = "$here\n" . cat_vet($line) . "\n";
+			ERROR("trailing whitespace\n" . $herevet);
 		}
 #80 column limit
 		if ($line =~ /^\+/ && !($prevline=~/\/\*\*/) && $length > 80) {
-			print "line over 80 characters\n";
-			print "$herecurr";
-			$clean = 0;
+			WARN("line over 80 characters\n" . $herecurr);
 		}
 
 # check we are in a valid source file *.[hc] if not then ignore this hunk
@@ -421,10 +462,8 @@
 # at the beginning of a line any tabs must come first and anything
 # more than 8 must use tabs.
 		if ($line=~/^\+\s* \t\s*\S/ or $line=~/^\+\s*        \s*/) {
-			my $herevet = "$here\n" . cat_vet($line) . "\n\n";
-			print "use tabs not spaces\n";
-			print "$herevet";
-			$clean = 0;
+			my $herevet = "$here\n" . cat_vet($line) . "\n";
+			ERROR("use tabs not spaces\n" . $herevet);
 		}
 
 		#
@@ -463,9 +502,27 @@
 				}
 			}
 			if ($err ne '') {
-				print "switch and case should be at the same indent\n";
-				print "$here\n$line\n$err\n";
-				$clean = 0;
+				ERROR("switch and case should be at the same indent\n$hereline\n$err\n");
+			}
+		}
+
+# if/while/etc brace do not go on next line, unless defining a do while loop,
+# or if that brace on the next line is for something else
+		if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
+			my @ctx = ctx_statement($linenr, $realcnt);
+			my $ctx_ln = $linenr + $#ctx + 1;
+			my $ctx_cnt = $realcnt - $#ctx - 1;
+			my $ctx = join("\n", @ctx);
+
+			while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
+				$ctx_ln++;
+				$ctx_cnt--;
+			}
+			##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
+
+			if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
+				ERROR("That { should be on the previous line\n" .
+					"$here\n$ctx\n$lines[$ctx_ln - 1]");
 			}
 		}
 
@@ -474,9 +531,7 @@
 
 # TEST: allow direct testing of the type matcher.
 		if ($tst_type && $line =~ /^.$Declare$/) {
-			print "TEST: is type $Declare\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("TEST: is type $Declare\n" . $herecurr);
 			next;
 		}
 
@@ -488,9 +543,8 @@
 		if ($rawline =~ m{^.#\s*include\s+[<"](.*)[">]}) {
 			my $path = $1;
 			if ($path =~ m{//}) {
-				print "malformed #include filename\n";
-				print "$herecurr";
-				$clean = 0;
+				ERROR("malformed #include filename\n" .
+					$herecurr);
 			}
 			# Sanitise this special form of string.
 			$path = 'X' x length($path);
@@ -499,9 +553,7 @@
 
 # no C99 // comments
 		if ($line =~ m{//}) {
-			print "do not use C99 // comments\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("do not use C99 // comments\n" . $herecurr);
 		}
 		# Remove C99 comments.
 		$line =~ s@//.*@@;
@@ -514,49 +566,40 @@
 			   ($prevline !~ /^\+}/) &&
 			   ($prevline !~ /^ }/) &&
 			   ($prevline !~ /\s$name(?:\s+$Attribute)?\s*(?:;|=)/)) {
-				print "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n";
-				print "$herecurr";
-				$clean = 0;
+				WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
 			}
 		}
 
 # check for static initialisers.
 		if ($line=~/\s*static\s.*=\s+(0|NULL);/) {
-			print "do not initialise statics to 0 or NULL\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("do not initialise statics to 0 or NULL\n" .
+				$herecurr);
 		}
 
 # check for new typedefs, only function parameters and sparse annotations
 # make sense.
 		if ($line =~ /\btypedef\s/ &&
-		    $line !~ /\btypedef\s+$Type\s+\(\s*$Ident\s*\)\s*\(/ &&
+		    $line !~ /\btypedef\s+$Type\s+\(\s*\*$Ident\s*\)\s*\(/ &&
 		    $line !~ /\b__bitwise(?:__|)\b/) {
-			print "do not add new typedefs\n";
-			print "$herecurr";
-			$clean = 0;
+			WARN("do not add new typedefs\n" . $herecurr);
 		}
 
 # * goes on variable not on type
 		if ($line =~ m{\($NonptrType(\*+)(?:\s+const)?\)}) {
-			print "\"(foo$1)\" should be \"(foo $1)\"\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("\"(foo$1)\" should be \"(foo $1)\"\n" .
+				$herecurr);
 
 		} elsif ($line =~ m{\($NonptrType\s+(\*+)(?!\s+const)\s+\)}) {
-			print "\"(foo $1 )\" should be \"(foo $1)\"\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
+				$herecurr);
 
 		} elsif ($line =~ m{$NonptrType(\*+)(?:\s+const)?\s+[A-Za-z\d_]+}) {
-			print "\"foo$1 bar\" should be \"foo $1bar\"\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
+				$herecurr);
 
 		} elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+const)\s+[A-Za-z\d_]+}) {
-			print "\"foo $1 bar\" should be \"foo $1bar\"\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
+				$herecurr);
 		}
 
 # # no BUG() or BUG_ON()
@@ -585,9 +628,7 @@
 				}
 			}
 			if ($ok == 0) {
-				print "printk() should include KERN_ facility level\n";
-				print "$herecurr";
-				$clean = 0;
+				WARN("printk() should include KERN_ facility level\n" . $herecurr);
 			}
 		}
 
@@ -595,9 +636,7 @@
 # or if closed on same line
 		if (($line=~/$Type\s*[A-Za-z\d_]+\(.*\).* {/) and
 		    !($line=~/\#define.*do\s{/) and !($line=~/}/)) {
-			print "braces following function declarations go on the next line\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
 		}
 
 # Check operator spacing.
@@ -633,27 +672,27 @@
 				}
 
 				# Pick up the preceeding and succeeding characters.
-				my $ca = substr($opline, $off - 1, 1);
+				my $ca = substr($opline, 0, $off);
 				my $cc = '';
 				if (length($opline) >= ($off + length($elements[$n + 1]))) {
 					$cc = substr($opline, $off + length($elements[$n + 1]));
 				}
+				my $cb = "$ca$;$cc";
 
 				my $ctx = "${a}x${c}";
 
 				my $at = "(ctx:$ctx)";
 
 				my $ptr = (" " x $off) . "^";
-				my $hereptr = "$hereline$ptr\n\n";
+				my $hereptr = "$hereline$ptr\n";
 
 				##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
 
 				# ; should have either the end of line or a space or \ after it
 				if ($op eq ';') {
-					if ($ctx !~ /.x[WE]/ && $cc !~ /^\\/) {
-						print "need space after that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+					if ($ctx !~ /.x[WEB]/ && $cc !~ /^\\/ &&
+					    $cc !~ /^;/) {
+						ERROR("need space after that '$op' $at\n" . $hereptr);
 					}
 
 				# // is a comment
@@ -662,43 +701,31 @@
 				# -> should have no spaces
 				} elsif ($op eq '->') {
 					if ($ctx =~ /Wx.|.xW/) {
-						print "no spaces around that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("no spaces around that '$op' $at\n" . $hereptr);
 					}
 
 				# , must have a space on the right.
 				} elsif ($op eq ',') {
 					if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) {
-						print "need space after that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("need space after that '$op' $at\n" . $hereptr);
 					}
 
 				# unary ! and unary ~ are allowed no space on the right
 				} elsif ($op eq '!' or $op eq '~') {
 					if ($ctx !~ /[WOEB]x./) {
-						print "need space before that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("need space before that '$op' $at\n" . $hereptr);
 					}
 					if ($ctx =~ /.xW/) {
-						print "no space after that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("no space after that '$op' $at\n" . $hereptr);
 					}
 
 				# unary ++ and unary -- are allowed no space on one side.
 				} elsif ($op eq '++' or $op eq '--') {
 					if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) {
-						print "need space one side of that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("need space one side of that '$op' $at\n" . $hereptr);
 					}
 					if ($ctx =~ /Wx./ && $cc =~ /^;/) {
-						print "no space before that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("no space before that '$op' $at\n" . $hereptr);
 					}
 
 				# & is both unary and binary
@@ -715,9 +742,7 @@
 				#
 				} elsif ($op eq '&' or $op eq '-') {
 					if ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]/) {
-						print "need space before that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("need space before that '$op' $at\n" . $hereptr);
 					}
 
 				# * is the same as & only adding:
@@ -726,16 +751,9 @@
 				#	(foo **)
 				#
 				} elsif ($op eq '*') {
-					if ($ca eq '*') {
-						if ($cc =~ /^\s(?!\s*const)/) {
-							print "no space after that '$op' $at\n";
-							print "$hereptr";
-							$clean = 0;
-						}
-					} elsif ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB|BxB/) {
-						print "need space before that '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+					if ($ca !~ /$Type$/ && $cb !~ /(\*$;|$;\*)/ &&
+					    $ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB|BxB/) {
+						ERROR("need space before that '$op' $at\n" . $hereptr);
 					}
 
 				# << and >> may either have or not have spaces both sides
@@ -743,58 +761,51 @@
 					 $op eq '^' or $op eq '|')
 				{
 					if ($ctx !~ /VxV|WxW|VxE|WxE/) {
-						print "need consistent spacing around '$op' $at\n";
-						print "$hereptr";
-						$clean = 0;
+						ERROR("need consistent spacing around '$op' $at\n" .
+							$hereptr);
 					}
 
 				# All the others need spaces both sides.
 				} elsif ($ctx !~ /[EW]x[WE]/) {
-					print "need spaces around that '$op' $at\n";
-					print "$hereptr";
-					$clean = 0;
+					ERROR("need spaces around that '$op' $at\n" . $hereptr);
 				}
 				$off += length($elements[$n + 1]);
 			}
 		}
 
 #need space before brace following if, while, etc
-		if ($line=~/\(.*\){/) {
-			print "need a space before the brace\n";
-			print "$herecurr";
-			$clean = 0;
+		if ($line =~ /\(.*\){/ || $line =~ /do{/) {
+			ERROR("need a space before the open brace '{'\n" . $herecurr);
+		}
+
+# closing brace should have a space following it when it has anything
+# on the line
+		if ($line =~ /}(?!(?:,|;|\)))\S/) {
+			ERROR("need a space after that close brace '}'\n" . $herecurr);
 		}
 
 #goto labels aren't indented, allow a single space however
 		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
 		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
-			print "labels should not be indented\n";
-			print "$herecurr";
-			$clean = 0;
+			WARN("labels should not be indented\n" . $herecurr);
 		}
 
 # Need a space before open parenthesis after if, while etc
 		if ($line=~/\b(if|while|for|switch)\(/) {
-			print "need a space before the open parenthesis\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("need a space before the open parenthesis '('\n" . $herecurr);
 		}
 
 # Check for illegal assignment in if conditional.
 		if ($line=~/\bif\s*\(.*[^<>!=]=[^=].*\)/) {
 			#next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
-			print "do not use assignment in if condition\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("do not use assignment in if condition\n" . $herecurr);
 		}
 
 		# Check for }<nl>else {, these must be at the same
 		# indent level to be relevant to each other.
 		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
 						$previndent == $indent) {
-			print "else should follow close brace\n";
-			print "$hereprev";
-			$clean = 0;
+			ERROR("else should follow close brace '}'\n" . $hereprev);
 		}
 
 #studly caps, commented out until figure out how to distinguish between use of existing and adding new
@@ -806,57 +817,22 @@
 
 #no spaces allowed after \ in define
 		if ($line=~/\#define.*\\\s$/) {
-			print("Whitepspace after \\ makes next lines useless\n");
-			print "$herecurr";
-			$clean = 0;
+			WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
 		}
 
 #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
 		if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
 			my $checkfile = "include/linux/$1.h";
 			if (-f $checkfile) {
-				print "Use #include <linux/$1.h> instead of <asm/$1.h>\n";
-				print $herecurr;
-				$clean = 0;
-			}
-		}
-
-# if/while/etc brace do not go on next line, unless defining a do while loop,
-# or if that brace on the next line is for something else
-		if ($prevline=~/\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/) {
-			my @opened = $prevline=~/\(/g;
-			my @closed = $prevline=~/\)/g;
-			my $nr_line = $linenr;
-			my $remaining = $realcnt - 1;
-			my $next_line = $line;
-			my $extra_lines = 0;
-			my $display_segment = $prevline;
-
-			while ($remaining > 0 && scalar @opened > scalar @closed) {
-				$prevline .= $next_line;
-				$display_segment .= "\n" . $next_line;
-				$next_line = $lines[$nr_line];
-				$nr_line++;
-				$remaining--;
-
-				@opened = $prevline=~/\(/g;
-				@closed = $prevline=~/\)/g;
-			}
-
-			if (($prevline=~/\b(?:(if|while|for|switch)\s*\(.*\)|do|else)\s*$/) and ($next_line=~/{/) and
-			   !($next_line=~/\b(?:if|while|for|switch|do|else)\b/) and !($next_line=~/\#define.*do.*while/)) {
-				print "That { should be on the previous line\n";
-				print "$here\n$display_segment\n$next_line\n\n";
-				$clean = 0;
+				CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
+					$herecurr);
 			}
 		}
 
 # if and else should not have general statements after it
 		if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ &&
-		    $1 !~ /^\s*(?:\sif|{|$)/) {
-			print "trailing statements should be on next line\n";
-			print "$herecurr";
-			$clean = 0;
+		    $1 !~ /^\s*(?:\sif|{|\\|$)/) {
+			ERROR("trailing statements should be on next line\n" . $herecurr);
 		}
 
 # multi-statement macros should be enclosed in a do while loop, grab the
@@ -877,49 +853,49 @@
 				$ln--;
 				$cnt++;
 			}
-			my $ctx = join('', ctx_statement($ln, $cnt));
+			my @ctx = ctx_statement($ln, $cnt);
+			my $ctx_ln = $ln + $#ctx + 1;
+			my $ctx = join("\n", @ctx);
+
+			# Pull in any empty extension lines.
+			while ($ctx =~ /\\$/ &&
+			       $lines[$ctx_ln - 1] =~ /^.\s*(?:\\)?$/) {
+				$ctx .= $lines[$ctx_ln - 1];
+				$ctx_ln++;
+			}
 
 			if ($ctx =~ /\\$/) {
 				if ($ctx =~ /;/) {
-					print "Macros with multiple statements should be enclosed in a do - while loop\n";
+					ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
 				} else {
-					print "Macros with complex values should be enclosed in parenthesis\n";
+					ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
 				}
-				print "$hereprev";
-				$clean = 0;
 			}
 		}
 
 # don't include deprecated include files (uses RAW line)
 		for my $inc (@dep_includes) {
 			if ($rawline =~ m@\#\s*include\s*\<$inc>@) {
-				print "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n";
-				print "$herecurr";
-				$clean = 0;
+				ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
 			}
 		}
 
 # don't use deprecated functions
 		for my $func (@dep_functions) {
 			if ($line =~ /\b$func\b/) {
-				print "Don't use $func(): see Documentation/feature-removal-schedule.txt\n";
-				print "$herecurr";
-				$clean = 0;
+				ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
 			}
 		}
 
 # no volatiles please
 		if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
-			print "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n";
-			print "$herecurr";
-			$clean = 0;
+			WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
 		}
 
 # warn about #if 0
 		if ($line =~ /^.#\s*if\s+0\b/) {
-			print "#if 0 -- if this code redundant remove it\n";
-			print "$herecurr";
-			$clean = 0;
+			CHK("if this code is redundant consider removing it\n" .
+				$herecurr);
 		}
 
 # warn about #ifdefs in C files
@@ -933,41 +909,47 @@
 		if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
 			my $which = $1;
 			if (!ctx_has_comment($first_line, $linenr)) {
-				print "$1 definition without comment\n";
-				print "$herecurr";
-				$clean = 0;
+				CHK("$1 definition without comment\n" . $herecurr);
 			}
 		}
 # check for memory barriers without a comment.
 		if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
 			if (!ctx_has_comment($first_line, $linenr)) {
-				print "memory barrier without comment\n";
-				print "$herecurr";
-				$clean = 0;
+				CHK("memory barrier without comment\n" . $herecurr);
 			}
 		}
 # check of hardware specific defines
 		if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@) {
-			print "architecture specific defines should be avoided\n";
-			print "$herecurr";
-			$clean = 0;
+			CHK("architecture specific defines should be avoided\n" .  $herecurr);
 		}
 
+# check the location of the inline attribute, that it is between
+# storage class and type.
 		if ($line =~ /$Type\s+(?:inline|__always_inline)\b/ ||
 		    $line =~ /\b(?:inline|always_inline)\s+$Storage/) {
-			print "inline keyword should sit between storage class and type\n";
-			print "$herecurr";
-			$clean = 0;
+			ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
+		}
+
+# check for new externs in .c files.
+		if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) {
+			WARN("externs should be avoided in .c files\n" .  $herecurr);
+		}
+
+# checks for new __setup's
+		if ($rawline =~ /\b__setup\("([^"]*)"/) {
+			my $name = $1;
+
+			if (!grep(/$name/, @setup_docs)) {
+				CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
+			}
 		}
 	}
 
 	if ($chk_patch && !$is_patch) {
-		$clean = 0;
-		print "Does not appear to be a unified-diff format patch\n";
+		ERROR("Does not appear to be a unified-diff format patch\n");
 	}
 	if ($is_patch && $chk_signoff && $signoff == 0) {
-		$clean = 0;
-		print "Missing Signed-off-by: line(s)\n";
+		ERROR("Missing Signed-off-by: line(s)\n");
 	}
 
 	if ($clean == 1 && $quiet == 0) {
diff --git a/scripts/decodecode b/scripts/decodecode
new file mode 100644
index 0000000..1e1a8f6
--- /dev/null
+++ b/scripts/decodecode
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Disassemble the Code: line in Linux oopses
+# usage: decodecode < oops.file
+#
+# options: set env. variable AFLAGS=options to pass options to "as";
+# e.g., to decode an i386 oops on an x86_64 system, use:
+# AFLAGS=--32 decodecode < 386.oops
+
+T=`mktemp`
+code=
+
+while read i ; do
+
+case "$i" in
+*Code:*)
+	code=$i
+	;;
+esac
+
+done
+
+if [ -z "$code" ]; then
+	exit
+fi
+
+echo $code
+code=`echo $code | sed -e 's/.*Code: //'`
+
+marker=`expr index "$code" "\<"`
+if [ $marker -eq 0 ]; then
+	marker=`expr index "$code" "\("`
+fi
+
+if [ $marker -ne 0 ]; then
+	beforemark=`echo "$code" | cut -c-$((${marker} - 1))`
+	echo -n "	.byte 0x" > $T.s
+	echo $beforemark | sed -e 's/ /,0x/g' >> $T.s
+	as $AFLAGS -o $T.o $T.s
+	objdump -S $T.o
+	rm $T.o $T.s
+
+# and fix code at-and-after marker
+	code=`echo "$code" | cut -c$((${marker} + 1))-`
+fi
+
+code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g'`
+echo -n "	.byte 0x" > $T.s
+echo $code >> $T.s
+as $AFLAGS -o $T.o $T.s
+objdump -S $T.o
+rm $T.o $T.s
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 8b809b2..10b0066 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -31,7 +31,7 @@
 #include <string.h>
 #include <ctype.h>
 
-#define KSYM_NAME_LEN		127
+#define KSYM_NAME_LEN		128
 
 
 struct sym_entry {
@@ -254,7 +254,7 @@
 	unsigned int i, k, off;
 	unsigned int best_idx[256];
 	unsigned int *markers;
-	char buf[KSYM_NAME_LEN+1];
+	char buf[KSYM_NAME_LEN];
 
 	printf("#include <asm/types.h>\n");
 	printf("#if BITS_PER_LONG == 64\n");
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index ccfe875..eddc7b4 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -110,6 +110,8 @@
 	{ AUDIT_DEL_RULE,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
 	{ AUDIT_SIGNAL_INFO,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
+	{ AUDIT_TTY_GET,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
+	{ AUDIT_TTY_SET,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 };
 
 
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 4b30ae6..866d4de 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,35 +5,6 @@
 #
 # Prompt user for primary drivers.
 
-config OSS_OBSOLETE
-	bool "Obsolete OSS drivers"
-	depends on SOUND_PRIME
-	help
-	  This option enables support for obsolete OSS drivers that
-	  are scheduled for removal in the near future.
-
-	  Please contact Adrian Bunk <bunk@stusta.de> if you had to
-	  say Y here because your hardware is not properly supported
-	  by ALSA.
-
-	  If unsure, say N.
-
-config SOUND_BT878
-	tristate "BT878 audio dma"
-	depends on SOUND_PRIME && PCI && OSS_OBSOLETE
-	---help---
-	  Audio DMA support for bt878 based grabber boards.  As you might have
-	  already noticed, bt878 is listed with two functions in /proc/pci.
-	  Function 0 does the video stuff (bt848 compatible), function 1 does
-	  the same for audio data.  This is a driver for the audio part of
-	  the chip.  If you say 'Y' here you get a oss-compatible dsp device
-	  where you can record from.  If you want just watch TV you probably
-	  don't need this driver as most TV cards handle sound with a short
-	  cable from the TV card to your sound card's line-in.
-
-	  To compile this driver as a module, choose M here: the module will
-	  be called btaudio.
-
 config SOUND_BCM_CS4297A
 	tristate "Crystal Sound CS4297a (for Swarm)"
 	depends on SOUND_PRIME && SIBYTE_SWARM
@@ -44,13 +15,6 @@
 	  note that CONFIG_KGDB should not be enabled at the same
 	  time, since it also attempts to use this UART port.
 
-config SOUND_ICH
-	tristate "Intel ICH (i8xx) audio support"
-	depends on SOUND_PRIME && PCI && OSS_OBSOLETE
-	help
-	  Support for integral audio in Intel's I/O Controller Hub (ICH)
-	  chipset, as used on the 810/820/840 motherboards.
-
 config SOUND_VWSND
 	tristate "SGI Visual Workstation Sound"
 	depends on SOUND_PRIME && X86_VISWS
@@ -346,29 +310,9 @@
 	  and Pinnacle). Larger values reduce the chance of data overruns at
 	  the expense of overall latency. If unsure, use the default.
 
-config SOUND_VIA82CXXX
-	tristate "VIA 82C686 Audio Codec"
-	depends on SOUND_PRIME && PCI && OSS_OBSOLETE
-	help
-	  Say Y here to include support for the audio codec found on VIA
-	  82Cxxx-based chips. Typically these are built into a motherboard.
-
-	  DO NOT select Sound Blaster or Adlib with this driver, unless
-	  you have a Sound Blaster or Adlib card in addition to your VIA
-	  audio chip.
-
-config MIDI_VIA82CXXX
-	bool "VIA 82C686 MIDI"
-	depends on SOUND_VIA82CXXX && ISA_DMA_API
-	help
-	  Answer Y to use the MIDI interface of the Via686. You may need to
-	  enable this in the BIOS before it will work. This is for connection
-	  to external MIDI hardware, and is not required for software playback
-	  of MIDI files.
-
 config SOUND_OSS
 	tristate "OSS sound modules"
-	depends on SOUND_PRIME && ISA_DMA_API
+	depends on SOUND_PRIME && ISA_DMA_API && VIRT_TO_BUS
 	help
 	  OSS is the Open Sound System suite of sound card drivers.  They make
 	  sound programming easier since they provide a common API.  Say Y or
@@ -400,23 +344,10 @@
 
 	  Say Y unless you have 16MB or more RAM or a PCI sound card.
 
-config SOUND_CS4232
-	tristate "Crystal CS4232 based (PnP) cards"
-	depends on SOUND_OSS && OSS_OBSOLETE
-	help
-	  Say Y here if you have a card based on the Crystal CS4232 chip set,
-	  which uses its own Plug and Play protocol.
-
-	  If you compile the driver into the kernel, you have to add
-	  "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
-	  command line.
-
-	  See <file:Documentation/sound/oss/CS4232> for more information on
-	  configuring this card.
-
 config SOUND_SSCAPE
 	tristate "Ensoniq SoundScape support"
 	depends on SOUND_OSS
+	depends on VIRT_TO_BUS
 	help
 	  Answer Y if you have a sound card based on the Ensoniq SoundScape
 	  chipset. Such cards are being manufactured at least by Ensoniq, Spea
@@ -719,13 +650,6 @@
 	  Say Y here to include support for the Rockwell WaveArtist sound
 	  system.  This driver is mainly for the NetWinder.
 
-config SOUND_TVMIXER
-	tristate "TV card (bt848) mixer support"
-	depends on SOUND_PRIME && I2C && VIDEO_V4L1 && OSS_OBSOLETE
-	help
-	  Support for audio mixer facilities on the BT848 TV frame-grabber
-	  card.
-
 config SOUND_KAHLUA
 	tristate "XpressAudio Sound Blaster emulation"
 	depends on SOUND_SB
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 2489bd6..7a2f9ae 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -18,20 +18,15 @@
 obj-$(CONFIG_SOUND_SSCAPE)	+= sscape.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o uart401.o
 obj-$(CONFIG_SOUND_MSS)		+= ad1848.o
-obj-$(CONFIG_SOUND_OPL3SA2)	+= opl3sa2.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_PAS)		+= pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)		+= sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_KAHLUA)	+= kahlua.o
 obj-$(CONFIG_SOUND_MPU401)	+= mpu401.o
 obj-$(CONFIG_SOUND_UART6850)	+= uart6850.o
-obj-$(CONFIG_SOUND_ADLIB)	+= adlib_card.o opl3.o
 obj-$(CONFIG_SOUND_YM3812)	+= opl3.o
 obj-$(CONFIG_SOUND_VMIDI)	+= v_midi.o
 obj-$(CONFIG_SOUND_VIDC)	+= vidc_mod.o
 obj-$(CONFIG_SOUND_WAVEARTIST)	+= waveartist.o
-obj-$(CONFIG_SOUND_AD1816)	+= ad1816.o
-obj-$(CONFIG_SOUND_AD1889)	+= ad1889.o ac97_codec.o
-obj-$(CONFIG_SOUND_ACI_MIXER)	+= aci.o
 
 obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
 ifeq ($(CONFIG_MIDI_VIA82CXXX),y)
@@ -40,24 +35,16 @@
 obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)	+= msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_VWSND)	+= vwsnd.o
-obj-$(CONFIG_SOUND_NM256)	+= nm256_audio.o ac97.o
 obj-$(CONFIG_SOUND_ICH)		+= i810_audio.o ac97_codec.o
 obj-$(CONFIG_SOUND_ES1371)	+= es1371.o ac97_codec.o
 obj-$(CONFIG_SOUND_VRC5477)	+= nec_vrc5477.o ac97_codec.o
 obj-$(CONFIG_SOUND_AU1550_AC97)	+= au1550_ac97.o ac97_codec.o
-obj-$(CONFIG_SOUND_FUSION)	+= cs46xx.o ac97_codec.o
 obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o
-obj-$(CONFIG_SOUND_EMU10K1)	+= ac97_codec.o
 obj-$(CONFIG_SOUND_BCM_CS4297A)	+= swarm_cs4297a.o
 obj-$(CONFIG_SOUND_BT878)	+= btaudio.o
 
 obj-$(CONFIG_SOUND_WM97XX)	+= ac97_plugin_wm97xx.o
 
-ifeq ($(CONFIG_MIDI_EMU10K1),y)
-  obj-$(CONFIG_SOUND_EMU10K1)	+= sound.o
-endif
-
-obj-$(CONFIG_SOUND_EMU10K1)	+= emu10k1/
 obj-$(CONFIG_DMASOUND)		+= dmasound/
 
 # Declare multi-part drivers.
diff --git a/sound/oss/ac97.c b/sound/oss/ac97.c
deleted file mode 100644
index 72cf4ed..0000000
--- a/sound/oss/ac97.c
+++ /dev/null
@@ -1,432 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include "ac97.h"
-
-/* Flag for mono controls. */
-#define MO 0
-/* And for stereo. */
-#define ST 1
-
-/* Whether or not the bits in the channel are inverted. */
-#define INV 1
-#define NINV 0
-
-static struct ac97_chn_desc {
-    int ac97_regnum;
-    int oss_channel;
-    int maxval;
-    int is_stereo;
-    int oss_mask;
-    int recordNum;
-    u16 regmask;
-    int is_inverted;
-} mixerRegs[] = {
-    { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME,   0x3f, ST, SOUND_MASK_VOLUME,   5, 0x0000, INV  },
-    { AC97_MASTER_VOL_MONO,   SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000, INV  },
-    { AC97_MASTER_TONE,       SOUND_MIXER_TREBLE,   0x0f, MO, SOUND_MASK_TREBLE,  -1, 0x00ff, INV  },
-    { AC97_MASTER_TONE,       SOUND_MIXER_BASS,     0x0f, MO, SOUND_MASK_BASS,    -1, 0xff00, INV  },
-    { AC97_PCBEEP_VOL,        SOUND_MIXER_SPEAKER,  0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e, INV  },
-    { AC97_PHONE_VOL,         SOUND_MIXER_PHONEIN,  0x1f, MO, SOUND_MASK_PHONEIN,  7, 0x0000, INV  },
-    { AC97_MIC_VOL,           SOUND_MIXER_MIC,      0x1f, MO, SOUND_MASK_MIC,      0, 0x0000, INV  },
-    { AC97_LINEIN_VOL,        SOUND_MIXER_LINE,     0x1f, ST, SOUND_MASK_LINE,     4, 0x0000, INV  },
-    { AC97_CD_VOL,            SOUND_MIXER_CD,       0x1f, ST, SOUND_MASK_CD,       1, 0x0000, INV  },
-    { AC97_VIDEO_VOL,         SOUND_MIXER_VIDEO,    0x1f, ST, SOUND_MASK_VIDEO,    2, 0x0000, INV  },
-    { AC97_AUX_VOL,           SOUND_MIXER_LINE1,    0x1f, ST, SOUND_MASK_LINE1,	   3, 0x0000, INV  },
-    { AC97_PCMOUT_VOL,        SOUND_MIXER_PCM,      0x1f, ST, SOUND_MASK_PCM,     -1, 0x0000, INV  },
-    { AC97_RECORD_GAIN,       SOUND_MIXER_IGAIN,    0x0f, ST, SOUND_MASK_IGAIN,   -1, 0x0000, NINV },
-    { -1,		      -1,		    0xff, 0,  0,                  -1, 0x0000, 0    },
-};
-
-static struct ac97_chn_desc *
-ac97_find_chndesc (struct ac97_hwint *dev, int oss_channel)
-{
-    int x;
-
-    for (x = 0; mixerRegs[x].oss_channel != -1; x++) {
-	if (mixerRegs[x].oss_channel == oss_channel)
-	    return mixerRegs + x;
-    }
-
-    return NULL;
-}
-
-static inline int
-ac97_is_valid_channel (struct ac97_hwint *dev, struct ac97_chn_desc *chn)
-{
-    return (dev->last_written_mixer_values[chn->ac97_regnum / 2]
-	    != AC97_REG_UNSUPPORTED);
-}
-
-int
-ac97_init (struct ac97_hwint *dev)
-{
-    int x;
-    int reg0;
-
-    /* Clear out the arrays of cached values. */
-    for (x = 0; x < AC97_REG_CNT; x++)
-	dev->last_written_mixer_values[x] = AC97_REGVAL_UNKNOWN;
-
-    for (x = 0; x < SOUND_MIXER_NRDEVICES; x++)
-	dev->last_written_OSS_values[x] = AC97_REGVAL_UNKNOWN;
-
-    /* Clear the device masks.  */
-    dev->mixer_devmask = 0;
-    dev->mixer_stereomask = 0;
-    dev->mixer_recmask = 0;
-
-    /* ??? Do a "standard reset" via register 0? */
-
-    /* Hardware-dependent reset.  */
-    if (dev->reset_device (dev))
-	return -1;
-
-    /* Check the mixer device capabilities.  */
-    reg0 = dev->read_reg (dev, AC97_RESET);
-
-    if (reg0 < 0)
-	return -1;
-
-    /* Check for support for treble/bass controls.  */
-    if (! (reg0 & 4)) {
-	dev->last_written_mixer_values[AC97_MASTER_TONE / 2] 
-	    = AC97_REG_UNSUPPORTED;
-    }
-
-    /* ??? There may be other tests here? */
-
-    /* Fill in the device masks.  */
-    for (x = 0; mixerRegs[x].ac97_regnum != -1; x++) {
-	if (ac97_is_valid_channel (dev, mixerRegs + x)) {
-	    dev->mixer_devmask |= mixerRegs[x].oss_mask;
-
-	    if (mixerRegs[x].is_stereo)
-		dev->mixer_stereomask |= mixerRegs[x].oss_mask;
-
-	    if (mixerRegs[x].recordNum != -1)
-		dev->mixer_recmask |= mixerRegs[x].oss_mask;
-	}
-    }
-
-    return 0;
-}
-
-/* Return the contents of register REG; use the cache if the value in it
-   is valid.  Returns a negative error code on failure. */
-static int
-ac97_get_register (struct ac97_hwint *dev, u8 reg) 
-{
-    if (reg > 127 || (reg & 1))
-	return -EINVAL;
-
-    /* See if it's in the cache, or if it's just plain invalid.  */
-    switch (dev->last_written_mixer_values[reg / 2]) {
-    case AC97_REG_UNSUPPORTED:
-	return -EINVAL;
-	break;
-    case AC97_REGVAL_UNKNOWN:
-	dev->last_written_mixer_values[reg / 2] = dev->read_reg (dev, reg);
-	break;
-    default:
-	break;
-    }
-    return dev->last_written_mixer_values[reg / 2];
-}
-
-/* Write VALUE to AC97 register REG, and cache its value in the last-written
-   cache.  Returns a negative error code on failure, or 0 on success. */
-int
-ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value)
-{
-    if (reg > 127 || (reg & 1))
-	return -EINVAL;
-
-    if (dev->last_written_mixer_values[reg / 2] == AC97_REG_UNSUPPORTED)
-	return -EINVAL;
-    else {
-	int res = dev->write_reg (dev, reg, value);
-	if (res >= 0) {
-	    dev->last_written_mixer_values[reg / 2] = value;
-	    return 0;
-	}
-	else
-	    return res;
-    }
-}
-
-/* Scale VALUE (a value fro 0 to MAXVAL) to a value from 0-100.  If
-   IS_STEREO is set, VALUE is a stereo value; the left channel value
-   is in the lower 8 bits, and the right channel value is in the upper
-   8 bits.
-
-   A negative error code is returned on failure, or the unsigned
-   scaled value on success.  */
-
-static int
-ac97_scale_to_oss_val (int value, int maxval, int is_stereo, int inv)
-{
-    /* Muted?  */
-    if (value & AC97_MUTE)
-	return 0;
-
-    if (is_stereo)
-	return (ac97_scale_to_oss_val (value & 255, maxval, 0, inv) << 8)
-	| (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
-    else {
-	int i;
-	
-	/* Inverted. */
-	if (inv)
-	    value = maxval - value;
-
-	i = (value * 100 + (maxval / 2)) / maxval;
-	if (i > 100)
-	     i = 100;
-	if (i < 0)
-	    i = 0;
-	return i;
-    }
-}
-
-static int
-ac97_scale_from_oss_val (int value, int maxval, int is_stereo, int inv)
-{
-    if (is_stereo)
-	return (ac97_scale_from_oss_val (value & 255, maxval, 0, inv) << 8)
-	| (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
-    else {
-	int i = ((value & 255) * maxval + 50) / 100;
-	if (inv)
-	    i = maxval - i;
-	if (i < 0)
-	    i = 0;
-	if (i > maxval)
-	    i = maxval;
-	return i;
-    }
-}
-
-static int
-ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, u16 oss_value)
-{
-    int scaled_value;
-    struct ac97_chn_desc *channel = ac97_find_chndesc (dev, oss_channel);
-    int result;
-
-    if (channel == NULL)
-	return -ENODEV;
-    if (! ac97_is_valid_channel (dev, channel))
-	return -ENODEV;
-    scaled_value = ac97_scale_from_oss_val (oss_value, channel->maxval,
-					    channel->is_stereo, 
-					    channel->is_inverted);
-    if (scaled_value < 0)
-	return scaled_value;
-
-    if (channel->regmask != 0) {
-	int mv;
-
-	int oldval = ac97_get_register (dev, channel->ac97_regnum);
-	if (oldval < 0)
-	    return oldval;
-
-	for (mv = channel->regmask; ! (mv & 1); mv >>= 1)
-	    scaled_value <<= 1;
-
-	scaled_value &= channel->regmask;
-	scaled_value |= (oldval & ~channel->regmask);
-    }
-    result = ac97_put_register (dev, channel->ac97_regnum, scaled_value);
-    if (result == 0)
-	dev->last_written_OSS_values[oss_channel] = oss_value;
-    return result;
-}
-
-static int
-ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel)
-{
-    struct ac97_chn_desc *channel = ac97_find_chndesc (dev, oss_channel);
-    int regval;
-
-    if (channel == NULL)
-	return -ENODEV;
-
-    if (! ac97_is_valid_channel (dev, channel))
-	return -ENODEV;
-
-    regval = ac97_get_register (dev, channel->ac97_regnum);
-
-    if (regval < 0)
-	return regval;
-
-    if (channel->regmask != 0) {
-	int mv;
-
-	regval &= channel->regmask;
-
-	for (mv = channel->regmask; ! (mv & 1); mv >>= 1)
-	    regval >>= 1;
-    }
-    return ac97_scale_to_oss_val (regval, channel->maxval,
-				  channel->is_stereo, 
-				  channel->is_inverted);
-}
-
-static int
-ac97_get_recmask (struct ac97_hwint *dev)
-{
-    int recReg = ac97_get_register (dev, AC97_RECORD_SELECT);
-
-    if (recReg < 0)
-	return recReg;
-    else {
-	int x;
-	for (x = 0; mixerRegs[x].ac97_regnum >= 0; x++) {
-	    if (mixerRegs[x].recordNum == (recReg & 7))
-		return mixerRegs[x].oss_mask;
-	}
-	return -ENODEV;
-    }
-}
-
-static int
-ac97_set_recmask (struct ac97_hwint *dev, int oss_recmask)
-{
-    int x;
-
-    if (oss_recmask == 0)
-	oss_recmask = SOUND_MIXER_MIC;
-
-    for (x = 0; mixerRegs[x].ac97_regnum >= 0; x++) { 
-	if ((mixerRegs[x].recordNum >= 0)
-	     && (oss_recmask & mixerRegs[x].oss_mask))
-	    break;
-    }
-    if (mixerRegs[x].ac97_regnum < 0)
-	return -ENODEV;
-    else {
-	int regval = (mixerRegs[x].recordNum << 8) | mixerRegs[x].recordNum;
-	int res = ac97_put_register (dev, AC97_RECORD_SELECT, regval);
-	if (res == 0)
-	    return ac97_get_recmask (dev);
-	else
-	    return res;
-    }
-}
-
-/* Set the mixer DEV to the list of values in VALUE_LIST.  Return 0 on
-   success, or a negative error code.  */
-int
-ac97_set_values (struct ac97_hwint *dev, 
-		 struct ac97_mixer_value_list *value_list)
-{
-    int x;
-
-    for (x = 0; value_list[x].oss_channel != -1; x++) {
-	int chnum = value_list[x].oss_channel;
-	struct ac97_chn_desc *chent = ac97_find_chndesc (dev, chnum);
-	if (chent != NULL) {
-	    u16 val;
-	    int res;
-
-	    if (chent->is_stereo)
-		val = (value_list[x].value.stereo.right << 8) 
-		      | value_list[x].value.stereo.left;
-	    else {
-		/* We do this so the returned value looks OK in the
-		   mixer app.  It's not necessary otherwise.  */
-		val = (value_list[x].value.mono << 8) 
-		      | value_list[x].value.mono;
-	    }
-	    res = ac97_set_mixer (dev, chnum, val);
-	    if (res < 0)
-		return res;
-	}
-	else
-	    return -ENODEV;
-    }
-    return 0;
-}
-
-int
-ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, void __user *arg)
-{
-    int ret;
-
-    switch (cmd) {
-    case SOUND_MIXER_READ_RECSRC:
-	ret = ac97_get_recmask (dev);
-	break;
-
-    case SOUND_MIXER_WRITE_RECSRC:
-	{
-	    if (get_user (ret, (int __user *) arg))
-		ret = -EFAULT;
-	    else
-		ret = ac97_set_recmask (dev, ret);
-	}
-	break;
-
-    case SOUND_MIXER_READ_CAPS:
-	ret = SOUND_CAP_EXCL_INPUT;
-	break;
-
-    case SOUND_MIXER_READ_DEVMASK:
-	ret = dev->mixer_devmask;
-	break;
-
-    case SOUND_MIXER_READ_RECMASK:
-	ret = dev->mixer_recmask;
-	break;
-
-    case SOUND_MIXER_READ_STEREODEVS:
-	ret = dev->mixer_stereomask;
-	break;
-
-    default:
-	/* Read or write request. */
-	ret = -EINVAL;
-	if (_IOC_TYPE (cmd) == 'M') {
-	    int dir = _SIOC_DIR (cmd);
-	    int channel = _IOC_NR (cmd);
-
-	    if (channel >= 0 && channel < SOUND_MIXER_NRDEVICES) {
-		ret = 0;
-		if (dir & _SIOC_WRITE) {
-		    int val;
-		    if (get_user (val, (int __user *) arg) == 0)
-			ret = ac97_set_mixer (dev, channel, val);
-		    else
-			ret = -EFAULT;
-		}
-		if (ret >= 0 && (dir & _SIOC_READ)) {
-		    if (dev->last_written_OSS_values[channel]
-			== AC97_REGVAL_UNKNOWN)
-			dev->last_written_OSS_values[channel]
-			    = ac97_get_mixer_scaled (dev, channel);
-		    ret = dev->last_written_OSS_values[channel];
-		}
-	    }
-	}
-	break;
-    }
-
-    if (ret < 0)
-	return ret;
-    else
-	return put_user(ret, (int __user *) arg);
-}
-
-EXPORT_SYMBOL(ac97_init);
-EXPORT_SYMBOL(ac97_set_values);
-EXPORT_SYMBOL(ac97_put_register);
-EXPORT_SYMBOL(ac97_mixer_ioctl);
-MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/ac97.h b/sound/oss/ac97.h
deleted file mode 100644
index 01837a9..0000000
--- a/sound/oss/ac97.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * ac97.h 
- * 
- * definitions for the AC97, Intel's Audio Codec 97 Spec
- * also includes support for a generic AC97 interface
- */
-
-#ifndef _AC97_H_
-#define _AC97_H_
-#include "sound_config.h"
-#include "sound_calls.h"
-
-#define  AC97_RESET              0x0000      //
-#define  AC97_MASTER_VOL_STEREO  0x0002      // Line Out
-#define  AC97_HEADPHONE_VOL      0x0004      // 
-#define  AC97_MASTER_VOL_MONO    0x0006      // TAD Output
-#define  AC97_MASTER_TONE        0x0008      //
-#define  AC97_PCBEEP_VOL         0x000a      // none
-#define  AC97_PHONE_VOL          0x000c      // TAD Input (mono)
-#define  AC97_MIC_VOL            0x000e      // MIC Input (mono)
-#define  AC97_LINEIN_VOL         0x0010      // Line Input (stereo)
-#define  AC97_CD_VOL             0x0012      // CD Input (stereo)
-#define  AC97_VIDEO_VOL          0x0014      // none
-#define  AC97_AUX_VOL            0x0016      // Aux Input (stereo)
-#define  AC97_PCMOUT_VOL         0x0018      // Wave Output (stereo)
-#define  AC97_RECORD_SELECT      0x001a      //
-#define  AC97_RECORD_GAIN        0x001c
-#define  AC97_RECORD_GAIN_MIC    0x001e
-#define  AC97_GENERAL_PURPOSE    0x0020
-#define  AC97_3D_CONTROL         0x0022
-#define  AC97_MODEM_RATE         0x0024
-#define  AC97_POWER_CONTROL      0x0026
-
-/* registers 0x0028 - 0x0058 are reserved */
-
-/* AC'97 2.0 */
-#define AC97_EXTENDED_ID	0x0028	/* Extended Audio ID */
-#define AC97_EXTENDED_STATUS	0x002A	/* Extended Audio Status */
-#define AC97_PCM_FRONT_DAC_RATE 0x002C  /* PCM Front DAC Rate */
-#define AC97_PCM_SURR_DAC_RATE  0x002E  /* PCM Surround DAC Rate */
-#define AC97_PCM_LFE_DAC_RATE   0x0030  /* PCM LFE DAC Rate */
-#define AC97_PCM_LR_ADC_RATE	0x0032	/* PCM LR DAC Rate */
-#define AC97_PCM_MIC_ADC_RATE   0x0034  /* PCM MIC ADC Rate */
-#define AC97_CENTER_LFE_MASTER  0x0036  /* Center + LFE Master Volume */
-#define AC97_SURROUND_MASTER    0x0038  /* Surround (Rear) Master Volume */
-#define AC97_RESERVED_3A	0x003A	/* Reserved */
-/* range 0x3c-0x58 - MODEM */
-
-/* registers 0x005a - 0x007a are vendor reserved */
-
-#define  AC97_VENDOR_ID1         0x007c
-#define  AC97_VENDOR_ID2         0x007e
-
-/* volume control bit defines */
-
-#define AC97_MUTE                0x8000
-#define AC97_MICBOOST            0x0040
-#define AC97_LEFTVOL             0x3f00
-#define AC97_RIGHTVOL            0x003f
-
-/* record mux defines */
-
-#define AC97_RECMUX_MIC          0x0000
-#define AC97_RECMUX_CD           0x0101
-#define AC97_RECMUX_VIDEO        0x0202      /* not used */
-#define AC97_RECMUX_AUX          0x0303      
-#define AC97_RECMUX_LINE         0x0404      
-#define AC97_RECMUX_STEREO_MIX   0x0505
-#define AC97_RECMUX_MONO_MIX     0x0606
-#define AC97_RECMUX_PHONE        0x0707
-
-
-/* general purpose register bit defines */
-
-#define AC97_GP_LPBK             0x0080      /* Loopback mode */
-#define AC97_GP_MS               0x0100      /* Mic Select 0=Mic1, 1=Mic2 */
-#define AC97_GP_MIX              0x0200      /* Mono output select 0=Mix, 1=Mic */
-#define AC97_GP_RLBK             0x0400      /* Remote Loopback - Modem line codec */
-#define AC97_GP_LLBK             0x0800      /* Local Loopback - Modem Line codec */
-#define AC97_GP_LD               0x1000      /* Loudness 1=on */
-#define AC97_GP_3D               0x2000      /* 3D Enhancement 1=on */
-#define AC97_GP_ST               0x4000      /* Stereo Enhancement 1=on */
-#define AC97_GP_POP              0x8000      /* Pcm Out Path, 0=pre 3D, 1=post 3D */
-
-
-/* powerdown control and status bit defines */
-
-/* status */
-#define AC97_PWR_MDM             0x0010      /* Modem section ready */
-#define AC97_PWR_REF             0x0008      /* Vref nominal */
-#define AC97_PWR_ANL             0x0004      /* Analog section ready */
-#define AC97_PWR_DAC             0x0002      /* DAC section ready */
-#define AC97_PWR_ADC             0x0001      /* ADC section ready */
-
-/* control */
-#define AC97_PWR_PR0             0x0100      /* ADC and Mux powerdown */
-#define AC97_PWR_PR1             0x0200      /* DAC powerdown */
-#define AC97_PWR_PR2             0x0400      /* Output mixer powerdown (Vref on) */
-#define AC97_PWR_PR3             0x0800      /* Output mixer powerdown (Vref off) */
-#define AC97_PWR_PR4             0x1000      /* AC-link powerdown */
-#define AC97_PWR_PR5             0x2000      /* Internal Clk disable */
-#define AC97_PWR_PR6             0x4000      /* HP amp powerdown */
-#define AC97_PWR_PR7             0x8000      /* Modem off - if supported */
-
-/* useful power states */
-#define AC97_PWR_D0              0x0000      /* everything on */
-#define AC97_PWR_D1              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4
-#define AC97_PWR_D2              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
-#define AC97_PWR_D3              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
-#define AC97_PWR_ANLOFF          AC97_PWR_PR2|AC97_PWR_PR3  /* analog section off */
-
-/* Total number of defined registers.  */
-#define AC97_REG_CNT 64
-
-/* Generic AC97 mixer interface. */
-
-/* Structure describing access to the hardware. */
-struct ac97_hwint
-{
-    /* Perform any hardware-specific reset and initialization.  Returns
-     0 on success, or a negative error code.  */
-    int (*reset_device) (struct ac97_hwint *dev);
-
-    /* Returns the contents of the specified register REG.  The caller
-       should check to see if the desired contents are available in
-       the cache first, if applicable. Returns a positive unsigned value
-       representing the contents of the register, or a negative error
-       code.  */
-    int (*read_reg) (struct ac97_hwint *dev, u8 reg);
-
-    /* Writes VALUE to register REG.  Returns 0 on success, or a
-       negative error code.  */
-    int (*write_reg) (struct ac97_hwint *dev, u8 reg, u16 value);
-
-    /* Hardware-specific information. */
-    void *driver_private;
-
-    /* Three OSS masks. */
-    int mixer_devmask;
-    int mixer_stereomask;
-    int mixer_recmask;
-
-    /* The mixer cache. The indices correspond to the AC97 hardware register
-       number / 2, since the register numbers are always an even number.
-
-       Unknown values are set to -1; unsupported registers contain a
-       -2.  */
-    int last_written_mixer_values[AC97_REG_CNT];
-
-    /* A cache of values written via OSS; we need these so we can return
-       the values originally written by the user.
-
-       Why the original user values?  Because the real-world hardware
-       has less precision, and some existing applications assume that
-       they will get back the exact value that they wrote (aumix).
-
-       A -1 value indicates that no value has been written to this mixer
-       channel via OSS.  */
-    int last_written_OSS_values[SOUND_MIXER_NRDEVICES];
-};
-
-/* Values stored in the register cache.  */
-#define AC97_REGVAL_UNKNOWN -1
-#define AC97_REG_UNSUPPORTED -2
-
-struct ac97_mixer_value_list
-{
-    /* Mixer channel to set.  List is terminated by a value of -1.  */
-    int oss_channel;
-    /* The scaled value to set it to; values generally range from 0-100. */
-    union {
-	struct {
-	    u8 left, right;
-	} stereo;
-	u8 mono;
-    } value;
-};
-
-/* Initialize the ac97 mixer by resetting it.  */
-extern int ac97_init (struct ac97_hwint *dev);
-
-/* Sets the mixer DEV to the values in VALUE_LIST.  Returns 0 on success,
-   or a negative error code.  */
-extern int ac97_set_values (struct ac97_hwint *dev,
-			    struct ac97_mixer_value_list *value_list);
-
-/* Writes the specified VALUE to the AC97 register REG in the mixer.
-   Takes care of setting the last-written cache as well.  */
-extern int ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value);
-
-/* Default ioctl. */
-extern int ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd,
-			     void __user * arg);
-
-#endif
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/aci.c b/sound/oss/aci.c
deleted file mode 100644
index 3bfac37..0000000
--- a/sound/oss/aci.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Audio Command Interface (ACI) driver (sound/aci.c)
- *
- * ACI is a protocol used to communicate with the microcontroller on
- * some sound cards produced by miro, e.g. the miroSOUND PCM12 and
- * PCM20. The ACI has been developed for miro by Norberto Pellicci
- * <pellicci@home.com>. Special thanks to both him and miro for
- * providing the ACI specification.
- *
- * The main function of the ACI is to control the mixer and to get a
- * product identification. On the PCM20, ACI also controls the radio
- * tuner on this card, this is supported in the Video for Linux 
- * miropcm20 driver.
- * -
- * This is a fullfeatured implementation. Unsupported features
- * are bugs... (:
- *
- * It is not longer necessary to load the mad16 module first. The
- * user is currently responsible to set the mad16 mixer correctly.
- *
- * To toggle the solo mode for full duplex operation just use the OSS
- * record switch for the pcm ('wave') controller.           Robert
- * -
- *
- * Revision history:
- *
- *   1995-11-10  Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
- *        First version written.
- *   1995-12-31  Markus Kuhn
- *        Second revision, general code cleanup.
- *   1996-05-16	 Hannu Savolainen
- *	  Integrated with other parts of the driver.
- *   1996-05-28  Markus Kuhn
- *        Initialize CS4231A mixer, make ACI first mixer,
- *        use new private mixer API for solo mode.
- *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- *	  Small modification to export ACI functions and 
- *	  complete modularisation.
- *   2000-06-20  Robert Siemer <Robert.Siemer@gmx.de>
- *        Don't initialize the CS4231A mixer anymore, so the code is
- *        working again, and other small changes to fit in todays
- *        kernels.
- *   2000-08-26  Robert Siemer
- *        Clean up and rewrite for 2.4.x. Maybe it's SMP safe now... (:
- *        ioctl bugfix, and integration of solo-mode into OSS-API,
- *        added (OSS-limited) equalizer support, return value bugfix,
- *        changed param aci_reset to reset, new params: ide, wss.
- *   2001-04-20  Robert Siemer
- *        even more cleanups...
- *   2001-10-08  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- *   	  Get rid of check_region, .bss optimizations, use set_current_state
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h> 
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include "sound_config.h"
-
-int aci_port;	/* as determined by bit 4 in the OPTi 929 MC4 register */
-static int aci_idcode[2];	/* manufacturer and product ID */
-int aci_version;	/* ACI firmware version	*/
-
-EXPORT_SYMBOL(aci_port);
-EXPORT_SYMBOL(aci_version);
-
-#include "aci.h"
-
-
-static int aci_solo;	/* status bit of the card that can't be		*
-			 * checked with ACI versions prior to 0xb0	*/
-static int aci_amp;   /* status bit for power-amp/line-out level
-			   but I have no docs about what is what... */
-static int aci_micpreamp=3; /* microphone preamp-level that can't be    *
-			 * checked with ACI versions prior to 0xb0	*/
-
-static int mixer_device;
-static struct mutex aci_mutex;
-
-#ifdef MODULE
-static int reset;
-module_param(reset, bool, 0);
-MODULE_PARM_DESC(reset,"When set to 1, reset aci mixer.");
-#else
-static int reset = 1;
-#endif
-
-static int ide=-1;
-module_param(ide, int, 0);
-MODULE_PARM_DESC(ide,"1 enable, 0 disable ide-port - untested"
-		 " default: do nothing");
-static int wss=-1;
-module_param(wss, int, 0);
-MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested"
-		 " default: do nothing; for PCM1-pro only");
-
-#ifdef DEBUG
-static void print_bits(unsigned char c)
-{
-	int j;
-	printk(KERN_DEBUG "aci: ");
-
-	for (j=7; j>=0; j--) {
-		printk("%d", (c >> j) & 0x1);
-	}
-
-	printk("\n");
-}
-#endif
-
-/*
- * This busy wait code normally requires less than 15 loops and
- * practically always less than 100 loops on my i486/DX2 66 MHz.
- *
- * Warning: Waiting on the general status flag after reseting the MUTE
- * function can take a VERY long time, because the PCM12 does some kind
- * of fade-in effect. For this reason, access to the MUTE function has
- * not been implemented at all.
- *
- * - The OSS interface has no mute option. It takes about 3 seconds to
- * fade-in on my PCM20. busy_wait() handles it great now...     Robert
- */
-
-static int busy_wait(void)
-{
-	#define MINTIME 500
-	long timeout;
-	unsigned char byte;
-
-	for (timeout = 1; timeout <= MINTIME+30; timeout++) {
-		if (((byte=inb(BUSY_REGISTER)) & 1) == 0) {
-			if (timeout >= MINTIME)
-				printk(KERN_DEBUG "aci: Got READYFLAG in round %ld.\n", timeout-MINTIME);
-			return byte;
-		}
-		if (timeout >= MINTIME) {
-			long out=10*HZ;
-			switch (timeout-MINTIME) {
-			case 0 ... 9:
-				out /= 10;
-			case 10 ... 19:
-				out /= 10;
-			case 20 ... 30:
-				out /= 10;
-			default:
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout(out);
-				break;
-			}
-		}
-	}
-	printk(KERN_WARNING "aci: busy_wait() time out.\n");
-	return -EBUSY;
-}
-
-/* The four ACI command types are fucked up. [-:
- * implied is: 1w      - special case for INIT
- * write   is: 2w1r
- * read    is: x(1w1r) where x is 1 or 2 (1 CHECK_SIG, 1 CHECK_STER,
- *                                        1 VERSION, 2 IDCODE)
- *  the command is only in the first write, rest is protocol overhead
- *
- * indexed is technically a write and used for STATUS
- * and the special case for TUNE is: 3w1r
- * 
- * Here the new general sheme: TUNE --> aci_rw_cmd(x,  y,  z)
- *                indexed and write --> aci_rw_cmd(x,  y, -1)
- *           implied and read (x=1) --> aci_rw_cmd(x, -1, -1)
- *
- * Read (x>=2) is not implemented (only used during initialization).
- * Use aci_idcode[2] and aci_version...                    Robert
- */
-
-/* Some notes for error detection: theoretically it is possible.
- * But it doubles the I/O-traffic from ww(r) to wwwrw(r) in the normal 
- * case and doesn't seem to be designed for that...        Robert
- */
-
-static inline int aci_rawwrite(unsigned char byte)
-{
-	if (busy_wait() >= 0) {
-#ifdef DEBUG
-		printk(KERN_DEBUG "aci_rawwrite(%d)\n", byte);
-#endif
-		outb(byte, COMMAND_REGISTER);
-		return 0;
-	} else
-		return -EBUSY;
-}
-
-static inline int aci_rawread(void)
-{
-	unsigned char byte;
-
-	if (busy_wait() >= 0) {
-		byte=inb(STATUS_REGISTER);
-#ifdef DEBUG
-		printk(KERN_DEBUG "%d = aci_rawread()\n", byte);
-#endif
-		return byte;
-	} else
-		return -EBUSY;
-}
-
-
-int aci_rw_cmd(int write1, int write2, int write3)
-{
-	int write[] = {write1, write2, write3};
-	int read = -EINTR, i;
-
-	if (mutex_lock_interruptible(&aci_mutex))
-		goto out;
-
-	for (i=0; i<3; i++) {
-		if (write[i]< 0 || write[i] > 255)
-			break;
-		else {
-			read = aci_rawwrite(write[i]);
-			if (read < 0)
-				goto out_up;
-		}
-		
-	}
-	
-	read = aci_rawread();
-out_up:	mutex_unlock(&aci_mutex);
-out:	return read;
-}
-
-EXPORT_SYMBOL(aci_rw_cmd);
-
-static int setvolume(int __user *arg, 
-		     unsigned char left_index, unsigned char right_index)
-{
-	int vol, ret, uservol, buf;
-
-	__get_user(uservol, arg);
-
-	/* left channel */
-	vol = uservol & 0xff;
-	if (vol > 100)
-		vol = 100;
-	vol = SCALE(100, 0x20, vol);
-	if ((buf=aci_write_cmd(left_index, 0x20 - vol))<0)
-		return buf;
-	ret = SCALE(0x20, 100, vol);
-
-
-	/* right channel */
-	vol = (uservol >> 8) & 0xff;
-	if (vol > 100)
-		vol = 100;
-	vol = SCALE(100, 0x20, vol);
-	if ((buf=aci_write_cmd(right_index, 0x20 - vol))<0)
-		return buf;
-	ret |= SCALE(0x20, 100, vol) << 8;
- 
-	__put_user(ret, arg);
-
-	return 0;
-}
-
-static int getvolume(int __user *arg,
-		     unsigned char left_index, unsigned char right_index)
-{
-	int vol;
-	int buf;
-
-	/* left channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
-		return buf;
-	vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
-	
-	/* right channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
-		return buf;
-	vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
-
-	__put_user(vol, arg);
-
-	return 0;
-}
-
-
-/* The equalizer is somewhat strange on the ACI. From -12dB to +12dB
- * write:  0xff..down.to..0x80==0x00..up.to..0x7f
- */
-
-static inline unsigned int eq_oss2aci(unsigned int vol)
-{
-	int boost=0;
-	unsigned int ret;
-
-	if (vol > 100)
-		vol = 100;
-	if (vol > 50) {
-		vol -= 51;
-		boost=1;
-	}
-	if (boost)
-		ret=SCALE(49, 0x7e, vol)+1;
-	else
-		ret=0xff - SCALE(50, 0x7f, vol);
-	return ret;
-}
-
-static inline unsigned int eq_aci2oss(unsigned int vol)
-{
-	if (vol < 0x80)
-		return SCALE(0x7f, 50, vol) + 50;
-	else
-		return SCALE(0x7f, 50, 0xff-vol);
-}
-
-
-static int setequalizer(int __user *arg, 
-			unsigned char left_index, unsigned char right_index)
-{
-	int buf;
-	unsigned int vol;
-
-	__get_user(vol, arg);
-
-	/* left channel */
-	if ((buf=aci_write_cmd(left_index, eq_oss2aci(vol & 0xff)))<0)
-		return buf;
-
-	/* right channel */
-	if ((buf=aci_write_cmd(right_index, eq_oss2aci((vol>>8) & 0xff)))<0)
-		return buf;
-
-	/* the ACI equalizer is more precise */
-	return 0;
-}
-
-static int getequalizer(int __user *arg,
-			unsigned char left_index, unsigned char right_index)
-{
-	int buf;
-	unsigned int vol;
-
-	/* left channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
-		return buf;
-	vol = eq_aci2oss(buf);
-	
-	/* right channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
-		return buf;
-	vol |= eq_aci2oss(buf) << 8;
-
-	__put_user(vol, arg);
-
-	return 0;
-}
-
-static int aci_mixer_ioctl (int dev, unsigned int cmd, void __user * arg)
-{
-	int vol, buf;
-	int __user *p = arg;
-
-	switch (cmd) {
-	case SOUND_MIXER_WRITE_VOLUME:
-		return setvolume(p, 0x01, 0x00);
-	case SOUND_MIXER_WRITE_CD:
-		return setvolume(p, 0x3c, 0x34);
-	case SOUND_MIXER_WRITE_MIC:
-		return setvolume(p, 0x38, 0x30);
-	case SOUND_MIXER_WRITE_LINE:
-		return setvolume(p, 0x39, 0x31);
-	case SOUND_MIXER_WRITE_SYNTH:
-		return setvolume(p, 0x3b, 0x33);
-	case SOUND_MIXER_WRITE_PCM:
-		return setvolume(p, 0x3a, 0x32);
-	case MIXER_WRITE(SOUND_MIXER_RADIO): /* fall through */
-	case SOUND_MIXER_WRITE_LINE1:  /* AUX1 or radio */
-		return setvolume(p, 0x3d, 0x35);
-	case SOUND_MIXER_WRITE_LINE2:  /* AUX2 */
-		return setvolume(p, 0x3e, 0x36);
-	case SOUND_MIXER_WRITE_BASS:   /* set band one and two */
-		if (aci_idcode[1]=='C') {
-			if ((buf=setequalizer(p, 0x48, 0x40)) || 
-			    (buf=setequalizer(p, 0x49, 0x41)));
-			return buf;
-		}
-		break;
-	case SOUND_MIXER_WRITE_TREBLE: /* set band six and seven */
-		if (aci_idcode[1]=='C') {
-			if ((buf=setequalizer(p, 0x4d, 0x45)) || 
-			    (buf=setequalizer(p, 0x4e, 0x46)));
-			return buf;
-		}
-		break;
-	case SOUND_MIXER_WRITE_IGAIN:  /* MIC pre-amp */
-		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
-			__get_user(vol, p);
-			vol = vol & 0xff;
-			if (vol > 100)
-				vol = 100;
-			vol = SCALE(100, 3, vol);
-			if ((buf=aci_write_cmd(ACI_WRITE_IGAIN, vol))<0)
-				return buf;
-			aci_micpreamp = vol;
-			vol = SCALE(3, 100, vol);
-			vol |= (vol << 8);
-			__put_user(vol, p);
-			return 0;
-		}
-		break;
-	case SOUND_MIXER_WRITE_OGAIN:  /* Power-amp/line-out level */
-		if (aci_idcode[1]=='A' || aci_idcode[1]=='B') {
-			__get_user(buf, p);
-			buf = buf & 0xff;
-			if (buf > 50)
-				vol = 1;
-			else
-				vol = 0;
-			if ((buf=aci_write_cmd(ACI_SET_POWERAMP, vol))<0)
-				return buf;
-			aci_amp = vol;
-			if (aci_amp)
-				buf = (100 || 100<<8);
-			else
-				buf = 0;
-			__put_user(buf, p);
-			return 0;
-		}
-		break;
-	case SOUND_MIXER_WRITE_RECSRC:
-		/* handle solo mode control */
-		__get_user(buf, p);
-		/* unset solo when RECSRC for PCM is requested */
-		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
-			vol = !(buf & SOUND_MASK_PCM);
-			if ((buf=aci_write_cmd(ACI_SET_SOLOMODE, vol))<0)
-				return buf;
-			aci_solo = vol;
-		}
-		buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
-		       SOUND_MASK_SYNTH| SOUND_MASK_LINE2);
-		if (aci_idcode[1] == 'C') /* PCM20 radio */
-			buf |= SOUND_MASK_RADIO;
-		else
-			buf |= SOUND_MASK_LINE1;
-		if (!aci_solo)
-			buf |= SOUND_MASK_PCM;
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_DEVMASK:
-		buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
-		       SOUND_MASK_MIC    | SOUND_MASK_LINE  |
-		       SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
-		       SOUND_MASK_LINE2);
-		switch (aci_idcode[1]) {
-		case 'C': /* PCM20 radio */
-			buf |= (SOUND_MASK_RADIO | SOUND_MASK_IGAIN |
-				SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
-			break;
-		case 'B': /* PCM12 */
-			buf |= (SOUND_MASK_LINE1 | SOUND_MASK_IGAIN |
-				SOUND_MASK_OGAIN);
-			break;
-		case 'A': /* PCM1-pro */
-			buf |= (SOUND_MASK_LINE1 | SOUND_MASK_OGAIN);
-			break;
-		default:
-			buf |= SOUND_MASK_LINE1;
-		}
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_STEREODEVS:
-		buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
-		       SOUND_MASK_MIC    | SOUND_MASK_LINE  |
-		       SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
-		       SOUND_MASK_LINE2);
-		switch (aci_idcode[1]) {
-		case 'C': /* PCM20 radio */
-			buf |= (SOUND_MASK_RADIO |
-				SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
-			break;
-		default:
-			buf |= SOUND_MASK_LINE1;
-		}
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_RECMASK:
-		buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
-		       SOUND_MASK_SYNTH| SOUND_MASK_LINE2| SOUND_MASK_PCM);
-		if (aci_idcode[1] == 'C') /* PCM20 radio */
-			buf |= SOUND_MASK_RADIO;
-		else
-			buf |= SOUND_MASK_LINE1;
-
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_RECSRC:
-		buf = (SOUND_MASK_CD    | SOUND_MASK_MIC   | SOUND_MASK_LINE  |
-		       SOUND_MASK_SYNTH | SOUND_MASK_LINE2);
-		/* do we need aci_solo or can I get it from the ACI? */
-		switch (aci_idcode[1]) {
-		case 'B': /* PCM12 */
-		case 'C': /* PCM20 radio */
-			if (aci_version >= 0xb0) {
-				if ((vol=aci_rw_cmd(ACI_STATUS,
-						    ACI_S_GENERAL, -1))<0)
-					return vol;
-				if (vol & 0x20)
-					buf |= SOUND_MASK_PCM;
-			}
-			else
-				if (!aci_solo)
-					buf |= SOUND_MASK_PCM;
-			break;
-		default:
-			buf |= SOUND_MASK_PCM;
-		}
-		if (aci_idcode[1] == 'C') /* PCM20 radio */
-			buf |= SOUND_MASK_RADIO;
-		else
-			buf |= SOUND_MASK_LINE1;
-
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_CAPS:
-		__put_user(0, p);
-		return 0;
-	case SOUND_MIXER_READ_VOLUME:
-		return getvolume(p, 0x04, 0x03);
-	case SOUND_MIXER_READ_CD:
-		return getvolume(p, 0x0a, 0x09);
-	case SOUND_MIXER_READ_MIC:
-		return getvolume(p, 0x06, 0x05);
-	case SOUND_MIXER_READ_LINE:
-		return getvolume(p, 0x08, 0x07);
-	case SOUND_MIXER_READ_SYNTH:
-		return getvolume(p, 0x0c, 0x0b);
-	case SOUND_MIXER_READ_PCM:
-		return getvolume(p, 0x0e, 0x0d);
-	case MIXER_READ(SOUND_MIXER_RADIO): /* fall through */
-	case SOUND_MIXER_READ_LINE1:  /* AUX1 */
-		return getvolume(p, 0x11, 0x10);
-	case SOUND_MIXER_READ_LINE2:  /* AUX2 */
-		return getvolume(p, 0x13, 0x12);
-	case SOUND_MIXER_READ_BASS:   /* get band one */
-		if (aci_idcode[1]=='C') {
-			return getequalizer(p, 0x23, 0x22);
-		}
-		break;
-	case SOUND_MIXER_READ_TREBLE: /* get band seven */
-		if (aci_idcode[1]=='C') {
-			return getequalizer(p, 0x2f, 0x2e);
-		}
-		break;
-	case SOUND_MIXER_READ_IGAIN:  /* MIC pre-amp */
-		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
-			/* aci_micpreamp or ACI? */
-			if (aci_version >= 0xb0) {
-				if ((buf=aci_indexed_cmd(ACI_STATUS,
-							 ACI_S_READ_IGAIN))<0)
-					return buf;
-			}
-			else
-				buf=aci_micpreamp;
-			vol = SCALE(3, 100, buf <= 3 ? buf : 3);
-			vol |= vol << 8;
-			__put_user(vol, p);
-			return 0;
-		}
-		break;
-	case SOUND_MIXER_READ_OGAIN:
-		if (aci_amp)
-			buf = (100 || 100<<8);
-		else
-			buf = 0;
-		__put_user(buf, p);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static struct mixer_operations aci_mixer_operations =
-{
-	.owner = THIS_MODULE,
-	.id    = "ACI",
-	.ioctl = aci_mixer_ioctl
-};
-
-/*
- * There is also an internal mixer in the codec (CS4231A or AD1845),
- * that deserves no purpose in an ACI based system which uses an
- * external ACI controlled stereo mixer. Make sure that this codec
- * mixer has the AUX1 input selected as the recording source, that the
- * input gain is set near maximum and that the other channels going
- * from the inputs to the codec output are muted.
- */
-
-static int __init attach_aci(void)
-{
-	char *boardname;
-	int i, rc = -EBUSY;
-
-	mutex_init(&aci_mutex);
-
-	outb(0xE3, 0xf8f); /* Write MAD16 password */
-	aci_port = (inb(0xf90) & 0x10) ?
-		0x344: 0x354; /* Get aci_port from MC4_PORT */
-
-	if (!request_region(aci_port, 3, "sound mixer (ACI)")) {
-		printk(KERN_NOTICE
-		       "aci: I/O area 0x%03x-0x%03x already used.\n",
-		       aci_port, aci_port+2);
-		goto out;
-	}
-
-	/* force ACI into a known state */
-	rc = -EFAULT;
-	for (i=0; i<3; i++)
-		if (aci_rw_cmd(ACI_ERROR_OP, -1, -1)<0)
-			goto out_release_region;
-
-	/* official this is one aci read call: */
-	rc = -EFAULT;
-	if ((aci_idcode[0]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0 ||
-	    (aci_idcode[1]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0) {
-		printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n",
-		       aci_port);
-		goto out_release_region;
-	}
-
-	if ((aci_version=aci_rw_cmd(ACI_READ_VERSION, -1, -1))<0) {
-		printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n",
-		       aci_port);
-		goto out_release_region;
-	}
-
-	if (aci_idcode[0] == 'm') {
-		/* It looks like a miro sound card. */
-		switch (aci_idcode[1]) {
-		case 'A':
-			boardname = "PCM1 pro / early PCM12";
-			break;
-		case 'B':
-			boardname = "PCM12";
-			break;
-		case 'C':
-			boardname = "PCM20 radio";
-			break;
-		default:
-			boardname = "unknown miro";
-		}
-	} else {
-		printk(KERN_WARNING "aci: Warning: unsupported card! - "
-		       "no hardware, no specs...\n");
-		boardname = "unknown Cardinal Technologies";
-	}
-
-	printk(KERN_INFO "<ACI 0x%02x, id %02x/%02x \"%c/%c\", (%s)> at 0x%03x\n",
-	       aci_version,
-	       aci_idcode[0], aci_idcode[1],
-	       aci_idcode[0], aci_idcode[1],
-	       boardname, aci_port);
-
-	rc = -EBUSY;
-	if (reset) {
-		/* first write()s after reset fail with my PCM20 */
-		if (aci_rw_cmd(ACI_INIT, -1, -1)<0 ||
-		    aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0 ||
-		    aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0)
-			goto out_release_region;
-	}
-
-	/* the PCM20 is muted after reset (and reboot) */
-	if (aci_rw_cmd(ACI_SET_MUTE, 0x00, -1)<0)
-		goto out_release_region;
-
-	if (ide>=0)
-		if (aci_rw_cmd(ACI_SET_IDE, !ide, -1)<0)
-			goto out_release_region;
-	
-	if (wss>=0 && aci_idcode[1]=='A')
-		if (aci_rw_cmd(ACI_SET_WSS, !!wss, -1)<0)
-			goto out_release_region;
-
-	mixer_device = sound_install_mixer(MIXER_DRIVER_VERSION, boardname,
-					   &aci_mixer_operations,
-					   sizeof(aci_mixer_operations), NULL);
-	rc = 0;
-	if (mixer_device < 0) {
-		printk(KERN_ERR "aci: Failed to install mixer.\n");
-		rc = mixer_device;
-		goto out_release_region;
-	} /* else Maybe initialize the CS4231A mixer here... */
-out:	return rc;
-out_release_region:
-	release_region(aci_port, 3);
-	goto out;
-}
-
-static void __exit unload_aci(void)
-{
-	sound_unload_mixerdev(mixer_device);
-	release_region(aci_port, 3);
-}
-
-module_init(attach_aci);
-module_exit(unload_aci);
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/aci.h b/sound/oss/aci.h
deleted file mode 100644
index 20102ee..0000000
--- a/sound/oss/aci.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _ACI_H_
-#define _ACI_H_
-
-extern int aci_port;
-extern int aci_version;		/* ACI firmware version	*/
-extern int aci_rw_cmd(int write1, int write2, int write3);
-
-#define aci_indexed_cmd(a, b) aci_rw_cmd(a, b, -1)
-#define aci_write_cmd(a, b)   aci_rw_cmd(a, b, -1)
-#define aci_read_cmd(a)       aci_rw_cmd(a,-1, -1)
-
-#define COMMAND_REGISTER    (aci_port)      /* write register */
-#define STATUS_REGISTER     (aci_port + 1)  /* read register */
-#define BUSY_REGISTER       (aci_port + 2)  /* also used for rds */
-
-#define RDS_REGISTER        BUSY_REGISTER
-
-#define ACI_SET_MUTE          0x0d
-#define ACI_SET_POWERAMP      0x0f
-#define ACI_SET_TUNERMUTE     0xa3
-#define ACI_SET_TUNERMONO     0xa4
-#define ACI_SET_IDE           0xd0
-#define ACI_SET_WSS           0xd1
-#define ACI_SET_SOLOMODE      0xd2
-#define ACI_WRITE_IGAIN       0x03
-#define ACI_WRITE_TUNE        0xa7
-#define ACI_READ_TUNERSTEREO  0xa8
-#define ACI_READ_TUNERSTATION 0xa9
-#define ACI_READ_VERSION      0xf1
-#define ACI_READ_IDCODE       0xf2
-#define ACI_INIT              0xff
-#define ACI_STATUS            0xf0
-#define     ACI_S_GENERAL     0x00
-#define     ACI_S_READ_IGAIN  0x21
-#define ACI_ERROR_OP          0xdf
-
-/*
- * The following macro SCALE can be used to scale one integer volume
- * value into another one using only integer arithmetic. If the input
- * value x is in the range 0 <= x <= xmax, then the result will be in
- * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
- *
- * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
- * following nice properties:
- *
- * - SCALE(xmax,ymax,xmax) = ymax
- * - SCALE(xmax,ymax,0) = 0
- * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
- *
- * In addition, the rounding error is minimal and nicely distributed.
- * The proofs are left as an exercise to the reader.
- */
-
-#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
-
-
-#endif  /* _ACI_H_ */
diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c
deleted file mode 100644
index caabf31..0000000
--- a/sound/oss/ad1816.c
+++ /dev/null
@@ -1,1368 +0,0 @@
-/*
- *
- * AD1816 lowlevel sound driver for Linux 2.6.0 and above
- *
- * Copyright (C) 1998-2003 by Thorsten Knabe <linux@thorsten-knabe.de>
- *
- * Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
- *
- *
- * version: 1.5
- * status: beta
- * date: 2003/07/15
- *
- * Changes:
- *	Oleg Drokin: Some cleanup of load/unload functions.	1998/11/24
- *	
- *	Thorsten Knabe: attach and unload rewritten, 
- *	some argument checks added				1998/11/30
- *
- *	Thorsten Knabe: Buggy isa bridge workaround added	1999/01/16
- *	
- *	David Moews/Thorsten Knabe: Introduced options 
- *	parameter. Added slightly modified patch from 
- *	David Moews to disable dsp audio sources by setting 
- *	bit 0 of options parameter. This seems to be
- *	required by some Aztech/Newcom SC-16 cards.		1999/04/18
- *
- *	Christoph Hellwig: Adapted to module_init/module_exit.	2000/03/03
- *
- *	Christoph Hellwig: Added isapnp support			2000/03/15
- *
- *	Arnaldo Carvalho de Melo: get rid of check_region	2001/10/07
- *      
- *      Thorsten Knabe: Compiling with CONFIG_PNP enabled
- *	works again. It is now possible to use more than one 
- *	AD1816 sound card. Sample rate now may be changed during
- *	playback/capture. printk() uses log levels everywhere.
- *	SMP fixes. DMA handling fixes.
- *	Other minor code cleanup.				2003/07/15
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/isapnp.h>
-#include <linux/stddef.h>
-#include <linux/spinlock.h>
-#include "sound_config.h"
-
-#define DEBUGNOISE(x)
-
-#define CHECK_FOR_POWER { int timeout=100; \
-  while (timeout > 0 && (inb(devc->base)&0x80)!= 0x80) {\
-          timeout--; \
-  } \
-  if (timeout==0) {\
-          printk(KERN_WARNING "ad1816: Check for power failed in %s line: %d\n",__FILE__,__LINE__); \
-  } \
-}
-
-/* structure to hold device specific information */
-typedef struct
-{
-        int            base;          /* set in attach */
-	int            irq;
-	int            dma_playback;
-        int            dma_capture;
-  
-	int            opened;         /* open */
-        int            speed;	
-	int            channels;
-	int            audio_format;
-        int            audio_mode; 
-  
-        int            recmask;        /* setup */
-	unsigned char  format_bits;
-	int            supported_devices;
-	int            supported_rec_devices;
-	unsigned short levels[SOUND_MIXER_NRDEVICES];
-					/* misc */
-	struct pnp_dev *pnpdev;	 /* configured via pnp */
-        int            dev_no;   /* this is the # in audio_devs and NOT 
-				    in ad1816_info */
-	spinlock_t	lock;  
-} ad1816_info;
-
-static int nr_ad1816_devs;
-static int ad1816_clockfreq = 33000;
-static int options;
-
-/* supported audio formats */
-static int  ad_format_mask =
-AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW;
-
-/* array of device info structures */
-static ad1816_info dev_info[MAX_AUDIO_DEV];
-
-
-/* ------------------------------------------------------------------- */
-
-/* functions for easier access to inderect registers */
-
-static int ad_read (ad1816_info * devc, int reg)
-{
-	int result;
-	
-	CHECK_FOR_POWER;
-	outb ((unsigned char) (reg & 0x3f), devc->base+0);
-	result = inb(devc->base+2);
-	result+= inb(devc->base+3)<<8;
-	return (result);
-}
-
-
-static void ad_write (ad1816_info * devc, int reg, int data)
-{
-	CHECK_FOR_POWER;
-	outb ((unsigned char) (reg & 0xff), devc->base+0);
-	outb ((unsigned char) (data & 0xff),devc->base+2);
-	outb ((unsigned char) ((data>>8)&0xff),devc->base+3);
-}
-
-/* ------------------------------------------------------------------- */
-
-/* function interface required by struct audio_driver */
-
-static void ad1816_halt_input (int dev)
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	unsigned char buffer;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_input called\n"));
-	
-	spin_lock_irqsave(&devc->lock,flags); 
-	
-	if(!isa_dma_bridge_buggy) {
-	        disable_dma(audio_devs[dev]->dmap_in->dma);
-	}
-	
-	buffer=inb(devc->base+9);
-	if (buffer & 0x01) {
-		/* disable capture */
-		outb(buffer & ~0x01,devc->base+9); 
-	}
-
-	if(!isa_dma_bridge_buggy) {
-	        enable_dma(audio_devs[dev]->dmap_in->dma);
-	}
-
-	/* Clear interrupt status */
-	outb (~0x40, devc->base+1);	
-	
-	devc->audio_mode &= ~PCM_ENABLE_INPUT;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static void ad1816_halt_output (int dev)
-{
-	unsigned long  flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	unsigned char buffer;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_output called!\n"));
-
-	spin_lock_irqsave(&devc->lock,flags); 
-	/* Mute pcm output */
-	ad_write(devc, 4, ad_read(devc,4)|0x8080);
-
-	if(!isa_dma_bridge_buggy) {
-	        disable_dma(audio_devs[dev]->dmap_out->dma);
-	}
-
-	buffer=inb(devc->base+8);
-	if (buffer & 0x01) {
-		/* disable capture */
-		outb(buffer & ~0x01,devc->base+8); 
-	}
-
-	if(!isa_dma_bridge_buggy) {
-	        enable_dma(audio_devs[dev]->dmap_out->dma);
-	}
-
-	/* Clear interrupt status */
-	outb ((unsigned char)~0x80, devc->base+1);	
-
-	devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static void ad1816_output_block (int dev, unsigned long buf, 
-				 int count, int intrflag)
-{
-	unsigned long flags;
-	unsigned long cnt;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: output_block called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
-  
-	cnt = count/4 - 1;
-  
-	spin_lock_irqsave(&devc->lock,flags);
-	
-	/* set transfer count */
-	ad_write (devc, 8, cnt & 0xffff); 
-	
-	devc->audio_mode |= PCM_ENABLE_OUTPUT; 
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-static void ad1816_start_input (int dev, unsigned long buf, int count,
-				int intrflag)
-{
-	unsigned long flags;
-	unsigned long  cnt;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: start_input called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
-
-	cnt = count/4 - 1;
-
-	spin_lock_irqsave(&devc->lock,flags);
-
-	/* set transfer count */
-	ad_write (devc, 10, cnt & 0xffff); 
-	devc->audio_mode |= PCM_ENABLE_INPUT;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static int ad1816_prepare_for_input (int dev, int bsize, int bcount)
-{
-	unsigned long flags;
-	unsigned int freq;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	unsigned char fmt_bits;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_input called: bsize=%d bcount=%d\n",bsize,bcount));
-
-	spin_lock_irqsave(&devc->lock,flags);
-	fmt_bits= (devc->format_bits&0x7)<<3;
-	
-	/* set mono/stereo mode */
-	if (devc->channels > 1) {
-		fmt_bits |=0x4;
-	}
-	/* set Mono/Stereo in playback/capture register */
-	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
-	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
-
-	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
-
-	/* write playback/capture speeds */
-	ad_write (devc, 2, freq & 0xffff);	
-	ad_write (devc, 3, freq & 0xffff);	
-
-	spin_unlock_irqrestore(&devc->lock,flags);
-
-	ad1816_halt_input(dev);
-	return 0;
-}
-
-static int ad1816_prepare_for_output (int dev, int bsize, int bcount)
-{
-	unsigned long flags;
-	unsigned int freq;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	unsigned char fmt_bits;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_output called: bsize=%d bcount=%d\n",bsize,bcount));
-
-	spin_lock_irqsave(&devc->lock,flags);
-
-	fmt_bits= (devc->format_bits&0x7)<<3;
-	/* set mono/stereo mode */
-	if (devc->channels > 1) {
-		fmt_bits |=0x4;
-	}
-
-	/* write format bits to playback/capture registers */
-	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
-	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
-  
-	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
-	
-	/* write playback/capture speeds */
-	ad_write (devc, 2, freq & 0xffff);
-	ad_write (devc, 3, freq & 0xffff);
-
-	spin_unlock_irqrestore(&devc->lock,flags);
-	
-	ad1816_halt_output(dev);
-	return 0;
-
-}
-
-static void ad1816_trigger (int dev, int state) 
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: trigger called! (devc=%d,devc->base=%d\n", devc, devc->base));
-
-	/* mode may have changed */
-
-	spin_lock_irqsave(&devc->lock,flags);
-
-	/* mask out modes not specified on open call */
-	state &= devc->audio_mode; 
-				
-	/* setup soundchip to new io-mode */
-	if (state & PCM_ENABLE_INPUT) {
-		/* enable capture */
-		outb(inb(devc->base+9)|0x01, devc->base+9);
-	} else {
-		/* disable capture */
-		outb(inb(devc->base+9)&~0x01, devc->base+9);
-	}
-
-	if (state & PCM_ENABLE_OUTPUT) {
-		/* enable playback */
-		outb(inb(devc->base+8)|0x01, devc->base+8);
-		/* unmute pcm output */
-		ad_write(devc, 4, ad_read(devc,4)&~0x8080);
-	} else {
-		/* mute pcm output */
-		ad_write(devc, 4, ad_read(devc,4)|0x8080);
-		/* disable capture */
-		outb(inb(devc->base+8)&~0x01, devc->base+8);
-	}
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-/* halt input & output */
-static void ad1816_halt (int dev)
-{
-	ad1816_halt_input(dev);
-	ad1816_halt_output(dev);
-}
-
-static void ad1816_reset (int dev)
-{
-	ad1816_halt (dev);
-}
-
-/* set playback speed */
-static int ad1816_set_speed (int dev, int arg)
-{
-	unsigned long flags;
-	unsigned int freq;
-	int ret;
-
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	spin_lock_irqsave(&devc->lock, flags);
-	if (arg == 0) {
-		ret = devc->speed;
-		spin_unlock_irqrestore(&devc->lock, flags);
-		return ret;
-	}
-	/* range checking */
-	if (arg < 4000) {
-		arg = 4000;
-	}
-	if (arg > 55000) {
-		arg = 55000;
-	}
-	devc->speed = arg;
-
-	/* change speed during playback */
-	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
-	/* write playback/capture speeds */
-	ad_write (devc, 2, freq & 0xffff);	
-	ad_write (devc, 3, freq & 0xffff);	
-
-	ret = devc->speed;
-	spin_unlock_irqrestore(&devc->lock, flags);
-	return ret;
-
-}
-
-static unsigned int ad1816_set_bits (int dev, unsigned int arg)
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	static struct format_tbl {
-		int             format;
-		unsigned char   bits;
-	} format2bits[] = {
-		{ 0, 0 },
-		{ AFMT_MU_LAW, 1 },
-		{ AFMT_A_LAW, 3 },
-		{ AFMT_IMA_ADPCM, 0 },
-		{ AFMT_U8, 0 },
-		{ AFMT_S16_LE, 2 },
-		{ AFMT_S16_BE, 6 },
-		{ AFMT_S8, 0 },
-		{ AFMT_U16_LE, 0 },
-		{ AFMT_U16_BE, 0 }
-  	};
-
-	int  i, n = sizeof (format2bits) / sizeof (struct format_tbl);
-
-	spin_lock_irqsave(&devc->lock, flags);
-	/* return current format */
-	if (arg == 0) {
-	  	arg = devc->audio_format;
-		spin_unlock_irqrestore(&devc->lock, flags);
-		return arg;
-	}
-	devc->audio_format = arg;
-
-	/* search matching format bits */
-	for (i = 0; i < n; i++)
-		if (format2bits[i].format == arg) {
-			devc->format_bits = format2bits[i].bits;
-			devc->audio_format = arg;
-			spin_unlock_irqrestore(&devc->lock, flags);
-			return arg;
-		}
-
-	/* Still hanging here. Something must be terribly wrong */
-	devc->format_bits = 0;
-	devc->audio_format = AFMT_U8;
-	spin_unlock_irqrestore(&devc->lock, flags);
-	return(AFMT_U8); 
-}
-
-static short ad1816_set_channels (int dev, short arg)
-{
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-
-	if (arg != 1 && arg != 2)
-		return devc->channels;
-
-	devc->channels = arg;
-	return arg;
-}
-
-/* open device */
-static int ad1816_open (int dev, int mode) 
-{
-	ad1816_info    *devc = NULL;
-	unsigned long   flags;
-
-	/* is device number valid ? */
-	if (dev < 0 || dev >= num_audiodevs)
-		return -(ENXIO);
-
-	/* get device info of this dev */
-	devc = (ad1816_info *) audio_devs[dev]->devc; 
-
-	/* make check if device already open atomic */
-	spin_lock_irqsave(&devc->lock,flags);
-
-	if (devc->opened) {
-		spin_unlock_irqrestore(&devc->lock,flags);
-		return -(EBUSY);
-	}
-
-	/* mark device as open */
-	devc->opened = 1; 
-
-	devc->audio_mode = 0;
-	devc->speed = 8000;
-	devc->audio_format=AFMT_U8;
-	devc->channels=1;
-	spin_unlock_irqrestore(&devc->lock,flags);
-	ad1816_reset(devc->dev_no); /* halt all pending output */
-	return 0;
-}
-
-static void ad1816_close (int dev) /* close device */
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-
-	/* halt all pending output */
-	ad1816_reset(devc->dev_no); 
-
-	spin_lock_irqsave(&devc->lock,flags);
-	devc->opened = 0;
-	devc->audio_mode = 0;
-	devc->speed = 8000;
-	devc->audio_format=AFMT_U8;
-	devc->format_bits = 0;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-/* ------------------------------------------------------------------- */
-
-/* Audio driver structure */
-
-static struct audio_driver ad1816_audio_driver =
-{
-	.owner			= THIS_MODULE,
-	.open			= ad1816_open,
-	.close			= ad1816_close,
-	.output_block		= ad1816_output_block,
-	.start_input		= ad1816_start_input,
-	.prepare_for_input	= ad1816_prepare_for_input,
-	.prepare_for_output	= ad1816_prepare_for_output,
-	.halt_io		= ad1816_halt,
-	.halt_input		= ad1816_halt_input,
-	.halt_output		= ad1816_halt_output,
-	.trigger		= ad1816_trigger,
-	.set_speed		= ad1816_set_speed,
-	.set_bits		= ad1816_set_bits,
-	.set_channels		= ad1816_set_channels,
-};
-
-
-/* ------------------------------------------------------------------- */
-
-/* Interrupt handler */
-
-
-static irqreturn_t ad1816_interrupt (int irq, void *dev_id)
-{
-	unsigned char	status;
-	ad1816_info	*devc = (ad1816_info *)dev_id;
-	
-	if (irq < 0 || irq > 15) {
-	        printk(KERN_WARNING "ad1816: Got bogus interrupt %d\n", irq);
-		return IRQ_NONE;
-	}
-
-	spin_lock(&devc->lock);
-
-	/* read interrupt register */
-	status = inb (devc->base+1); 
-	/* Clear all interrupt  */
-	outb (~status, devc->base+1);	
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: Got interrupt subclass %d\n",status));
-
-	if (status == 0) {
-		DEBUGNOISE(printk(KERN_DEBUG "ad1816: interrupt: Got interrupt, but no source.\n"));
-		spin_unlock(&devc->lock);
-		return IRQ_NONE;
-	}
-
-	if (devc->opened && (devc->audio_mode & PCM_ENABLE_INPUT) && (status&64))
-		DMAbuf_inputintr (devc->dev_no);
-
-	if (devc->opened && (devc->audio_mode & PCM_ENABLE_OUTPUT) && (status & 128))
-		DMAbuf_outputintr (devc->dev_no, 1);
-
-	spin_unlock(&devc->lock);
-	return IRQ_HANDLED;
-}
-
-/* ------------------------------------------------------------------- */
-
-/* Mixer stuff */
-
-struct mixer_def {
-	unsigned int regno: 7;
-	unsigned int polarity:1;	/* 0=normal, 1=reversed */
-	unsigned int bitpos:4;
-	unsigned int nbits:4;
-};
-
-static char mix_cvt[101] = {
-	 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
-	43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
-	65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
-	80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
-	91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
-	100
-};
-
-typedef struct mixer_def mixer_ent;
-
-/*
- * Most of the mixer entries work in backwards. Setting the polarity field
- * makes them to work correctly.
- *
- * The channel numbering used by individual soundcards is not fixed. Some
- * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
- * The current version doesn't try to compensate this.
- */
-
-#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r)	\
-  {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
-
-
-static mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
-MIX_ENT(SOUND_MIXER_VOLUME,	14, 1, 8, 5,	14, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH,	 5, 1, 8, 6,	 5, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_PCM,	 4, 1, 8, 6,	 4, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_SPEAKER,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE,	18, 1, 8, 5,	18, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_MIC,	19, 1, 8, 5,	19, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_CD,	 	15, 1, 8, 5,	15, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_IMIX,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV,	20, 0, 8, 4,	20, 0, 0, 4),
-MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE1, 	17, 1, 8, 5,	17, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE2,	16, 1, 8, 5,	16, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE3,      39, 0, 9, 4,    39, 1, 0, 5)
-};
-
-
-static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
-{
-	0x4343,		/* Master Volume */
-	0x3232,		/* Bass */
-	0x3232,		/* Treble */
-	0x0000,		/* FM */
-	0x4343,		/* PCM */
-	0x0000,		/* PC Speaker */
-	0x0000,		/* Ext Line */
-	0x0000,		/* Mic */
-	0x0000,		/* CD */
-	0x0000,		/* Recording monitor */
-	0x0000,		/* SB PCM */
-	0x0000,		/* Recording level */
-	0x0000,		/* Input gain */
-	0x0000,		/* Output gain */
-	0x0000,		/* Line1 */
-	0x0000,		/* Line2 */
-	0x0000		/* Line3 (usually line in)*/
-};
-
-#define LEFT_CHN	0
-#define RIGHT_CHN	1
-
-
-
-static int
-ad1816_set_recmask (ad1816_info * devc, int mask)
-{
-  	unsigned long 	flags;
-	unsigned char   recdev;
-	int             i, n;
-	
-	spin_lock_irqsave(&devc->lock, flags);
-	mask &= devc->supported_rec_devices;
-	
-	n = 0;
-	/* Count selected device bits */
-	for (i = 0; i < 32; i++)
-		if (mask & (1 << i))
-			n++;
-	
-	if (n == 0)
-		mask = SOUND_MASK_MIC;
-	else if (n != 1) { /* Too many devices selected */
-		/* Filter out active settings */
-		mask &= ~devc->recmask;	
-		
-		n = 0;
-		/* Count selected device bits */
-		for (i = 0; i < 32; i++) 
-			if (mask & (1 << i))
-				n++;
-		
-		if (n != 1)
-			mask = SOUND_MASK_MIC;
-	}
-	
-	switch (mask) {
-	case SOUND_MASK_MIC:
-		recdev = 5;
-		break;
-		
-	case SOUND_MASK_LINE:
-		recdev = 0;
-		break;
-		
-	case SOUND_MASK_CD:
-		recdev = 2;
-		break;
-		
-	case SOUND_MASK_LINE1:
-		recdev = 4;
-		break;
-		
-	case SOUND_MASK_LINE2:
-		recdev = 3;
-		break;
-		
-	case SOUND_MASK_VOLUME:
-		recdev = 1;
-		break;
-		
-	default:
-		mask = SOUND_MASK_MIC;
-		recdev = 5;
-	}
-	
-	recdev <<= 4;
-	ad_write (devc, 20, 
-		  (ad_read (devc, 20) & 0x8f8f) | recdev | (recdev<<8));
-
-	devc->recmask = mask;
-	spin_unlock_irqrestore(&devc->lock, flags);
-	return mask;
-}
-
-static void
-change_bits (int *regval, int dev, int chn, int newval)
-{
-	unsigned char   mask;
-	int             shift;
-  
-	/* Reverse polarity*/
-
-	if (mix_devices[dev][chn].polarity == 1) 
-		newval = 100 - newval;
-
-	mask = (1 << mix_devices[dev][chn].nbits) - 1;
-	shift = mix_devices[dev][chn].bitpos;
-	/* Scale it */
-	newval = (int) ((newval * mask) + 50) / 100;	
-	/* Clear bits */
-	*regval &= ~(mask << shift);	
-	/* Set new value */
-	*regval |= (newval & mask) << shift;	
-}
-
-static int
-ad1816_mixer_get (ad1816_info * devc, int dev)
-{
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_get called!\n"));
-	
-	/* range check + supported mixer check */
-	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
-	        return (-(EINVAL));
-	if (!((1 << dev) & devc->supported_devices))
-		return -(EINVAL);
-	
-	return devc->levels[dev];
-}
-
-static int
-ad1816_mixer_set (ad1816_info * devc, int dev, int value)
-{
-	int   left = value & 0x000000ff;
-	int   right = (value & 0x0000ff00) >> 8;
-	int   retvol;
-
-	int   regoffs;
-	int   val;
-	int   valmute;
-	unsigned long flags;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_set called!\n"));
-	
-	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
-		return -(EINVAL);
-
-	if (left > 100)
-		left = 100;
-	if (left < 0)
-		left = 0;
-	if (right > 100)
-		right = 100;
-	if (right < 0)
-		right = 0;
-	
-	/* Mono control */
-	if (mix_devices[dev][RIGHT_CHN].nbits == 0) 
-		right = left;
-	retvol = left | (right << 8);
-	
-	/* Scale it */
-	
-	left = mix_cvt[left];
-	right = mix_cvt[right];
-
-	/* reject all mixers that are not supported */
-	if (!(devc->supported_devices & (1 << dev)))
-		return -(EINVAL);
-	
-	/* sanity check */
-	if (mix_devices[dev][LEFT_CHN].nbits == 0)
-		return -(EINVAL);
-	spin_lock_irqsave(&devc->lock, flags);
-
-	/* keep precise volume internal */
-	devc->levels[dev] = retvol;
-
-	/* Set the left channel */
-	regoffs = mix_devices[dev][LEFT_CHN].regno;
-	val = ad_read (devc, regoffs);
-	change_bits (&val, dev, LEFT_CHN, left);
-
-	valmute=val;
-
-	/* Mute bit masking on some registers */
-	if ( regoffs==5 || regoffs==14 || regoffs==15 ||
-	     regoffs==16 || regoffs==17 || regoffs==18 || 
-	     regoffs==19 || regoffs==39) {
-		if (left==0)
-			valmute |= 0x8000;
-		else
-			valmute &= ~0x8000;
-	}
-	ad_write (devc, regoffs, valmute); /* mute */
-
-	/*
-	 * Set the right channel
-	 */
- 
-	/* Was just a mono channel */
-	if (mix_devices[dev][RIGHT_CHN].nbits == 0) {
-		spin_unlock_irqrestore(&devc->lock, flags);
-		return retvol;		
-	}
-
-	regoffs = mix_devices[dev][RIGHT_CHN].regno;
-	val = ad_read (devc, regoffs);
-	change_bits (&val, dev, RIGHT_CHN, right);
-
-	valmute=val;
-	if ( regoffs==5 || regoffs==14 || regoffs==15 ||
-	     regoffs==16 || regoffs==17 || regoffs==18 || 
-	     regoffs==19 || regoffs==39) {
-		if (right==0)
-			valmute |= 0x80;
-		else
-			valmute &= ~0x80;
-	}
-	ad_write (devc, regoffs, valmute); /* mute */
-	spin_unlock_irqrestore(&devc->lock, flags);
-       	return retvol;
-}
-
-#define MIXER_DEVICES ( SOUND_MASK_VOLUME | \
-			SOUND_MASK_SYNTH | \
-			SOUND_MASK_PCM | \
-			SOUND_MASK_LINE | \
-			SOUND_MASK_LINE1 | \
-			SOUND_MASK_LINE2 | \
-			SOUND_MASK_LINE3 | \
-			SOUND_MASK_MIC | \
-			SOUND_MASK_CD | \
-			SOUND_MASK_RECLEV  \
-			)
-#define REC_DEVICES ( SOUND_MASK_LINE2 |\
-		      SOUND_MASK_LINE |\
-		      SOUND_MASK_LINE1 |\
-		      SOUND_MASK_MIC |\
-		      SOUND_MASK_CD |\
-		      SOUND_MASK_VOLUME \
-		      )
-     
-static void
-ad1816_mixer_reset (ad1816_info * devc)
-{
-	int  i;
-
-	devc->supported_devices = MIXER_DEVICES;
-	
-	devc->supported_rec_devices = REC_DEVICES;
-
-	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-		if (devc->supported_devices & (1 << i))
-			ad1816_mixer_set (devc, i, default_mixer_levels[i]);
-	ad1816_set_recmask (devc, SOUND_MASK_MIC);
-}
-
-static int
-ad1816_mixer_ioctl (int dev, unsigned int cmd, void __user * arg)
-{
-	ad1816_info    *devc = mixer_devs[dev]->devc;
-	int val;
-	int __user *p = arg;
-  
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_ioctl called!\n"));
-  
-	/* Mixer ioctl */
-	if (((cmd >> 8) & 0xff) == 'M') { 
-		
-		/* set ioctl */
-		if (_SIOC_DIR (cmd) & _SIOC_WRITE) { 
-			switch (cmd & 0xff){
-			case SOUND_MIXER_RECSRC:
-				
-				if (get_user(val, p))
-					return -EFAULT;
-				val=ad1816_set_recmask (devc, val);
-				return put_user(val, p);
-				break;
-				
-			default:
-				if (get_user(val, p))
-					return -EFAULT;
-				if ((val=ad1816_mixer_set (devc, cmd & 0xff, val))<0)
-				        return val;
-				else
-				        return put_user(val, p);
-			}
-		} else { 
-			/* read ioctl */
-			switch (cmd & 0xff) {
-				
-			case SOUND_MIXER_RECSRC:
-				val=devc->recmask;
-				return put_user(val, p);
-				break;
-				
-			case SOUND_MIXER_DEVMASK:
-				val=devc->supported_devices;
-				return put_user(val, p);
-				break;
-
-			case SOUND_MIXER_STEREODEVS:
-				val=devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
-				return put_user(val, p);
-				break;
-				
-			case SOUND_MIXER_RECMASK:
-				val=devc->supported_rec_devices;
-				return put_user(val, p);
-				break;
-				
-			case SOUND_MIXER_CAPS:
-				val=SOUND_CAP_EXCL_INPUT;
-				return put_user(val, p);
-				break;
-				
-			default:
-			        if ((val=ad1816_mixer_get (devc, cmd & 0xff))<0)
-				        return val;
-				else
-				        return put_user(val, p);
-			}
-		}
-	} else
-		/* not for mixer */
-		return -(EINVAL);
-}
-
-/* ------------------------------------------------------------------- */
-
-/* Mixer structure */
-
-static struct mixer_operations ad1816_mixer_operations = {
-	.owner	= THIS_MODULE,
-	.id	= "AD1816",
-	.name	= "AD1816 Mixer",
-	.ioctl	= ad1816_mixer_ioctl
-};
-
-
-/* ------------------------------------------------------------------- */
-
-/* stuff for card recognition, init and unloading PNP ...*/
-
-
-/* check if AD1816 present at specified hw_config and register device with OS 
- * return 1 if initialization was successful, 0 otherwise
- */
-static int __init ad1816_init_card (struct address_info *hw_config, 
-	struct pnp_dev *pnp)
-{
-	ad1816_info    *devc = NULL;
-	int tmp;
-	int oss_devno = -1;
-
-	printk(KERN_INFO "ad1816: initializing card: io=0x%x, irq=%d, dma=%d, "
-			 "dma2=%d, clockfreq=%d, options=%d isadmabug=%d "
-			 "%s\n",
-	       hw_config->io_base,
-	       hw_config->irq,
-	       hw_config->dma,
-	       hw_config->dma2,
-	       ad1816_clockfreq,
-	       options,
-	       isa_dma_bridge_buggy,
-	       pnp?"(PNP)":"");
-
-	/* ad1816_info structure remaining ? */
-	if (nr_ad1816_devs >= MAX_AUDIO_DEV) {
-		printk(KERN_WARNING "ad1816: no more ad1816_info structures "
-			"left\n");
-		goto out;
-	}
-
-	devc = &dev_info[nr_ad1816_devs];
-	devc->base = hw_config->io_base;
-	devc->irq = hw_config->irq;
-	devc->dma_playback=hw_config->dma;
-	devc->dma_capture=hw_config->dma2;
-	devc->opened = 0;
-	devc->pnpdev = pnp;
-	spin_lock_init(&devc->lock);
-
-	if (!request_region(devc->base, 16, "AD1816 Sound")) {
-		printk(KERN_WARNING "ad1816: I/O port 0x%03x not free\n",
-				    devc->base);
-		goto out;
-	}
-
-	printk(KERN_INFO "ad1816: Examining AD1816 at address 0x%03x.\n", 
-		devc->base);
-	
-
-	/* tests for ad1816 */
-	/* base+0: bit 1 must be set but not 255 */
-	tmp=inb(devc->base);
-	if ( (tmp&0x80)==0 || tmp==255 ) {
-		printk (KERN_INFO "ad1816: Chip is not an AD1816 or chip "
-			"is not active (Test 0)\n");
-		goto out_release_region;
-	}
-
-	/* writes to ireg 8 are copied to ireg 9 */
-	ad_write(devc,8,12345); 
-	if (ad_read(devc,9)!=12345) {
-		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 1)\n");
-		goto out_release_region;
-	}
-  
-	/* writes to ireg 8 are copied to ireg 9 */
-	ad_write(devc,8,54321); 
-	if (ad_read(devc,9)!=54321) {
-		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 2)\n");
-		goto out_release_region;
-	}
-
-	/* writes to ireg 10 are copied to ireg 11 */
-	ad_write(devc,10,54321); 
-	if (ad_read(devc,11)!=54321) {
-		printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 3)\n");
-		goto out_release_region;
-	}
-
-	/* writes to ireg 10 are copied to ireg 11 */
-	ad_write(devc,10,12345); 
-	if (ad_read(devc,11)!=12345) {
-		printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 4)\n");
-		goto out_release_region;
-	}
-
-	/* bit in base +1 cannot be set to 1 */
-	tmp=inb(devc->base+1);
-	outb(0xff,devc->base+1); 
-	if (inb(devc->base+1)!=tmp) {
-		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 5)\n");
-		goto out_release_region;
-	}
-  
-	printk(KERN_INFO "ad1816: AD1816 (version %d) successfully detected!\n",
-		ad_read(devc,45));
-
-	/* disable all interrupts */
-	ad_write(devc,1,0);     
-
-	/* Clear pending interrupts */
-	outb (0, devc->base+1);	
-
-	/* allocate irq */
-	if (devc->irq < 0 || devc->irq > 15)
-		goto out_release_region;
-	if (request_irq(devc->irq, ad1816_interrupt,0,
-			"SoundPort", devc) < 0)	{
-	        printk(KERN_WARNING "ad1816: IRQ in use\n");
-		goto out_release_region;
-	}
-
-	/* DMA stuff */
-	if (sound_alloc_dma (devc->dma_playback, "Sound System")) {
-		printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
-				    devc->dma_playback);
-		goto out_free_irq;
-	}
-	
-	if ( devc->dma_capture >= 0 && 
-	  	devc->dma_capture != devc->dma_playback) {
-		if (sound_alloc_dma(devc->dma_capture,
-				    "Sound System (capture)")) {
-			printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
-					    devc->dma_capture);
-			goto out_free_dma;
-		}
-		devc->audio_mode=DMA_AUTOMODE|DMA_DUPLEX;
-	} else {
-	  	printk(KERN_WARNING "ad1816: Only one DMA channel "
-			"available/configured. No duplex operation possible\n");
-		devc->audio_mode=DMA_AUTOMODE;
-	}
-
-	conf_printf2 ("AD1816 audio driver",
-		      devc->base, devc->irq, devc->dma_playback, 
-		      devc->dma_capture);
-
-	/* register device */
-	if ((oss_devno = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
-					      "AD1816 audio driver",
-					      &ad1816_audio_driver,
-					      sizeof (struct audio_driver),
-					      devc->audio_mode,
-					      ad_format_mask,
-					      devc,
-					      devc->dma_playback, 
-					      devc->dma_capture)) < 0) {
-		printk(KERN_WARNING "ad1816: Can't install sound driver\n");
-		goto out_free_dma_2;
-	}
-
-
-	ad_write(devc,32,0x80f0); /* sound system mode */
-	if (options&1) {
-	        ad_write(devc,33,0); /* disable all audiosources for dsp */
-	} else {
-	        ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
-	}
-	ad_write(devc,4,0x8080);  /* default values for volumes (muted)*/
-	ad_write(devc,5,0x8080);
-	ad_write(devc,6,0x8080);
-	ad_write(devc,7,0x8080);
-	ad_write(devc,15,0x8888);
-	ad_write(devc,16,0x8888);
-	ad_write(devc,17,0x8888);
-	ad_write(devc,18,0x8888);
-	ad_write(devc,19,0xc888); /* +20db mic active */
-	ad_write(devc,14,0x0000); /* Master volume unmuted */
-	ad_write(devc,39,0x009f); /* 3D effect on 0% phone out muted */
-	ad_write(devc,44,0x0080); /* everything on power, 3d enabled for d/a */
-	outb(0x10,devc->base+8); /* set dma mode */
-	outb(0x10,devc->base+9);
-  
-	/* enable capture + playback interrupt */
-	ad_write(devc,1,0xc000); 
-	
-	/* set mixer defaults */
-	ad1816_mixer_reset (devc); 
-  
-	/* register mixer */
-	if ((audio_devs[oss_devno]->mixer_dev=sound_install_mixer(
-				       MIXER_DRIVER_VERSION,
-				       "AD1816 audio driver",
-				       &ad1816_mixer_operations,
-				       sizeof (struct mixer_operations),
-				       devc)) < 0) {
-	  	printk(KERN_WARNING "Can't install mixer\n");
-	}
-	/* make ad1816_info active */
-	nr_ad1816_devs++;
-	printk(KERN_INFO "ad1816: card successfully installed!\n");
-	return 1;
-	/* error handling */
-out_free_dma_2:
-	if (devc->dma_capture >= 0 && devc->dma_capture != devc->dma_playback)
-	        sound_free_dma(devc->dma_capture);
-out_free_dma:
-	sound_free_dma(devc->dma_playback);
-out_free_irq:
-	free_irq(devc->irq, devc);
-out_release_region:
-	release_region(devc->base, 16);
-out:
-	return 0;
-}
-
-static void __exit unload_card(ad1816_info *devc)
-{
-	int  mixer, dev = 0;
-	
-	if (devc != NULL) {
-		printk("ad1816: Unloading card at address 0x%03x\n",devc->base);
-		
-		dev = devc->dev_no;
-		mixer = audio_devs[dev]->mixer_dev;
-
-		/* unreg mixer*/
-		if(mixer>=0) {
-			sound_unload_mixerdev(mixer);
-		}
-		/* unreg audiodev */
-		sound_unload_audiodev(dev);
-		
-		/* free dma channels */
-		if (devc->dma_capture>=0 && 
-		  	devc->dma_capture != devc->dma_playback) {
-			sound_free_dma(devc->dma_capture);
-		}
-		sound_free_dma (devc->dma_playback);
-		/* free irq */
-		free_irq(devc->irq, devc);
-		/* free io */
-		release_region (devc->base, 16);
-#ifdef __ISAPNP__
-		if (devc->pnpdev) {
-		  	pnp_disable_dev(devc->pnpdev);
-			pnp_device_detach(devc->pnpdev);
-		}
-#endif
-		
-	} else
-		printk(KERN_WARNING "ad1816: no device/card specified\n");
-}
-
-static int __initdata io = -1;
-static int __initdata irq = -1;
-static int __initdata dma = -1;
-static int __initdata dma2 = -1;
-
-#ifdef __ISAPNP__
-/* use isapnp for configuration */
-static int isapnp	= 1;
-static int isapnpjump;
-module_param(isapnp, bool, 0);
-module_param(isapnpjump, int, 0);
-#endif
-
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(dma, int, 0);
-module_param(dma2, int, 0);
-module_param(ad1816_clockfreq, int, 0);
-module_param(options, int, 0);
-
-#ifdef __ISAPNP__
-static struct {
-	unsigned short card_vendor, card_device;
-	unsigned short vendor;
-	unsigned short function;
-	struct ad1816_data *data;
-} isapnp_ad1816_list[] __initdata = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7150), 
-		NULL },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7180),
-		NULL },
-	{0}
-};
-
-MODULE_DEVICE_TABLE(isapnp, isapnp_ad1816_list);
-
-
-static void __init ad1816_config_pnp_card(struct pnp_card *card,
-					  unsigned short vendor,
-					  unsigned short function)
-{
-	struct address_info cfg;
-  	struct pnp_dev *card_dev = pnp_find_dev(card, vendor, function, NULL);
-	if (!card_dev) return;
-	if (pnp_device_attach(card_dev) < 0) {
-	  	printk(KERN_WARNING "ad1816: Failed to attach PnP device\n");
-		return;
-	}
-	if (pnp_activate_dev(card_dev) < 0) {
-		printk(KERN_WARNING "ad1816: Failed to activate PnP device\n");
-		pnp_device_detach(card_dev);
-		return;
-	}
-	cfg.io_base = pnp_port_start(card_dev, 2);
-	cfg.irq = pnp_irq(card_dev, 0);
-	cfg.dma = pnp_irq(card_dev, 0);
-	cfg.dma2 = pnp_irq(card_dev, 1);
-	if (!ad1816_init_card(&cfg, card_dev)) {
-	  	pnp_disable_dev(card_dev);
-		pnp_device_detach(card_dev);
-	}
-}
-
-static void __init ad1816_config_pnp_cards(void)
-{
-	int nr_pnp_cfg;
-	int i;
-	
-	/* Count entries in isapnp_ad1816_list */
-	for (nr_pnp_cfg = 0; isapnp_ad1816_list[nr_pnp_cfg].card_vendor != 0; 
-		nr_pnp_cfg++);
-	/* Check and adjust isapnpjump */
-	if( isapnpjump < 0 || isapnpjump >= nr_pnp_cfg) {
-		printk(KERN_WARNING 
-			"ad1816: Valid range for isapnpjump is 0-%d. "
-			"Adjusted to 0.\n", nr_pnp_cfg-1);
-		isapnpjump = 0;
-	}
-	for (i = isapnpjump; isapnp_ad1816_list[i].card_vendor != 0; i++) {
-	 	struct pnp_card *card = NULL;
-		/* iterate over all pnp cards */		
-		while ((card = pnp_find_card(isapnp_ad1816_list[i].card_vendor,
-		              	isapnp_ad1816_list[i].card_device, card))) 
-			ad1816_config_pnp_card(card, 
-				isapnp_ad1816_list[i].vendor,
-				isapnp_ad1816_list[i].function);
-	}
-}
-#endif
-
-/* module initialization */
-static int __init init_ad1816(void)
-{
-	printk(KERN_INFO "ad1816: AD1816 sounddriver "
-			 "Copyright (C) 1998-2003 by Thorsten Knabe and "
-			 "others\n");
-#ifdef AD1816_CLOCK 
-	/* set ad1816_clockfreq if set during compilation */
-	ad1816_clockfreq=AD1816_CLOCK;
-#endif
-	if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
-		ad1816_clockfreq=33000;
-	}
-
-#ifdef __ISAPNP__
-	/* configure PnP cards */
-	if(isapnp) ad1816_config_pnp_cards();
-#endif
-	/* configure card by module params */
-	if (io != -1 && irq != -1 && dma != -1) {
-		struct address_info cfg;
-		cfg.io_base = io;
-		cfg.irq = irq;
-		cfg.dma = dma;
-		cfg.dma2 = dma2;
-		ad1816_init_card(&cfg, NULL);
-	}
-	if (nr_ad1816_devs <= 0)
-	  	return -ENODEV;
-	return 0;
-}
-
-/* module cleanup */
-static void __exit cleanup_ad1816 (void)
-{
-	int          i;
-	ad1816_info  *devc = NULL;
-  
-	/* remove any soundcard */
-	for (i = 0;  i < nr_ad1816_devs; i++) {
-		devc = &dev_info[i];
-		unload_card(devc);
-	}     
-	nr_ad1816_devs=0;
-	printk(KERN_INFO "ad1816: driver unloaded!\n");
-}
-
-module_init(init_ad1816);
-module_exit(cleanup_ad1816);
-
-#ifndef MODULE
-/* kernel command line parameter evaluation */
-static int __init setup_ad1816(char *str)
-{
-	/* io, irq, dma, dma2 */
-	int ints[5];
-	
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma2	= ints[4];
-	return 1;
-}
-
-__setup("ad1816=", setup_ad1816);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
deleted file mode 100644
index c0730a3..0000000
--- a/sound/oss/ad1889.c
+++ /dev/null
@@ -1,1101 +0,0 @@
-/*
- *  Copyright 2001-2004 Randolph Chung <tausq@debian.org>
- *
- *  Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the 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.
- *
- *   Notes:
- *   1. Only flat DMA is supported; s-g is not supported right now
- *
- *
-<jsm> tausq: Anyway, to set up sample rates for D to A, you just use the sample rate on the codec. For A to D, you need to set the codec always to 48K (using the split sample rate feature on the codec) and then set the resampler on the AD1889 to the sample rate you want.
-<jsm> Also, when changing the sample rate on the codec you need to power it down and re power it up for the change to take effect!
- *
- * $Id: ad1889.c,v 1.3 2002/10/19 21:31:44 grundler Exp $
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/sound.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-
-#include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include "ad1889.h"
-
-#define DBG(fmt, arg...) printk(fmt, ##arg)
-#define DEVNAME "ad1889"
-
-#define NR_HW_CH	4
-#define DAC_RUNNING	1
-#define ADC_RUNNING	2
-
-#define UNDERRUN(dev)	(0)
-
-#define AD1889_READW(dev,reg) readw(dev->regbase + reg)
-#define AD1889_WRITEW(dev,reg,val) writew((val), dev->regbase + reg)
-#define AD1889_READL(dev,reg) readl(dev->regbase + reg)
-#define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
-
-//now 100ms
-/* #define WAIT_10MS()	schedule_timeout(HZ/10) */
-#define WAIT_10MS()	do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
-
-/* currently only support a single device */
-static ad1889_dev_t *ad1889_dev = NULL;
-
-/************************* helper routines ***************************** */
-static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
-{
-	struct ac97_codec *ac97_codec = dev->ac97_codec;
-
-	DBG("Setting WAV rate to %d\n", rate);
-	dev->state[AD_WAV_STATE].dmabuf.rate = rate;
-	AD1889_WRITEW(dev, AD_DS_WAS, rate);
-
-	/* Cycle the DAC to enable the new rate */
-	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
-	WAIT_10MS();
-	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
-}
-
-static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
-{
-	u16 tmp;
-
-	DBG("Setting WAV format to 0x%x\n", fmt);
-
-	tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-	if (fmt & AFMT_S16_LE) {
-		//tmp |= 0x0100; /* set WA16 */
-		tmp |= 0x0300; /* set WA16 stereo */
-	} else if (fmt & AFMT_U8) {
-		tmp &= ~0x0100; /* clear WA16 */
-	} 
-	AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
-}
-
-static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
-{
-	u16 tmp;
-
-	DBG("Setting ADC format to 0x%x\n", fmt);
-
-	tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
-	if (fmt & AFMT_S16_LE) {
-		tmp |= 0x0100; /* set WA16 */
-	} else if (fmt & AFMT_U8) {
-		tmp &= ~0x0100; /* clear WA16 */
-	} 
-	AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
-}
-
-static void ad1889_start_wav(ad1889_state_t *state)
-{
-	unsigned long flags;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int cnt;
-	u16 tmp;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-
-	if (dmabuf->dma_len)	/* DMA already in flight */
-		goto skip_dma;
-
-	/* setup dma */
-	cnt = dmabuf->wr_ptr - dmabuf->rd_ptr;
-	if (cnt == 0)		/* done - don't need to do anything */
-		goto skip_dma;
-
-	/* If the wr_ptr has wrapped, only map to the end */
-	if (cnt < 0)
-		cnt = DMA_SIZE - dmabuf->rd_ptr;
-
-	dmabuf->dma_handle = pci_map_single(ad1889_dev->pci,
-					dmabuf->rawbuf + dmabuf->rd_ptr,
-					cnt, PCI_DMA_TODEVICE);
-	dmabuf->dma_len = cnt;
-	dmabuf->ready = 1;
-
-	DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
-	    dmabuf->rd_ptr, dmabuf->dma_len);
-
-        /* load up the current register set */
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
-
-	/* TODO: for now we load the base registers with the same thing */
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
-
-	/* and we're off to the races... */
-	AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
-	tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-	tmp |= 0x0400; /* set WAEN */
-	AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
-	(void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
-
-	dmabuf->enable |= DAC_RUNNING;
-
-skip_dma:
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-
-static void ad1889_stop_wav(ad1889_state_t *state)
-{
-	unsigned long flags;
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-
-	if (dmabuf->enable & DAC_RUNNING) {
-		u16 tmp;
-		unsigned long cnt = dmabuf->dma_len;
-
-		tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-		tmp &= ~0x0400; /* clear WAEN */
-		AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
-		(void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
-		pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle, 
-				cnt, PCI_DMA_TODEVICE);
-
-		dmabuf->enable &= ~DAC_RUNNING;
-
-		/* update dma pointers */
-		dmabuf->rd_ptr += cnt;
-		dmabuf->rd_ptr &= (DMA_SIZE - 1);
-
-		dmabuf->dma_handle = 0;
-		dmabuf->dma_len = 0;
-		dmabuf->ready = 0;
-
-		wake_up(&dmabuf->wait);
-	}
-
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-
-#if 0
-static void ad1889_startstop_adc(ad1889_state_t *state, int start)
-{
-	u16 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-	
-	tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
-	if (start) {
-		state->dmabuf.enable |= ADC_RUNNING;
-		tmp |= 0x0004; /* set ADEN */
-	} else {
-		state->dmabuf.enable &= ~ADC_RUNNING;
-		tmp &= ~0x0004; /* clear ADEN */
-	}
-	AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
-
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-#endif
-
-static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
-{
-	ad1889_dev_t *dev;
-	struct dmabuf *dmabuf;
-	int i;
-
-	if ((dev = kzalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL)
-		return NULL;
-	spin_lock_init(&dev->lock);
-	dev->pci = pci;
-
-	for (i = 0; i < AD_MAX_STATES; i++) {
-		dev->state[i].card = dev;
-		mutex_init(&dev->state[i].mutex);
-		init_waitqueue_head(&dev->state[i].dmabuf.wait);
-	}
-
-	/* allocate dma buffer */
-
-	for (i = 0; i < AD_MAX_STATES; i++) {
-		dmabuf = &dev->state[i].dmabuf;
-		dmabuf->rawbuf = kmalloc(DMA_SIZE, GFP_KERNEL|GFP_DMA);
-		if (!dmabuf->rawbuf)
-			goto err_free_dmabuf;
-		dmabuf->rawbuf_size = DMA_SIZE;
-		dmabuf->dma_handle = 0;
-		dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
-		dmabuf->ready = 0;
-		dmabuf->rate = 48000;
-	}
-	return dev;
-
-err_free_dmabuf:
-	while (--i >= 0)
-		kfree(dev->state[i].dmabuf.rawbuf);
-	kfree(dev);
-	return NULL;
-}
-
-static void ad1889_free_dev(ad1889_dev_t *dev)
-{
-	int j;
-	struct dmabuf *dmabuf;
-
-	if (dev == NULL) 
-		return;
-
-	if (dev->ac97_codec)
-		ac97_release_codec(dev->ac97_codec);
-
-	for (j = 0; j < AD_MAX_STATES; j++) {
-		dmabuf = &dev->state[j].dmabuf;
-		kfree(dmabuf->rawbuf);
-	}
-
-	kfree(dev);
-}
-
-static inline void ad1889_trigger_playback(ad1889_dev_t *dev)
-{
-#if 0
-	u32 val;
-	struct dmabuf *dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
-#endif
-
-	ad1889_start_wav(&dev->state[AD_WAV_STATE]);
-}
-
-static int ad1889_read_proc (char *page, char **start, off_t off,
-			     int count, int *eof, void *data)
-{
-	char *out = page;
-	int len, i;
-	ad1889_dev_t *dev = data;
-	ad1889_reg_t regs[] = {
-		{ "WSMC", AD_DS_WSMC, 16 },
-		{ "RAMC", AD_DS_RAMC, 16 },
-		{ "WADA", AD_DS_WADA, 16 },
-		{ "SYDA", AD_DS_SYDA, 16 },
-		{ "WAS", AD_DS_WAS, 16 },
-		{ "RES", AD_DS_RES, 16 },
-		{ "CCS", AD_DS_CCS, 16 },
-		{ "ADCBA", AD_DMA_ADCBA, 32 },
-		{ "ADCCA", AD_DMA_ADCCA, 32 },
-		{ "ADCBC", AD_DMA_ADCBC, 32 },
-		{ "ADCCC", AD_DMA_ADCCC, 32 },
-		{ "ADCIBC", AD_DMA_ADCIBC, 32 },
-		{ "ADCICC", AD_DMA_ADCICC, 32 },
-		{ "ADCCTRL", AD_DMA_ADCCTRL, 16 },
-		{ "WAVBA", AD_DMA_WAVBA, 32 },
-		{ "WAVCA", AD_DMA_WAVCA, 32 },
-		{ "WAVBC", AD_DMA_WAVBC, 32 },
-		{ "WAVCC", AD_DMA_WAVCC, 32 },
-		{ "WAVIBC", AD_DMA_WAVIBC, 32 },
-		{ "WAVICC", AD_DMA_WAVICC, 32 },
-		{ "WAVCTRL", AD_DMA_WAVCTRL, 16 },
-		{ "DISR", AD_DMA_DISR, 32 },
-		{ "CHSS", AD_DMA_CHSS, 32 },
-		{ "IPC", AD_GPIO_IPC, 16 },
-		{ "OP", AD_GPIO_OP, 16 },
-		{ "IP", AD_GPIO_IP, 16 },
-		{ "ACIC", AD_AC97_ACIC, 16 },
-		{ "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
-		{ "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
-		{ "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
-		{ "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
-		{ "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
-		{ "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
-		{ "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
-		{ "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
-		{ "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
-		{ "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
-		{ "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
-		{ "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
-		{ "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
-		{ "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
-		{ "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
-		{ "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
-		{ "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
-		{ "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
-		{ "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
-		{ "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
-		{ NULL }
-	};
-
-	if (dev == NULL)
-		return -ENODEV;
-
-	for (i = 0; regs[i].name != 0; i++)
-		out += sprintf(out, "%s: 0x%0*x\n", regs[i].name, 
-			regs[i].width >> 2, 
-			(regs[i].width == 16 
-			 	? AD1889_READW(dev, regs[i].offset)
-				: AD1889_READL(dev, regs[i].offset)));
-
-	for (i = 0; i < AD_MAX_STATES; i++) {
-		out += sprintf(out, "DMA status for %s:\n", 
-			(i == AD_WAV_STATE ? "WAV" : "ADC")); 
-		out += sprintf(out, "\t\t0x%p (IOVA: 0x%llu)\n",
-			dev->state[i].dmabuf.rawbuf,
-			(unsigned long long)dev->state[i].dmabuf.dma_handle);
-
-		out += sprintf(out, "\tread ptr: offset %u\n", 
-			(unsigned int)dev->state[i].dmabuf.rd_ptr);
-		out += sprintf(out, "\twrite ptr: offset %u\n", 
-			(unsigned int)dev->state[i].dmabuf.wr_ptr);
-		out += sprintf(out, "\tdma len: offset %u\n", 
-			(unsigned int)dev->state[i].dmabuf.dma_len);
-	}
-
-	len = out - page - off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0) return 0;
-	} else {
-		len = count;
-	}
-	*start = page + off;
-	return len;
-}
-
-/***************************** DMA interfaces ************************** */
-#if 0
-static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 offset;
-
-	if (!(dmabuf->enable & (DAC_RUNNING | ADC_RUNNING))) {
-		printk(KERN_ERR DEVNAME ": get_dma_addr called without dma enabled\n");
-		return 0;
-	}
-	
-	if (dmabuf->enable & DAC_RUNNING)
-		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
-	else
-		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
-
-	return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
-}
-
-static void ad1889_update_ptr(ad1889_dev_t *dev, int wake)
-{
-	ad1889_state_t *state;
-	struct dmabuf *dmabuf;
-	unsigned long hwptr;
-	int diff;
-
-	/* check ADC first */
-	state = &dev->adc_state;
-	dmabuf = &state->dmabuf;
-	if (dmabuf->enable & ADC_RUNNING) {
-		hwptr = ad1889_get_dma_addr(state);
-		diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-
-		dmabuf->hwptr = hwptr;
-		dmabuf->total_bytes += diff;
-		dmabuf->count += diff;
-		if (dmabuf->count > dmabuf->dmasize)
-			dmabuf->count = dmabuf->dmasize;
-
-		if (dmabuf->mapped) {
-			if (wake & dmabuf->count >= dmabuf->fragsize)
-				wake_up(&dmabuf->wait);
-		} else {
-			if (wake & dmabuf->count > 0)
-				wake_up(&dmabuf->wait);
-		}
-	}
-
-	/* check DAC */
-	state = &dev->wav_state;
-	dmabuf = &state->dmabuf;
-	if (dmabuf->enable & DAC_RUNNING) {
-XXX
-
-}
-#endif
-
-/************************* /dev/dsp interfaces ************************* */
-
-static ssize_t ad1889_read(struct file *file, char __user *buffer, size_t count,
-	loff_t *ppos)
-{
-	return 0;
-}
-
-static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t count,
-	loff_t *ppos)
-{
-	ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
-	ad1889_state_t *state = &dev->state[AD_WAV_STATE];
-	volatile struct dmabuf *dmabuf = &state->dmabuf;
-	ssize_t ret = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	mutex_lock(&state->mutex);
-#if 0
-	if (dmabuf->mapped) {
-		ret = -ENXIO;
-		goto err1;
-	}
-#endif
-	if (!access_ok(VERIFY_READ, buffer, count)) {
-		ret = -EFAULT;
-		goto err1;
-	}
-
-	add_wait_queue(&state->dmabuf.wait, &wait);
-
-	/* start filling dma buffer.... */
-	while (count > 0) {
-		long rem;
-		long cnt = count;
-		unsigned long flags;
-
-		for (;;) {
-			long used_bytes;
-			long timeout;	/* max time for DMA in jiffies */
-
-			/* buffer is full if wr catches up to rd */
-			spin_lock_irqsave(&state->card->lock, flags);
-			used_bytes = dmabuf->wr_ptr - dmabuf->rd_ptr;
-			timeout = (dmabuf->dma_len * HZ) / dmabuf->rate;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-
-			/* adjust for buffer wrap around */
-			used_bytes = (used_bytes + DMA_SIZE) & (DMA_SIZE - 1);
-
-			/* If at least one page unused */
-			if (used_bytes < (DMA_SIZE - 0x1000))
-				break;
-
-			/* dma buffer full */
-
-			if (file->f_flags & O_NONBLOCK) {
-				ret = -EAGAIN;
-				goto err2;
-			}
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(timeout + 1);
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				goto err2;
-			}
-		}
-
-		/* watch out for wrapping around static buffer */
-		spin_lock_irqsave(&state->card->lock, flags);
-		rem = DMA_SIZE - dmabuf->wr_ptr;
-		if (cnt > rem)
-			cnt = rem;
-
-		rem = dmabuf->wr_ptr;
-
-		/* update dma pointers */
-		dmabuf->wr_ptr += cnt;
-		dmabuf->wr_ptr &= DMA_SIZE - 1;	/* wrap ptr if necessary */
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* transfer unwrapped chunk */
-		if (copy_from_user(dmabuf->rawbuf + rem, buffer, cnt)) {
-			ret = -EFAULT;
-			goto err2;
-		}
-
-		DBG("Writing 0x%lx bytes to +0x%lx\n", cnt, rem);
-
-		/* update counters */
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-
-		/* we have something to play - go play it! */
-		ad1889_trigger_playback(dev);
-	}
-
-err2:
-	remove_wait_queue(&state->dmabuf.wait, &wait);
-err1:
-	mutex_unlock(&state->mutex);
-	return ret;
-}
-
-static unsigned int ad1889_poll(struct file *file, struct poll_table_struct *wait)
-{
-	unsigned int mask = 0;
-#if 0
-	ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
-	ad1889_state_t *state = NULL;
-	struct dmabuf *dmabuf;
-	unsigned long flags;
-	
-	if (!(file->f_mode & (FMODE_READ | FMODE_WRITE)))
-		return -EINVAL;
-
-	if (file->f_mode & FMODE_WRITE) {
-		state = &dev->state[AD_WAV_STATE];
-		if (!state) return 0;
-		dmabuf = &state->dmabuf;
-		poll_wait(file, &dmabuf->wait, wait);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		state = &dev->state[AD_ADC_STATE];
-		if (!state) return 0;
-		dmabuf = &state->dmabuf;
-		poll_wait(file, &dmabuf->wait, wait);
-	}
-
-	spin_lock_irqsave(&dev->lock, flags);
-	ad1889_update_ptr(dev, 0);
-
-	if (file->f_mode & FMODE_WRITE) {
-		state = &dev->state[WAV_STATE];
-		dmabuf = &state->dmabuf;
-		if (dmabuf->mapped) {
-			if (dmabuf->count >= (int)dmabuf->fragsize)
-				mask |= POLLOUT | POLLWRNORM;
-		} else {
-			if ((int)dmabuf->dmasize >= dmabuf->count + 
-				(int)dmabuf->fragsize)
-				mask |= POLLOUT | POLLWRNORM;
-		}
-	}
-
-	if (file ->f_mode & FMODE_READ) {
-		state = &dev->state[AD_ADC_STATE];
-		dmabuf = &state->dmabuf;
-		if (dmabuf->count >= (int)dmabuf->fragsize)
-			mask |= POLLIN | POLLRDNORM;
-	}
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-#endif
-	return mask;
-}
-
-static int ad1889_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	return 0;
-}
-
-static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-	unsigned long arg)
-{
-	int val = 0;
-	ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
-	struct dmabuf *dmabuf;
-	audio_buf_info abinfo;
-	int __user *p = (int __user *)arg;
-
-	DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
-
-	switch (cmd)
-	{
-	case OSS_GETVERSION:
-		return put_user(SOUND_VERSION, p);
-
-	case SNDCTL_DSP_RESET:
-		break;
-
-	case SNDCTL_DSP_SYNC:
-		break;
-
-	case SNDCTL_DSP_SPEED:
-		/* set sampling rate */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val > 5400 && val < 48000)
-		{
-			if (file->f_mode & FMODE_WRITE)
-				AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
-			if (file->f_mode & FMODE_READ)
-				AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
-		}
-		return 0;
-
-	case SNDCTL_DSP_STEREO: /* undocumented? */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_READ) {
-			val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-			if (val) {
-				val |= 0x0200;  /* set WAST */
-			} else {
-				val &= ~0x0200; /* clear WAST */
-			}
-			AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
-			if (val) {
-				val |= 0x0002;  /* set ADST */
-			} else {
-				val &= ~0x0002; /* clear ADST */
-			}
-			AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
-		}
-
-		return 0;
-
-	case SNDCTL_DSP_GETBLKSIZE:
-		return put_user(DMA_SIZE, p);
-
-	case SNDCTL_DSP_GETFMTS:
-		return put_user(AFMT_S16_LE|AFMT_U8, p);
-
-	case SNDCTL_DSP_SETFMT:
-		if (get_user(val, p))
-			return -EFAULT;
-
-		if (val == 0) {
-			if (file->f_mode & FMODE_READ) 
-				ad1889_set_adc_fmt(dev, val);
-
-			if (file->f_mode & FMODE_WRITE) 
-				ad1889_set_wav_fmt(dev, val);
-		} else {
-			val = AFMT_S16_LE | AFMT_U8;
-		}
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_CHANNELS:
-		break;
-
-	case SNDCTL_DSP_POST:
-		/* send all data to device */
-		break;
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		break;
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		/* not supported; uses fixed fragment sizes */
-		return put_user(DMA_SIZE, p);
-
-	case SNDCTL_DSP_GETOSPACE:
-	case SNDCTL_DSP_GETISPACE:
-		/* space left in dma buffers */
-		if (cmd == SNDCTL_DSP_GETOSPACE)
-			dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
-		else
-			dmabuf = &dev->state[AD_ADC_STATE].dmabuf;
-		abinfo.fragments = 1;
-		abinfo.fragstotal = 1;
-		abinfo.fragsize = DMA_SIZE;
-		abinfo.bytes = DMA_SIZE;
-		return copy_to_user(p, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-
-	case SNDCTL_DSP_GETCAPS:
-		return put_user(0, p);
-
-	case SNDCTL_DSP_GETTRIGGER:
-	case SNDCTL_DSP_SETTRIGGER:
-		break;
-
-	case SNDCTL_DSP_GETIPTR:
-	case SNDCTL_DSP_GETOPTR:
-		break;
-
-	case SNDCTL_DSP_SETDUPLEX:
-		break;
-	
-	case SNDCTL_DSP_GETODELAY:
-		break;
-
-	case SOUND_PCM_READ_RATE:
-		return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
-
-	case SOUND_PCM_READ_CHANNELS:
-	case SOUND_PCM_READ_BITS:
-		break;
-
-	case SNDCTL_DSP_MAPINBUF:
-	case SNDCTL_DSP_MAPOUTBUF:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_WRITE_FILTER:
-	case SOUND_PCM_READ_FILTER:
-		break;
-
-	default:
-		break;
-	}
-
-	return -ENOTTY;
-}
-
-static int ad1889_open(struct inode *inode, struct file *file)
-{
-	/* check minor; only support /dev/dsp atm */
-	if (iminor(inode) != 3)
-		return -ENXIO;
-	
-	file->private_data = ad1889_dev;
-
-	ad1889_set_wav_rate(ad1889_dev, 48000);
-	ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
-	AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
-	return nonseekable_open(inode, file);
-}
-
-static int ad1889_release(struct inode *inode, struct file *file)
-{
-	/* if we have state free it here */
-	return 0;
-}
-
-static const struct file_operations ad1889_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= ad1889_read,
-	.write		= ad1889_write,
-	.poll		= ad1889_poll,
-	.ioctl		= ad1889_ioctl,
-	.mmap		= ad1889_mmap,
-	.open		= ad1889_open,
-	.release	= ad1889_release,
-};
-
-/************************* /dev/mixer interfaces ************************ */
-static int ad1889_mixer_open(struct inode *inode, struct file *file)
-{
-	if (ad1889_dev->ac97_codec->dev_mixer != iminor(inode))
-		return -ENODEV;
-
-	file->private_data = ad1889_dev->ac97_codec;
-	return 0;
-}
-
-static int ad1889_mixer_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static int ad1889_mixer_ioctl(struct inode *inode, struct file *file,
-	unsigned int cmd, unsigned long arg)
-{
-	struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
-	return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static const struct file_operations ad1889_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.ioctl		= ad1889_mixer_ioctl,
-	.open		= ad1889_mixer_open,
-	.release	= ad1889_mixer_release,
-};
-
-/************************* AC97 interfaces ****************************** */
-static void ad1889_codec_write(struct ac97_codec *ac97, u8 reg, u16 val)
-{
-	ad1889_dev_t *dev = ac97->private_data;
-
-	//DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
-	AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
-}
-
-static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
-{
-	ad1889_dev_t *dev = ac97->private_data;
-	//DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
-	return AD1889_READW(dev, AD_AC97_BASE + reg);
-}	
-
-static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
-{
-	struct ac97_codec *ac97;
-	u16 eid;
-
-	if ((ac97 = ac97_alloc_codec()) == NULL) 
-		return -ENOMEM;
-
-	ac97->private_data = dev;
-	ac97->id = id;
-
-	ac97->codec_read = ad1889_codec_read;
-	ac97->codec_write = ad1889_codec_write;
-
-	if (ac97_probe_codec(ac97) == 0) {
-		printk(DEVNAME ": ac97_probe_codec failed\n");
-		goto out_free;
-	}
-
-	eid = ad1889_codec_read(ac97, AC97_EXTENDED_ID);
-	if (eid == 0xffff) {
-		printk(KERN_WARNING DEVNAME ": no codec attached?\n");
-		goto out_free;
-	}
-
-	dev->ac97_features = eid;
-
-	if ((ac97->dev_mixer = register_sound_mixer(&ad1889_mixer_fops, -1)) < 0) {
-		printk(KERN_ERR DEVNAME ": cannot register mixer\n");
-		goto out_free;
-	}
-
-	dev->ac97_codec = ac97;
-	return 0;
-
-out_free:
-	ac97_release_codec(ac97);
-	return -ENODEV;
-}
-
-static int ad1889_aclink_reset(struct pci_dev * pcidev)
-{
-	u16 stat;
-	int retry = 200;
-	ad1889_dev_t *dev = pci_get_drvdata(pcidev);
-
-	AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
-	AD1889_READW(dev, AD_DS_CCS);
-
-	WAIT_10MS();
-
-	stat = AD1889_READW(dev, AD_AC97_ACIC);
-	stat |= 0x0002;				/* Reset Disable */
-	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
-	(void) AD1889_READW(dev, AD_AC97_ACIC);	/* flush posted write */
-
-	udelay(10);
-
-	stat = AD1889_READW(dev, AD_AC97_ACIC);
-	stat |= 0x0001;				/* Interface Enable */
-	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
-
-	do {
-		if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000)	/* Ready */
-			break;
-		WAIT_10MS();
-		retry--;
-	} while (retry > 0);
-
-	if (!retry) {
-		printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
-			    AD1889_READW(dev, AD_AC97_ACIC));
-		return -EBUSY;
-	}
-
-	/* TODO reset AC97 codec */
-	/* TODO set wave/adc pci ctrl status */
-
-	stat = AD1889_READW(dev, AD_AC97_ACIC);
-	stat |= 0x0004;				/* Audio Stream Output Enable */
-	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
-	return 0;
-}
-
-/************************* PCI interfaces ****************************** */
-/* PCI device table */
-static struct pci_device_id ad1889_id_tbl[] = {
-	{ PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS, PCI_ANY_ID, 
-	  PCI_ANY_ID, 0, 0, (unsigned long)DEVNAME },
-	{ },
-};
-MODULE_DEVICE_TABLE(pci, ad1889_id_tbl);
-
-static irqreturn_t ad1889_interrupt(int irq, void *dev_id)
-{
-	u32 stat;
-	ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
-
-	stat = AD1889_READL(dev, AD_DMA_DISR);
-
-	/* clear ISR */
-	AD1889_WRITEL(dev, AD_DMA_DISR, stat);
-
-	if (stat & 0x8) {		/* WAVI */
-		DBG("WAV interrupt\n");
-		dev->stats.wav_intrs++;
-		if (dev->state[AD_WAV_STATE].dmabuf.ready) {
-			ad1889_stop_wav(&dev->state[AD_WAV_STATE]);	/* clean up */
-			ad1889_start_wav(&dev->state[AD_WAV_STATE]);	/* start new */
-		}
-	}
-
-	if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
-		DBG("ADC interrupt\n");
-		dev->stats.adc_intrs++;
-	}
-	if(stat)
-		return IRQ_HANDLED;
-	return IRQ_NONE;
-}
-
-static void ad1889_initcfg(ad1889_dev_t *dev)
-{
-	u16 tmp16;
-	u32 tmp32;
-
-	/* make sure the interrupt bits are setup the way we want */
-	tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
-	tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
-	tmp32 |= 0x6;  /* intr on count, loop */
-	AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
-
-	/* unmute... */
-	tmp16 = AD1889_READW(dev, AD_DS_WADA);
-	tmp16 &= ~0x8080;
-	AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
-}
-
-static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
-{
-	int err;
-	ad1889_dev_t *dev;
-	unsigned long bar;
-	struct proc_dir_entry *proc_root = NULL;
-
-	if ((err = pci_enable_device(pcidev)) != 0) {
-		printk(KERN_ERR DEVNAME ": pci_enable_device failed\n");
-		return err;
-	}
-
-	pci_set_master(pcidev);
-	if ((dev = ad1889_alloc_dev(pcidev)) == NULL) {
-		printk(KERN_ERR DEVNAME ": cannot allocate memory for device\n");
-		return -ENOMEM;
-	}
-	pci_set_drvdata(pcidev, dev);
-	bar = pci_resource_start(pcidev, 0);
-	
-        if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
-		printk(KERN_ERR DEVNAME ": memory region not assigned\n");
-		goto out1;
-	}
-
-	if (pci_request_region(pcidev, 0, DEVNAME)) {
-		printk(KERN_ERR DEVNAME ": unable to request memory region\n");
-		goto out1;
-	}
-
-	dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
-	if (!dev->regbase) {
-		printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
-		goto out2;
-	}
-
-	if (request_irq(pcidev->irq, ad1889_interrupt, IRQF_SHARED, DEVNAME, dev) != 0) {
-		printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
-		goto out3;
-	}
-
-	printk(KERN_INFO DEVNAME ": %s at %p IRQ %d\n",
-		(char *)ent->driver_data, dev->regbase, pcidev->irq);
-
-	if (ad1889_aclink_reset(pcidev) != 0)
-		goto out4;
-
-	/* register /dev/dsp */
-	if ((dev->dev_audio = register_sound_dsp(&ad1889_fops, -1)) < 0) {
-		printk(KERN_ERR DEVNAME ": cannot register /dev/dsp\n");
-		goto out4;
-	}
-
-	if ((err = ad1889_ac97_init(dev, 0)) != 0)
-		goto out5;
-
-	/* XXX: cleanups */
-	if (((proc_root = proc_mkdir("driver/ad1889", NULL)) == NULL) ||
-	    create_proc_read_entry("ac97", S_IFREG|S_IRUGO, proc_root, ac97_read_proc, dev->ac97_codec) == NULL ||
-	    create_proc_read_entry("info", S_IFREG|S_IRUGO, proc_root, ad1889_read_proc, dev) == NULL) 
-		goto out5;
-	
-	ad1889_initcfg(dev);
-
-	//DBG(DEVNAME ": Driver initialization done!\n");
-
-	ad1889_dev = dev;
-
-	return 0;
-
-out5:
-	unregister_sound_dsp(dev->dev_audio);
-out4:
-	free_irq(pcidev->irq, dev);
-out3:
-	iounmap(dev->regbase);
-out2:
-	pci_release_region(pcidev, 0);
-out1:
-	ad1889_free_dev(dev);
-	pci_set_drvdata(pcidev, NULL);
-
-	return -ENODEV;
-}
-
-static void __devexit ad1889_remove(struct pci_dev *pcidev)
-{
-	ad1889_dev_t *dev = pci_get_drvdata(pcidev);
-
-	if (dev == NULL) return;
-	
-	unregister_sound_mixer(dev->ac97_codec->dev_mixer);
-	unregister_sound_dsp(dev->dev_audio);
-	free_irq(pcidev->irq, dev);
-	iounmap(dev->regbase);
-	pci_release_region(pcidev, 0);
-
-	/* any hw programming needed? */
-	ad1889_free_dev(dev);
-	pci_set_drvdata(pcidev, NULL);
-}
-
-MODULE_AUTHOR("Randolph Chung");
-MODULE_DESCRIPTION("Analog Devices AD1889 PCI Audio");
-MODULE_LICENSE("GPL");
-
-static struct pci_driver ad1889_driver = {
-	.name		= DEVNAME,
-	.id_table	= ad1889_id_tbl,
-	.probe		= ad1889_probe,
-	.remove		= __devexit_p(ad1889_remove),
-};
-
-static int __init ad1889_init_module(void)
-{
-	return pci_register_driver(&ad1889_driver);
-}
-
-static void ad1889_exit_module(void)
-{
-	pci_unregister_driver(&ad1889_driver);
-	return;
-}
-
-module_init(ad1889_init_module);
-module_exit(ad1889_exit_module);
diff --git a/sound/oss/ad1889.h b/sound/oss/ad1889.h
deleted file mode 100644
index 0991376..0000000
--- a/sound/oss/ad1889.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _AD1889_H_
-#define _AD1889_H_
-
-#define AD_DS_WSMC	0x00	/* DMA input wave/syn mixer control */
-#define AD_DS_RAMC	0x02	/* DMA output resamp/ADC mixer control */
-#define AD_DS_WADA	0x04	/* DMA input wave attenuation */
-#define AD_DS_SYDA	0x06	/* DMA input syn attentuation */
-#define AD_DS_WAS	0x08	/* wave input sample rate */
-#define AD_DS_RES	0x0a	/* resampler output sample rate */
-#define AD_DS_CCS	0x0c	/* chip control/status */
-
-#define AD_DMA_RESBA	0x40	/* RES base addr */
-#define AD_DMA_RESCA	0x44	/* RES current addr */
-#define AD_DMA_RESBC	0x48	/* RES base cnt */
-#define AD_DMA_RESCC	0x4c	/* RES current count */
-#define AD_DMA_ADCBA	0x50	/* ADC */
-#define AD_DMA_ADCCA	0x54
-#define AD_DMA_ADCBC	0x58
-#define AD_DMA_ADCCC	0x5c
-#define AD_DMA_SYNBA	0x60	/* SYN */
-#define AD_DMA_SYNCA	0x64
-#define AD_DMA_SYNBC	0x68
-#define AD_DMA_SYNCC	0x6c
-#define AD_DMA_WAVBA	0x70	/* WAV */
-#define AD_DMA_WAVCA	0x74
-#define AD_DMA_WAVBC	0x78
-#define AD_DMA_WAVCC	0x7c
-#define AD_DMA_RESICC	0x80	/* RES interrupt current count */
-#define AD_DMA_RESIBC	0x84	/* RES interrupt base count */
-#define AD_DMA_ADCICC	0x88	/* ADC interrupt current count */
-#define AD_DMA_ADCIBC	0x8c	/* ADC interrupt base count */
-#define AD_DMA_SYNICC	0x90	/* SYN interrupt current count */
-#define AD_DMA_SYNIBC	0x94	/* SYN interrupt base count */
-#define AD_DMA_WAVICC	0x98	/* WAV interrupt current count */
-#define AD_DMA_WAVIBC	0x9c	/* WAV interrupt base count */
-#define AD_DMA_RESCTRL	0xa0	/* RES PCI control/status */
-#define AD_DMA_ADCCTRL	0xa8	/* ADC PCI control/status */
-#define AD_DMA_SYNCTRL	0xb0	/* SYN PCI control/status */
-#define AD_DMA_WAVCTRL	0xb8	/* WAV PCI control/status */
-#define AD_DMA_DISR	0xc0	/* PCI DMA intr status */
-#define AD_DMA_CHSS	0xc4	/* PCI DMA channel stop status */
-
-#define AD_GPIO_IPC	0xc8	/* IO port ctrl */
-#define AD_GPIO_OP	0xca	/* IO output status */
-#define AD_GPIO_IP	0xcc	/* IO input status */
-
-/* AC97 registers, 0x100 - 0x17f; see ac97.h */
-#define AD_AC97_BASE    0x100   /* ac97 base register */
-#define AD_AC97_ACIC	0x180	/* AC Link interface ctrl */
-
-/* OPL3; BAR1 */
-#define AD_OPL_M0AS	0x00	/* Music0 address/status */
-#define AD_OPL_M0DATA	0x01	/* Music0 data */
-#define AD_OPL_M1A	0x02	/* Music1 address */
-#define AD_OPL_M1DATA	0x03	/* Music1 data */
-/* 0x04-0x0f reserved */
-
-/* MIDI; BAR2 */
-#define AD_MIDA		0x00	/* MIDI data */
-#define AD_MISC		0x01	/* MIDI status/cmd */
-/* 0x02-0xff reserved */
-
-#define AD_DS_IOMEMSIZE	512
-#define AD_OPL_MEMSIZE	16
-#define AD_MIDI_MEMSIZE	16
-
-#define AD_WAV_STATE	0
-#define AD_ADC_STATE	1
-#define AD_MAX_STATES	2
-
-#define DMA_SIZE	(128*1024)
-
-#define DMA_FLAG_MAPPED	1
-
-struct ad1889_dev;
-
-typedef struct ad1889_state {
-	struct ad1889_dev *card;
-
-	mode_t open_mode;
-	struct dmabuf {
-		unsigned int rate;
-		unsigned char fmt, enable;
-
-		/* buf management */
-		size_t rawbuf_size;
-		void *rawbuf;
-		dma_addr_t dma_handle;	/* mapped address */
-		unsigned long dma_len;	/* number of bytes mapped */
-
-		/* indexes into rawbuf for setting up DMA engine */
-		volatile unsigned long rd_ptr, wr_ptr;
-
-		wait_queue_head_t wait; /* to wait for buf servicing */
-
-		/* OSS bits */
-		unsigned int mapped:1;
-		unsigned int ready:1;
-		unsigned int ossfragshift;
-		int ossmaxfrags;
-		unsigned int subdivision;
-	} dmabuf;
-
-	struct mutex mutex;
-} ad1889_state_t;
-
-typedef struct ad1889_dev {
-	void __iomem *regbase;
-	struct pci_dev *pci;
-	
-	spinlock_t lock;
-
-	int dev_audio;
-
-	/* states; one per channel; right now only WAV and ADC */
-	struct ad1889_state state[AD_MAX_STATES];
-
-	/* AC97 codec */
-	struct ac97_codec *ac97_codec;
-	u16 ac97_features;
-
-	/* debugging stuff */
-	struct stats {
-		unsigned int wav_intrs, adc_intrs;
-		unsigned int blocks, underrun, error;
-	} stats;
-} ad1889_dev_t;
-
-typedef struct ad1889_reg {
-	const char *name;
-	int offset;
-	int width;
-} ad1889_reg_t;
-
-#endif
diff --git a/sound/oss/adlib_card.c b/sound/oss/adlib_card.c
deleted file mode 100644
index c9a7c9b..0000000
--- a/sound/oss/adlib_card.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * sound/oss/adlib_card.c
- *
- * Detection routine for the AdLib card.
- *
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "sound_config.h"
-
-#include "opl3.h"
-
-static void __init attach_adlib_card(struct address_info *hw_config)
-{
-	hw_config->slots[0] = opl3_init(hw_config->io_base, hw_config->osp, THIS_MODULE);
-}
-
-static int __init probe_adlib(struct address_info *hw_config)
-{
-	return opl3_detect(hw_config->io_base, hw_config->osp);
-}
-
-static struct address_info cfg;
-
-static int __initdata io = -1;
-
-module_param(io, int, 0);
-
-static int __init init_adlib(void)
-{
-	cfg.io_base = io;
-
-	if (cfg.io_base == -1) {
-		printk(KERN_ERR "adlib: must specify I/O address.\n");
-		return -EINVAL;
-	}
-	if (probe_adlib(&cfg) == 0)
-		return -ENODEV;
-	attach_adlib_card(&cfg);
-
-	return 0;
-}
-
-static void __exit cleanup_adlib(void)
-{
-	sound_unload_synthdev(cfg.slots[0]);
-	
-}
-
-module_init(init_adlib);
-module_exit(cleanup_adlib);
-
-#ifndef MODULE
-static int __init setup_adlib(char *str)
-{
-        /* io */
-	int ints[2];
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io = ints[1];
-
-	return 1;
-}
-__setup("adlib=", setup_adlib);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/cs461x.h b/sound/oss/cs461x.h
deleted file mode 100644
index 0ce4133..0000000
--- a/sound/oss/cs461x.h
+++ /dev/null
@@ -1,1691 +0,0 @@
-#ifndef __CS461X_H
-#define __CS461X_H
-
-/*
- *  Copyright (c) by Cirrus Logic Corporation <pcaudio@crystal.cirrus.com>
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *  Definitions for Cirrus Logic CS461x chips
- *
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the 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 PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS            0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4610
-#define PCI_DEVICE_ID_CIRRUS_4610       0x6001
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4612
-#define PCI_DEVICE_ID_CIRRUS_4612       0x6003
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4615
-#define PCI_DEVICE_ID_CIRRUS_4615       0x6004
-#endif
-
-/*
- *  Direct registers
- */
-
-/*
- *  The following define the offsets of the registers accessed via base address
- *  register zero on the CS461x part.
- */
-#define BA0_HISR				0x00000000
-#define BA0_HSR0                                0x00000004
-#define BA0_HICR                                0x00000008
-#define BA0_DMSR                                0x00000100
-#define BA0_HSAR                                0x00000110
-#define BA0_HDAR                                0x00000114
-#define BA0_HDMR                                0x00000118
-#define BA0_HDCR                                0x0000011C
-#define BA0_PFMC                                0x00000200
-#define BA0_PFCV1                               0x00000204
-#define BA0_PFCV2                               0x00000208
-#define BA0_PCICFG00                            0x00000300
-#define BA0_PCICFG04                            0x00000304
-#define BA0_PCICFG08                            0x00000308
-#define BA0_PCICFG0C                            0x0000030C
-#define BA0_PCICFG10                            0x00000310
-#define BA0_PCICFG14                            0x00000314
-#define BA0_PCICFG18                            0x00000318
-#define BA0_PCICFG1C                            0x0000031C
-#define BA0_PCICFG20                            0x00000320
-#define BA0_PCICFG24                            0x00000324
-#define BA0_PCICFG28                            0x00000328
-#define BA0_PCICFG2C                            0x0000032C
-#define BA0_PCICFG30                            0x00000330
-#define BA0_PCICFG34                            0x00000334
-#define BA0_PCICFG38                            0x00000338
-#define BA0_PCICFG3C                            0x0000033C
-#define BA0_CLKCR1                              0x00000400
-#define BA0_CLKCR2                              0x00000404
-#define BA0_PLLM                                0x00000408
-#define BA0_PLLCC                               0x0000040C
-#define BA0_FRR                                 0x00000410 
-#define BA0_CFL1                                0x00000414
-#define BA0_CFL2                                0x00000418
-#define BA0_SERMC1                              0x00000420
-#define BA0_SERMC2                              0x00000424
-#define BA0_SERC1                               0x00000428
-#define BA0_SERC2                               0x0000042C
-#define BA0_SERC3                               0x00000430
-#define BA0_SERC4                               0x00000434
-#define BA0_SERC5                               0x00000438
-#define BA0_SERBSP                              0x0000043C
-#define BA0_SERBST                              0x00000440
-#define BA0_SERBCM                              0x00000444
-#define BA0_SERBAD                              0x00000448
-#define BA0_SERBCF                              0x0000044C
-#define BA0_SERBWP                              0x00000450
-#define BA0_SERBRP                              0x00000454
-#ifndef NO_CS4612
-#define BA0_ASER_FADDR                          0x00000458
-#endif
-#define BA0_ACCTL                               0x00000460
-#define BA0_ACSTS                               0x00000464
-#define BA0_ACOSV                               0x00000468
-#define BA0_ACCAD                               0x0000046C
-#define BA0_ACCDA                               0x00000470
-#define BA0_ACISV                               0x00000474
-#define BA0_ACSAD                               0x00000478
-#define BA0_ACSDA                               0x0000047C
-#define BA0_JSPT                                0x00000480
-#define BA0_JSCTL                               0x00000484
-#define BA0_JSC1                                0x00000488
-#define BA0_JSC2                                0x0000048C
-#define BA0_MIDCR                               0x00000490
-#define BA0_MIDSR                               0x00000494
-#define BA0_MIDWP                               0x00000498
-#define BA0_MIDRP                               0x0000049C
-#define BA0_JSIO                                0x000004A0
-#ifndef NO_CS4612
-#define BA0_ASER_MASTER                         0x000004A4
-#endif
-#define BA0_CFGI                                0x000004B0
-#define BA0_SSVID                               0x000004B4
-#define BA0_GPIOR                               0x000004B8
-#ifndef NO_CS4612
-#define BA0_EGPIODR                             0x000004BC
-#define BA0_EGPIOPTR                            0x000004C0
-#define BA0_EGPIOTR                             0x000004C4
-#define BA0_EGPIOWR                             0x000004C8
-#define BA0_EGPIOSR                             0x000004CC
-#define BA0_SERC6                               0x000004D0
-#define BA0_SERC7                               0x000004D4
-#define BA0_SERACC                              0x000004D8
-#define BA0_ACCTL2                              0x000004E0
-#define BA0_ACSTS2                              0x000004E4
-#define BA0_ACOSV2                              0x000004E8
-#define BA0_ACCAD2                              0x000004EC
-#define BA0_ACCDA2                              0x000004F0
-#define BA0_ACISV2                              0x000004F4
-#define BA0_ACSAD2                              0x000004F8
-#define BA0_ACSDA2                              0x000004FC
-#define BA0_IOTAC0                              0x00000500
-#define BA0_IOTAC1                              0x00000504
-#define BA0_IOTAC2                              0x00000508
-#define BA0_IOTAC3                              0x0000050C
-#define BA0_IOTAC4                              0x00000510
-#define BA0_IOTAC5                              0x00000514
-#define BA0_IOTAC6                              0x00000518
-#define BA0_IOTAC7                              0x0000051C
-#define BA0_IOTAC8                              0x00000520
-#define BA0_IOTAC9                              0x00000524
-#define BA0_IOTAC10                             0x00000528
-#define BA0_IOTAC11                             0x0000052C
-#define BA0_IOTFR0                              0x00000540
-#define BA0_IOTFR1                              0x00000544
-#define BA0_IOTFR2                              0x00000548
-#define BA0_IOTFR3                              0x0000054C
-#define BA0_IOTFR4                              0x00000550
-#define BA0_IOTFR5                              0x00000554
-#define BA0_IOTFR6                              0x00000558
-#define BA0_IOTFR7                              0x0000055C
-#define BA0_IOTFIFO                             0x00000580
-#define BA0_IOTRRD                              0x00000584
-#define BA0_IOTFP                               0x00000588
-#define BA0_IOTCR                               0x0000058C
-#define BA0_DPCID                               0x00000590
-#define BA0_DPCIA                               0x00000594
-#define BA0_DPCIC                               0x00000598
-#define BA0_PCPCIR                              0x00000600
-#define BA0_PCPCIG                              0x00000604
-#define BA0_PCPCIEN                             0x00000608
-#define BA0_EPCIPMC                             0x00000610
-#endif
-
-/*
- *  The following define the offsets of the registers and memories accessed via
- *  base address register one on the CS461x part.
- */
-#define BA1_SP_DMEM0                            0x00000000
-#define BA1_SP_DMEM1                            0x00010000
-#define BA1_SP_PMEM                             0x00020000
-#define BA1_SP_REG				0x00030000
-#define BA1_SPCR                                0x00030000
-#define BA1_DREG                                0x00030004
-#define BA1_DSRWP                               0x00030008
-#define BA1_TWPR                                0x0003000C
-#define BA1_SPWR                                0x00030010
-#define BA1_SPIR                                0x00030014
-#define BA1_FGR1                                0x00030020
-#define BA1_SPCS                                0x00030028
-#define BA1_SDSR                                0x0003002C
-#define BA1_FRMT                                0x00030030
-#define BA1_FRCC                                0x00030034
-#define BA1_FRSC                                0x00030038
-#define BA1_OMNI_MEM                            0x000E0000
-
-/*
- *  The following defines are for the flags in the host interrupt status
- *  register.
- */
-#define HISR_VC_MASK                            0x0000FFFF
-#define HISR_VC0                                0x00000001
-#define HISR_VC1                                0x00000002
-#define HISR_VC2                                0x00000004
-#define HISR_VC3                                0x00000008
-#define HISR_VC4                                0x00000010
-#define HISR_VC5                                0x00000020
-#define HISR_VC6                                0x00000040
-#define HISR_VC7                                0x00000080
-#define HISR_VC8                                0x00000100
-#define HISR_VC9                                0x00000200
-#define HISR_VC10                               0x00000400
-#define HISR_VC11                               0x00000800
-#define HISR_VC12                               0x00001000
-#define HISR_VC13                               0x00002000
-#define HISR_VC14                               0x00004000
-#define HISR_VC15                               0x00008000
-#define HISR_INT0                               0x00010000
-#define HISR_INT1                               0x00020000
-#define HISR_DMAI                               0x00040000
-#define HISR_FROVR                              0x00080000
-#define HISR_MIDI                               0x00100000
-#ifdef NO_CS4612
-#define HISR_RESERVED                           0x0FE00000
-#else
-#define HISR_SBINT                              0x00200000
-#define HISR_RESERVED                           0x0FC00000
-#endif
-#define HISR_H0P                                0x40000000
-#define HISR_INTENA                             0x80000000
-
-/*
- *  The following defines are for the flags in the host signal register 0.
- */
-#define HSR0_VC_MASK                            0xFFFFFFFF
-#define HSR0_VC16                               0x00000001
-#define HSR0_VC17                               0x00000002
-#define HSR0_VC18                               0x00000004
-#define HSR0_VC19                               0x00000008
-#define HSR0_VC20                               0x00000010
-#define HSR0_VC21                               0x00000020
-#define HSR0_VC22                               0x00000040
-#define HSR0_VC23                               0x00000080
-#define HSR0_VC24                               0x00000100
-#define HSR0_VC25                               0x00000200
-#define HSR0_VC26                               0x00000400
-#define HSR0_VC27                               0x00000800
-#define HSR0_VC28                               0x00001000
-#define HSR0_VC29                               0x00002000
-#define HSR0_VC30                               0x00004000
-#define HSR0_VC31                               0x00008000
-#define HSR0_VC32                               0x00010000
-#define HSR0_VC33                               0x00020000
-#define HSR0_VC34                               0x00040000
-#define HSR0_VC35                               0x00080000
-#define HSR0_VC36                               0x00100000
-#define HSR0_VC37                               0x00200000
-#define HSR0_VC38                               0x00400000
-#define HSR0_VC39                               0x00800000
-#define HSR0_VC40                               0x01000000
-#define HSR0_VC41                               0x02000000
-#define HSR0_VC42                               0x04000000
-#define HSR0_VC43                               0x08000000
-#define HSR0_VC44                               0x10000000
-#define HSR0_VC45                               0x20000000
-#define HSR0_VC46                               0x40000000
-#define HSR0_VC47                               0x80000000
-
-/*
- *  The following defines are for the flags in the host interrupt control
- *  register.
- */
-#define HICR_IEV                                0x00000001
-#define HICR_CHGM                               0x00000002
-
-/*
- *  The following defines are for the flags in the DMA status register.
- */
-#define DMSR_HP                                 0x00000001
-#define DMSR_HR                                 0x00000002
-#define DMSR_SP                                 0x00000004
-#define DMSR_SR                                 0x00000008
-
-/*
- *  The following defines are for the flags in the host DMA source address
- *  register.
- */
-#define HSAR_HOST_ADDR_MASK                     0xFFFFFFFF
-#define HSAR_DSP_ADDR_MASK                      0x0000FFFF
-#define HSAR_MEMID_MASK                         0x000F0000
-#define HSAR_MEMID_SP_DMEM0                     0x00000000
-#define HSAR_MEMID_SP_DMEM1                     0x00010000
-#define HSAR_MEMID_SP_PMEM                      0x00020000
-#define HSAR_MEMID_SP_DEBUG                     0x00030000
-#define HSAR_MEMID_OMNI_MEM                     0x000E0000
-#define HSAR_END                                0x40000000
-#define HSAR_ERR                                0x80000000
-
-/*
- *  The following defines are for the flags in the host DMA destination address
- *  register.
- */
-#define HDAR_HOST_ADDR_MASK                     0xFFFFFFFF
-#define HDAR_DSP_ADDR_MASK                      0x0000FFFF
-#define HDAR_MEMID_MASK                         0x000F0000
-#define HDAR_MEMID_SP_DMEM0                     0x00000000
-#define HDAR_MEMID_SP_DMEM1                     0x00010000
-#define HDAR_MEMID_SP_PMEM                      0x00020000
-#define HDAR_MEMID_SP_DEBUG                     0x00030000
-#define HDAR_MEMID_OMNI_MEM                     0x000E0000
-#define HDAR_END                                0x40000000
-#define HDAR_ERR                                0x80000000
-
-/*
- *  The following defines are for the flags in the host DMA control register.
- */
-#define HDMR_AC_MASK                            0x0000F000
-#define HDMR_AC_8_16                            0x00001000
-#define HDMR_AC_M_S                             0x00002000
-#define HDMR_AC_B_L                             0x00004000
-#define HDMR_AC_S_U                             0x00008000
-
-/*
- *  The following defines are for the flags in the host DMA control register.
- */
-#define HDCR_COUNT_MASK                         0x000003FF
-#define HDCR_DONE                               0x00004000
-#define HDCR_OPT                                0x00008000
-#define HDCR_WBD                                0x00400000
-#define HDCR_WBS                                0x00800000
-#define HDCR_DMS_MASK                           0x07000000
-#define HDCR_DMS_LINEAR                         0x00000000
-#define HDCR_DMS_16_DWORDS                      0x01000000
-#define HDCR_DMS_32_DWORDS                      0x02000000
-#define HDCR_DMS_64_DWORDS                      0x03000000
-#define HDCR_DMS_128_DWORDS                     0x04000000
-#define HDCR_DMS_256_DWORDS                     0x05000000
-#define HDCR_DMS_512_DWORDS                     0x06000000
-#define HDCR_DMS_1024_DWORDS                    0x07000000
-#define HDCR_DH                                 0x08000000
-#define HDCR_SMS_MASK                           0x70000000
-#define HDCR_SMS_LINEAR                         0x00000000
-#define HDCR_SMS_16_DWORDS                      0x10000000
-#define HDCR_SMS_32_DWORDS                      0x20000000
-#define HDCR_SMS_64_DWORDS                      0x30000000
-#define HDCR_SMS_128_DWORDS                     0x40000000
-#define HDCR_SMS_256_DWORDS                     0x50000000
-#define HDCR_SMS_512_DWORDS                     0x60000000
-#define HDCR_SMS_1024_DWORDS                    0x70000000
-#define HDCR_SH                                 0x80000000
-#define HDCR_COUNT_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the performance monitor control
- *  register.
- */
-#define PFMC_C1SS_MASK                          0x0000001F
-#define PFMC_C1EV                               0x00000020
-#define PFMC_C1RS                               0x00008000
-#define PFMC_C2SS_MASK                          0x001F0000
-#define PFMC_C2EV                               0x00200000
-#define PFMC_C2RS                               0x80000000
-#define PFMC_C1SS_SHIFT                         0
-#define PFMC_C2SS_SHIFT                         16
-#define PFMC_BUS_GRANT                          0
-#define PFMC_GRANT_AFTER_REQ                    1
-#define PFMC_TRANSACTION                        2
-#define PFMC_DWORD_TRANSFER                     3
-#define PFMC_SLAVE_READ                         4
-#define PFMC_SLAVE_WRITE                        5
-#define PFMC_PREEMPTION                         6
-#define PFMC_DISCONNECT_RETRY                   7
-#define PFMC_INTERRUPT                          8
-#define PFMC_BUS_OWNERSHIP                      9
-#define PFMC_TRANSACTION_LAG                    10
-#define PFMC_PCI_CLOCK                          11
-#define PFMC_SERIAL_CLOCK                       12
-#define PFMC_SP_CLOCK                           13
-
-/*
- *  The following defines are for the flags in the performance counter value 1
- *  register.
- */
-#define PFCV1_PC1V_MASK                         0xFFFFFFFF
-#define PFCV1_PC1V_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the performance counter value 2
- *  register.
- */
-#define PFCV2_PC2V_MASK                         0xFFFFFFFF
-#define PFCV2_PC2V_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the clock control register 1.
- */
-#define CLKCR1_OSCS                             0x00000001
-#define CLKCR1_OSCP                             0x00000002
-#define CLKCR1_PLLSS_MASK                       0x0000000C
-#define CLKCR1_PLLSS_SERIAL                     0x00000000
-#define CLKCR1_PLLSS_CRYSTAL                    0x00000004
-#define CLKCR1_PLLSS_PCI                        0x00000008
-#define CLKCR1_PLLSS_RESERVED                   0x0000000C
-#define CLKCR1_PLLP                             0x00000010
-#define CLKCR1_SWCE                             0x00000020
-#define CLKCR1_PLLOS                            0x00000040
-
-/*
- *  The following defines are for the flags in the clock control register 2.
- */
-#define CLKCR2_PDIVS_MASK                       0x0000000F
-#define CLKCR2_PDIVS_1                          0x00000001
-#define CLKCR2_PDIVS_2                          0x00000002
-#define CLKCR2_PDIVS_4                          0x00000004
-#define CLKCR2_PDIVS_7                          0x00000007
-#define CLKCR2_PDIVS_8                          0x00000008
-#define CLKCR2_PDIVS_16                         0x00000000
-
-/*
- *  The following defines are for the flags in the PLL multiplier register.
- */
-#define PLLM_MASK                               0x000000FF
-#define PLLM_SHIFT                              0
-
-/*
- *  The following defines are for the flags in the PLL capacitor coefficient
- *  register.
- */
-#define PLLCC_CDR_MASK                          0x00000007
-#ifndef NO_CS4610
-#define PLLCC_CDR_240_350_MHZ                   0x00000000
-#define PLLCC_CDR_184_265_MHZ                   0x00000001
-#define PLLCC_CDR_144_205_MHZ                   0x00000002
-#define PLLCC_CDR_111_160_MHZ                   0x00000003
-#define PLLCC_CDR_87_123_MHZ                    0x00000004
-#define PLLCC_CDR_67_96_MHZ                     0x00000005
-#define PLLCC_CDR_52_74_MHZ                     0x00000006
-#define PLLCC_CDR_45_58_MHZ                     0x00000007
-#endif
-#ifndef NO_CS4612
-#define PLLCC_CDR_271_398_MHZ                   0x00000000
-#define PLLCC_CDR_227_330_MHZ                   0x00000001
-#define PLLCC_CDR_167_239_MHZ                   0x00000002
-#define PLLCC_CDR_150_215_MHZ                   0x00000003
-#define PLLCC_CDR_107_154_MHZ                   0x00000004
-#define PLLCC_CDR_98_140_MHZ                    0x00000005
-#define PLLCC_CDR_73_104_MHZ                    0x00000006
-#define PLLCC_CDR_63_90_MHZ                     0x00000007
-#endif
-#define PLLCC_LPF_MASK                          0x000000F8
-#ifndef NO_CS4610
-#define PLLCC_LPF_23850_60000_KHZ               0x00000000
-#define PLLCC_LPF_7960_26290_KHZ                0x00000008
-#define PLLCC_LPF_4160_10980_KHZ                0x00000018
-#define PLLCC_LPF_1740_4580_KHZ                 0x00000038
-#define PLLCC_LPF_724_1910_KHZ                  0x00000078
-#define PLLCC_LPF_317_798_KHZ                   0x000000F8
-#endif
-#ifndef NO_CS4612
-#define PLLCC_LPF_25580_64530_KHZ               0x00000000
-#define PLLCC_LPF_14360_37270_KHZ               0x00000008
-#define PLLCC_LPF_6100_16020_KHZ                0x00000018
-#define PLLCC_LPF_2540_6690_KHZ                 0x00000038
-#define PLLCC_LPF_1050_2780_KHZ                 0x00000078
-#define PLLCC_LPF_450_1160_KHZ                  0x000000F8
-#endif
-
-/*
- *  The following defines are for the flags in the feature reporting register.
- */
-#define FRR_FAB_MASK                            0x00000003
-#define FRR_MASK_MASK                           0x0000001C
-#ifdef NO_CS4612
-#define FRR_CFOP_MASK                           0x000000E0
-#else
-#define FRR_CFOP_MASK                           0x00000FE0
-#endif
-#define FRR_CFOP_NOT_DVD                        0x00000020
-#define FRR_CFOP_A3D                            0x00000040
-#define FRR_CFOP_128_PIN                        0x00000080
-#ifndef NO_CS4612
-#define FRR_CFOP_CS4280                         0x00000800
-#endif
-#define FRR_FAB_SHIFT                           0
-#define FRR_MASK_SHIFT                          2
-#define FRR_CFOP_SHIFT                          5
-
-/*
- *  The following defines are for the flags in the configuration load 1
- *  register.
- */
-#define CFL1_CLOCK_SOURCE_MASK                  0x00000003
-#define CFL1_CLOCK_SOURCE_CS423X                0x00000000
-#define CFL1_CLOCK_SOURCE_AC97                  0x00000001
-#define CFL1_CLOCK_SOURCE_CRYSTAL               0x00000002
-#define CFL1_CLOCK_SOURCE_DUAL_AC97             0x00000003
-#define CFL1_VALID_DATA_MASK                    0x000000FF
-
-/*
- *  The following defines are for the flags in the configuration load 2
- *  register.
- */
-#define CFL2_VALID_DATA_MASK                    0x000000FF
-
-/*
- *  The following defines are for the flags in the serial port master control
- *  register 1.
- */
-#define SERMC1_MSPE                             0x00000001
-#define SERMC1_PTC_MASK                         0x0000000E
-#define SERMC1_PTC_CS423X                       0x00000000
-#define SERMC1_PTC_AC97                         0x00000002
-#define SERMC1_PTC_DAC                          0x00000004
-#define SERMC1_PLB                              0x00000010
-#define SERMC1_XLB                              0x00000020
-
-/*
- *  The following defines are for the flags in the serial port master control
- *  register 2.
- */
-#define SERMC2_LROE                             0x00000001
-#define SERMC2_MCOE                             0x00000002
-#define SERMC2_MCDIV                            0x00000004
-
-/*
- *  The following defines are for the flags in the serial port 1 configuration
- *  register.
- */
-#define SERC1_SO1EN                             0x00000001
-#define SERC1_SO1F_MASK                         0x0000000E
-#define SERC1_SO1F_CS423X                       0x00000000
-#define SERC1_SO1F_AC97                         0x00000002
-#define SERC1_SO1F_DAC                          0x00000004
-#define SERC1_SO1F_SPDIF                        0x00000006
-
-/*
- *  The following defines are for the flags in the serial port 2 configuration
- *  register.
- */
-#define SERC2_SI1EN                             0x00000001
-#define SERC2_SI1F_MASK                         0x0000000E
-#define SERC2_SI1F_CS423X                       0x00000000
-#define SERC2_SI1F_AC97                         0x00000002
-#define SERC2_SI1F_ADC                          0x00000004
-#define SERC2_SI1F_SPDIF                        0x00000006
-
-/*
- *  The following defines are for the flags in the serial port 3 configuration
- *  register.
- */
-#define SERC3_SO2EN                             0x00000001
-#define SERC3_SO2F_MASK                         0x00000006
-#define SERC3_SO2F_DAC                          0x00000000
-#define SERC3_SO2F_SPDIF                        0x00000002
-
-/*
- *  The following defines are for the flags in the serial port 4 configuration
- *  register.
- */
-#define SERC4_SO3EN                             0x00000001
-#define SERC4_SO3F_MASK                         0x00000006
-#define SERC4_SO3F_DAC                          0x00000000
-#define SERC4_SO3F_SPDIF                        0x00000002
-
-/*
- *  The following defines are for the flags in the serial port 5 configuration
- *  register.
- */
-#define SERC5_SI2EN                             0x00000001
-#define SERC5_SI2F_MASK                         0x00000006
-#define SERC5_SI2F_ADC                          0x00000000
-#define SERC5_SI2F_SPDIF                        0x00000002
-
-/*
- *  The following defines are for the flags in the serial port backdoor sample
- *  pointer register.
- */
-#define SERBSP_FSP_MASK                         0x0000000F
-#define SERBSP_FSP_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the serial port backdoor status
- *  register.
- */
-#define SERBST_RRDY                             0x00000001
-#define SERBST_WBSY                             0x00000002
-
-/*
- *  The following defines are for the flags in the serial port backdoor command
- *  register.
- */
-#define SERBCM_RDC                              0x00000001
-#define SERBCM_WRC                              0x00000002
-
-/*
- *  The following defines are for the flags in the serial port backdoor address
- *  register.
- */
-#ifdef NO_CS4612
-#define SERBAD_FAD_MASK                         0x000000FF
-#else
-#define SERBAD_FAD_MASK                         0x000001FF
-#endif
-#define SERBAD_FAD_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the serial port backdoor
- *  configuration register.
- */
-#define SERBCF_HBP                              0x00000001
-
-/*
- *  The following defines are for the flags in the serial port backdoor write
- *  port register.
- */
-#define SERBWP_FWD_MASK                         0x000FFFFF
-#define SERBWP_FWD_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the serial port backdoor read
- *  port register.
- */
-#define SERBRP_FRD_MASK                         0x000FFFFF
-#define SERBRP_FRD_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the async FIFO address register.
- */
-#ifndef NO_CS4612
-#define ASER_FADDR_A1_MASK                      0x000001FF
-#define ASER_FADDR_EN1                          0x00008000
-#define ASER_FADDR_A2_MASK                      0x01FF0000
-#define ASER_FADDR_EN2                          0x80000000
-#define ASER_FADDR_A1_SHIFT                     0
-#define ASER_FADDR_A2_SHIFT                     16
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 control register.
- */
-#define ACCTL_RSTN                              0x00000001
-#define ACCTL_ESYN                              0x00000002
-#define ACCTL_VFRM                              0x00000004
-#define ACCTL_DCV                               0x00000008
-#define ACCTL_CRW                               0x00000010
-#define ACCTL_ASYN                              0x00000020
-#ifndef NO_CS4612
-#define ACCTL_TC                                0x00000040
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status register.
- */
-#define ACSTS_CRDY                              0x00000001
-#define ACSTS_VSTS                              0x00000002
-#ifndef NO_CS4612
-#define ACSTS_WKUP                              0x00000004
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 output slot valid
- *  register.
- */
-#define ACOSV_SLV3                              0x00000001
-#define ACOSV_SLV4                              0x00000002
-#define ACOSV_SLV5                              0x00000004
-#define ACOSV_SLV6                              0x00000008
-#define ACOSV_SLV7                              0x00000010
-#define ACOSV_SLV8                              0x00000020
-#define ACOSV_SLV9                              0x00000040
-#define ACOSV_SLV10                             0x00000080
-#define ACOSV_SLV11                             0x00000100
-#define ACOSV_SLV12                             0x00000200
-
-/*
- *  The following defines are for the flags in the AC97 command address
- *  register.
- */
-#define ACCAD_CI_MASK                           0x0000007F
-#define ACCAD_CI_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the AC97 command data register.
- */
-#define ACCDA_CD_MASK                           0x0000FFFF
-#define ACCDA_CD_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the AC97 input slot valid
- *  register.
- */
-#define ACISV_ISV3                              0x00000001
-#define ACISV_ISV4                              0x00000002
-#define ACISV_ISV5                              0x00000004
-#define ACISV_ISV6                              0x00000008
-#define ACISV_ISV7                              0x00000010
-#define ACISV_ISV8                              0x00000020
-#define ACISV_ISV9                              0x00000040
-#define ACISV_ISV10                             0x00000080
-#define ACISV_ISV11                             0x00000100
-#define ACISV_ISV12                             0x00000200
-
-/*
- *  The following defines are for the flags in the AC97 status address
- *  register.
- */
-#define ACSAD_SI_MASK                           0x0000007F
-#define ACSAD_SI_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the AC97 status data register.
- */
-#define ACSDA_SD_MASK                           0x0000FFFF
-#define ACSDA_SD_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the joystick poll/trigger
- *  register.
- */
-#define JSPT_CAX                                0x00000001
-#define JSPT_CAY                                0x00000002
-#define JSPT_CBX                                0x00000004
-#define JSPT_CBY                                0x00000008
-#define JSPT_BA1                                0x00000010
-#define JSPT_BA2                                0x00000020
-#define JSPT_BB1                                0x00000040
-#define JSPT_BB2                                0x00000080
-
-/*
- *  The following defines are for the flags in the joystick control register.
- */
-#define JSCTL_SP_MASK                           0x00000003
-#define JSCTL_SP_SLOW                           0x00000000
-#define JSCTL_SP_MEDIUM_SLOW                    0x00000001
-#define JSCTL_SP_MEDIUM_FAST                    0x00000002
-#define JSCTL_SP_FAST                           0x00000003
-#define JSCTL_ARE                               0x00000004
-
-/*
- *  The following defines are for the flags in the joystick coordinate pair 1
- *  readback register.
- */
-#define JSC1_Y1V_MASK                           0x0000FFFF
-#define JSC1_X1V_MASK                           0xFFFF0000
-#define JSC1_Y1V_SHIFT                          0
-#define JSC1_X1V_SHIFT                          16
-
-/*
- *  The following defines are for the flags in the joystick coordinate pair 2
- *  readback register.
- */
-#define JSC2_Y2V_MASK                           0x0000FFFF
-#define JSC2_X2V_MASK                           0xFFFF0000
-#define JSC2_Y2V_SHIFT                          0
-#define JSC2_X2V_SHIFT                          16
-
-/*
- *  The following defines are for the flags in the MIDI control register.
- */
-#define MIDCR_TXE                               0x00000001	/* Enable transmitting. */
-#define MIDCR_RXE                               0x00000002	/* Enable receiving. */
-#define MIDCR_RIE                               0x00000004	/* Interrupt upon tx ready. */
-#define MIDCR_TIE                               0x00000008	/* Interrupt upon rx ready. */
-#define MIDCR_MLB                               0x00000010	/* Enable midi loopback. */
-#define MIDCR_MRST                              0x00000020	/* Reset interface. */
-
-/*
- *  The following defines are for the flags in the MIDI status register.
- */
-#define MIDSR_TBF                               0x00000001	/* Tx FIFO is full. */
-#define MIDSR_RBE                               0x00000002	/* Rx FIFO is empty. */
-
-/*
- *  The following defines are for the flags in the MIDI write port register.
- */
-#define MIDWP_MWD_MASK                          0x000000FF
-#define MIDWP_MWD_SHIFT                         0
-
-/*
- *  The following defines are for the flags in the MIDI read port register.
- */
-#define MIDRP_MRD_MASK                          0x000000FF
-#define MIDRP_MRD_SHIFT                         0
-
-/*
- *  The following defines are for the flags in the joystick GPIO register.
- */
-#define JSIO_DAX                                0x00000001
-#define JSIO_DAY                                0x00000002
-#define JSIO_DBX                                0x00000004
-#define JSIO_DBY                                0x00000008
-#define JSIO_AXOE                               0x00000010
-#define JSIO_AYOE                               0x00000020
-#define JSIO_BXOE                               0x00000040
-#define JSIO_BYOE                               0x00000080
-
-/*
- *  The following defines are for the flags in the master async/sync serial
- *  port enable register.
- */
-#ifndef NO_CS4612
-#define ASER_MASTER_ME                          0x00000001
-#endif
-
-/*
- *  The following defines are for the flags in the configuration interface
- *  register.
- */
-#define CFGI_CLK                                0x00000001
-#define CFGI_DOUT                               0x00000002
-#define CFGI_DIN_EEN                            0x00000004
-#define CFGI_EELD                               0x00000008
-
-/*
- *  The following defines are for the flags in the subsystem ID and vendor ID
- *  register.
- */
-#define SSVID_VID_MASK                          0x0000FFFF
-#define SSVID_SID_MASK                          0xFFFF0000
-#define SSVID_VID_SHIFT                         0
-#define SSVID_SID_SHIFT                         16
-
-/*
- *  The following defines are for the flags in the GPIO pin interface register.
- */
-#define GPIOR_VOLDN                             0x00000001
-#define GPIOR_VOLUP                             0x00000002
-#define GPIOR_SI2D                              0x00000004
-#define GPIOR_SI2OE                             0x00000008
-
-/*
- *  The following defines are for the flags in the extended GPIO pin direction
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIODR_GPOE0                           0x00000001
-#define EGPIODR_GPOE1                           0x00000002
-#define EGPIODR_GPOE2                           0x00000004
-#define EGPIODR_GPOE3                           0x00000008
-#define EGPIODR_GPOE4                           0x00000010
-#define EGPIODR_GPOE5                           0x00000020
-#define EGPIODR_GPOE6                           0x00000040
-#define EGPIODR_GPOE7                           0x00000080
-#define EGPIODR_GPOE8                           0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO pin polarity/
- *  type register.
- */
-#ifndef NO_CS4612
-#define EGPIOPTR_GPPT0                          0x00000001
-#define EGPIOPTR_GPPT1                          0x00000002
-#define EGPIOPTR_GPPT2                          0x00000004
-#define EGPIOPTR_GPPT3                          0x00000008
-#define EGPIOPTR_GPPT4                          0x00000010
-#define EGPIOPTR_GPPT5                          0x00000020
-#define EGPIOPTR_GPPT6                          0x00000040
-#define EGPIOPTR_GPPT7                          0x00000080
-#define EGPIOPTR_GPPT8                          0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO pin sticky
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIOTR_GPS0                            0x00000001
-#define EGPIOTR_GPS1                            0x00000002
-#define EGPIOTR_GPS2                            0x00000004
-#define EGPIOTR_GPS3                            0x00000008
-#define EGPIOTR_GPS4                            0x00000010
-#define EGPIOTR_GPS5                            0x00000020
-#define EGPIOTR_GPS6                            0x00000040
-#define EGPIOTR_GPS7                            0x00000080
-#define EGPIOTR_GPS8                            0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO ping wakeup
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIOWR_GPW0                            0x00000001
-#define EGPIOWR_GPW1                            0x00000002
-#define EGPIOWR_GPW2                            0x00000004
-#define EGPIOWR_GPW3                            0x00000008
-#define EGPIOWR_GPW4                            0x00000010
-#define EGPIOWR_GPW5                            0x00000020
-#define EGPIOWR_GPW6                            0x00000040
-#define EGPIOWR_GPW7                            0x00000080
-#define EGPIOWR_GPW8                            0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO pin status
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIOSR_GPS0                            0x00000001
-#define EGPIOSR_GPS1                            0x00000002
-#define EGPIOSR_GPS2                            0x00000004
-#define EGPIOSR_GPS3                            0x00000008
-#define EGPIOSR_GPS4                            0x00000010
-#define EGPIOSR_GPS5                            0x00000020
-#define EGPIOSR_GPS6                            0x00000040
-#define EGPIOSR_GPS7                            0x00000080
-#define EGPIOSR_GPS8                            0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the serial port 6 configuration
- *  register.
- */
-#ifndef NO_CS4612
-#define SERC6_ASDO2EN                           0x00000001
-#endif
-
-/*
- *  The following defines are for the flags in the serial port 7 configuration
- *  register.
- */
-#ifndef NO_CS4612
-#define SERC7_ASDI2EN                           0x00000001
-#define SERC7_POSILB                            0x00000002
-#define SERC7_SIPOLB                            0x00000004
-#define SERC7_SOSILB                            0x00000008
-#define SERC7_SISOLB                            0x00000010
-#endif
-
-/*
- *  The following defines are for the flags in the serial port AC link
- *  configuration register.
- */
-#ifndef NO_CS4612
-#define SERACC_CODEC_TYPE_MASK                  0x00000001
-#define SERACC_CODEC_TYPE_1_03                  0x00000000
-#define SERACC_CODEC_TYPE_2_0                   0x00000001
-#define SERACC_TWO_CODECS                       0x00000002
-#define SERACC_MDM                              0x00000004
-#define SERACC_HSP                              0x00000008
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 control register 2.
- */
-#ifndef NO_CS4612
-#define ACCTL2_RSTN                             0x00000001
-#define ACCTL2_ESYN                             0x00000002
-#define ACCTL2_VFRM                             0x00000004
-#define ACCTL2_DCV                              0x00000008
-#define ACCTL2_CRW                              0x00000010
-#define ACCTL2_ASYN                             0x00000020
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status register 2.
- */
-#ifndef NO_CS4612
-#define ACSTS2_CRDY                             0x00000001
-#define ACSTS2_VSTS                             0x00000002
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 output slot valid
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACOSV2_SLV3                             0x00000001
-#define ACOSV2_SLV4                             0x00000002
-#define ACOSV2_SLV5                             0x00000004
-#define ACOSV2_SLV6                             0x00000008
-#define ACOSV2_SLV7                             0x00000010
-#define ACOSV2_SLV8                             0x00000020
-#define ACOSV2_SLV9                             0x00000040
-#define ACOSV2_SLV10                            0x00000080
-#define ACOSV2_SLV11                            0x00000100
-#define ACOSV2_SLV12                            0x00000200
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 command address
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACCAD2_CI_MASK                          0x0000007F
-#define ACCAD2_CI_SHIFT                         0
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 command data register
- *  2.
- */
-#ifndef NO_CS4612
-#define ACCDA2_CD_MASK                          0x0000FFFF
-#define ACCDA2_CD_SHIFT                         0  
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 input slot valid
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACISV2_ISV3                             0x00000001
-#define ACISV2_ISV4                             0x00000002
-#define ACISV2_ISV5                             0x00000004
-#define ACISV2_ISV6                             0x00000008
-#define ACISV2_ISV7                             0x00000010
-#define ACISV2_ISV8                             0x00000020
-#define ACISV2_ISV9                             0x00000040
-#define ACISV2_ISV10                            0x00000080
-#define ACISV2_ISV11                            0x00000100
-#define ACISV2_ISV12                            0x00000200
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status address
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACSAD2_SI_MASK                          0x0000007F
-#define ACSAD2_SI_SHIFT                         0
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status data register 2.
- */
-#ifndef NO_CS4612
-#define ACSDA2_SD_MASK                          0x0000FFFF
-#define ACSDA2_SD_SHIFT                         0
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap address and control
- *  registers (all 12).
- */
-#ifndef NO_CS4612
-#define IOTAC_SA_MASK                           0x0000FFFF
-#define IOTAC_MSK_MASK                          0x000F0000
-#define IOTAC_IODC_MASK                         0x06000000
-#define IOTAC_IODC_16_BIT                       0x00000000
-#define IOTAC_IODC_10_BIT                       0x02000000
-#define IOTAC_IODC_12_BIT                       0x04000000
-#define IOTAC_WSPI                              0x08000000
-#define IOTAC_RSPI                              0x10000000
-#define IOTAC_WSE                               0x20000000
-#define IOTAC_WE                                0x40000000
-#define IOTAC_RE                                0x80000000
-#define IOTAC_SA_SHIFT                          0
-#define IOTAC_MSK_SHIFT                         16
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap fast read registers
- *  (all 8).
- */
-#ifndef NO_CS4612
-#define IOTFR_D_MASK                            0x0000FFFF
-#define IOTFR_A_MASK                            0x000F0000
-#define IOTFR_R_MASK                            0x0F000000
-#define IOTFR_ALL                               0x40000000
-#define IOTFR_VL                                0x80000000
-#define IOTFR_D_SHIFT                           0
-#define IOTFR_A_SHIFT                           16
-#define IOTFR_R_SHIFT                           24
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap FIFO register.
- */
-#ifndef NO_CS4612
-#define IOTFIFO_BA_MASK                         0x00003FFF
-#define IOTFIFO_S_MASK                          0x00FF0000
-#define IOTFIFO_OF                              0x40000000
-#define IOTFIFO_SPIOF                           0x80000000
-#define IOTFIFO_BA_SHIFT                        0
-#define IOTFIFO_S_SHIFT                         16
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap retry read data
- *  register.
- */
-#ifndef NO_CS4612
-#define IOTRRD_D_MASK                           0x0000FFFF
-#define IOTRRD_RDV                              0x80000000
-#define IOTRRD_D_SHIFT                          0
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap FIFO pointer
- *  register.
- */
-#ifndef NO_CS4612
-#define IOTFP_CA_MASK                           0x00003FFF
-#define IOTFP_PA_MASK                           0x3FFF0000
-#define IOTFP_CA_SHIFT                          0
-#define IOTFP_PA_SHIFT                          16
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap control register.
- */
-#ifndef NO_CS4612
-#define IOTCR_ITD                               0x00000001
-#define IOTCR_HRV                               0x00000002
-#define IOTCR_SRV                               0x00000004
-#define IOTCR_DTI                               0x00000008
-#define IOTCR_DFI                               0x00000010
-#define IOTCR_DDP                               0x00000020
-#define IOTCR_JTE                               0x00000040
-#define IOTCR_PPE                               0x00000080
-#endif
-
-/*
- *  The following defines are for the flags in the direct PCI data register.
- */
-#ifndef NO_CS4612
-#define DPCID_D_MASK                            0xFFFFFFFF
-#define DPCID_D_SHIFT                           0
-#endif
-
-/*
- *  The following defines are for the flags in the direct PCI address register.
- */
-#ifndef NO_CS4612
-#define DPCIA_A_MASK                            0xFFFFFFFF
-#define DPCIA_A_SHIFT                           0
-#endif
-
-/*
- *  The following defines are for the flags in the direct PCI command register.
- */
-#ifndef NO_CS4612
-#define DPCIC_C_MASK                            0x0000000F
-#define DPCIC_C_IOREAD                          0x00000002
-#define DPCIC_C_IOWRITE                         0x00000003
-#define DPCIC_BE_MASK                           0x000000F0
-#endif
-
-/*
- *  The following defines are for the flags in the PC/PCI request register.
- */
-#ifndef NO_CS4612
-#define PCPCIR_RDC_MASK                         0x00000007
-#define PCPCIR_C_MASK                           0x00007000
-#define PCPCIR_REQ                              0x00008000
-#define PCPCIR_RDC_SHIFT                        0
-#define PCPCIR_C_SHIFT                          12
-#endif
-
-/*
- *  The following defines are for the flags in the PC/PCI grant register.
- */ 
-#ifndef NO_CS4612
-#define PCPCIG_GDC_MASK                         0x00000007
-#define PCPCIG_VL                               0x00008000
-#define PCPCIG_GDC_SHIFT                        0
-#endif
-
-/*
- *  The following defines are for the flags in the PC/PCI master enable
- *  register.
- */
-#ifndef NO_CS4612
-#define PCPCIEN_EN                              0x00000001
-#endif
-
-/*
- *  The following defines are for the flags in the extended PCI power
- *  management control register.
- */
-#ifndef NO_CS4612
-#define EPCIPMC_GWU                             0x00000001
-#define EPCIPMC_FSPC                            0x00000002
-#endif 
-
-/*
- *  The following defines are for the flags in the SP control register.
- */
-#define SPCR_RUN                                0x00000001
-#define SPCR_STPFR                              0x00000002
-#define SPCR_RUNFR                              0x00000004
-#define SPCR_TICK                               0x00000008
-#define SPCR_DRQEN                              0x00000020
-#define SPCR_RSTSP                              0x00000040
-#define SPCR_OREN                               0x00000080
-#ifndef NO_CS4612
-#define SPCR_PCIINT                             0x00000100
-#define SPCR_OINTD                              0x00000200
-#define SPCR_CRE                                0x00008000
-#endif
-
-/*
- *  The following defines are for the flags in the debug index register.
- */
-#define DREG_REGID_MASK                         0x0000007F
-#define DREG_DEBUG                              0x00000080
-#define DREG_RGBK_MASK                          0x00000700
-#define DREG_TRAP                               0x00000800
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_TRAPX                              0x00001000
-#endif
-#endif
-#define DREG_REGID_SHIFT                        0
-#define DREG_RGBK_SHIFT                         8
-#define DREG_RGBK_REGID_MASK                    0x0000077F
-#define DREG_REGID_R0                           0x00000010
-#define DREG_REGID_R1                           0x00000011
-#define DREG_REGID_R2                           0x00000012
-#define DREG_REGID_R3                           0x00000013
-#define DREG_REGID_R4                           0x00000014
-#define DREG_REGID_R5                           0x00000015
-#define DREG_REGID_R6                           0x00000016
-#define DREG_REGID_R7                           0x00000017
-#define DREG_REGID_R8                           0x00000018
-#define DREG_REGID_R9                           0x00000019
-#define DREG_REGID_RA                           0x0000001A
-#define DREG_REGID_RB                           0x0000001B
-#define DREG_REGID_RC                           0x0000001C
-#define DREG_REGID_RD                           0x0000001D
-#define DREG_REGID_RE                           0x0000001E
-#define DREG_REGID_RF                           0x0000001F
-#define DREG_REGID_RA_BUS_LOW                   0x00000020
-#define DREG_REGID_RA_BUS_HIGH                  0x00000038
-#define DREG_REGID_YBUS_LOW                     0x00000050
-#define DREG_REGID_YBUS_HIGH                    0x00000058
-#define DREG_REGID_TRAP_0                       0x00000100
-#define DREG_REGID_TRAP_1                       0x00000101
-#define DREG_REGID_TRAP_2                       0x00000102
-#define DREG_REGID_TRAP_3                       0x00000103
-#define DREG_REGID_TRAP_4                       0x00000104
-#define DREG_REGID_TRAP_5                       0x00000105
-#define DREG_REGID_TRAP_6                       0x00000106
-#define DREG_REGID_TRAP_7                       0x00000107
-#define DREG_REGID_INDIRECT_ADDRESS             0x0000010E
-#define DREG_REGID_TOP_OF_STACK                 0x0000010F
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_8                       0x00000110
-#define DREG_REGID_TRAP_9                       0x00000111
-#define DREG_REGID_TRAP_10                      0x00000112
-#define DREG_REGID_TRAP_11                      0x00000113
-#define DREG_REGID_TRAP_12                      0x00000114
-#define DREG_REGID_TRAP_13                      0x00000115
-#define DREG_REGID_TRAP_14                      0x00000116
-#define DREG_REGID_TRAP_15                      0x00000117
-#define DREG_REGID_TRAP_16                      0x00000118
-#define DREG_REGID_TRAP_17                      0x00000119
-#define DREG_REGID_TRAP_18                      0x0000011A
-#define DREG_REGID_TRAP_19                      0x0000011B
-#define DREG_REGID_TRAP_20                      0x0000011C
-#define DREG_REGID_TRAP_21                      0x0000011D
-#define DREG_REGID_TRAP_22                      0x0000011E
-#define DREG_REGID_TRAP_23                      0x0000011F
-#endif
-#endif
-#define DREG_REGID_RSA0_LOW                     0x00000200
-#define DREG_REGID_RSA0_HIGH                    0x00000201
-#define DREG_REGID_RSA1_LOW                     0x00000202
-#define DREG_REGID_RSA1_HIGH                    0x00000203
-#define DREG_REGID_RSA2                         0x00000204
-#define DREG_REGID_RSA3                         0x00000205
-#define DREG_REGID_RSI0_LOW                     0x00000206
-#define DREG_REGID_RSI0_HIGH                    0x00000207
-#define DREG_REGID_RSI1                         0x00000208
-#define DREG_REGID_RSI2                         0x00000209
-#define DREG_REGID_SAGUSTATUS                   0x0000020A
-#define DREG_REGID_RSCONFIG01_LOW               0x0000020B
-#define DREG_REGID_RSCONFIG01_HIGH              0x0000020C
-#define DREG_REGID_RSCONFIG23_LOW               0x0000020D
-#define DREG_REGID_RSCONFIG23_HIGH              0x0000020E
-#define DREG_REGID_RSDMA01E                     0x0000020F
-#define DREG_REGID_RSDMA23E                     0x00000210
-#define DREG_REGID_RSD0_LOW                     0x00000211
-#define DREG_REGID_RSD0_HIGH                    0x00000212
-#define DREG_REGID_RSD1_LOW                     0x00000213
-#define DREG_REGID_RSD1_HIGH                    0x00000214
-#define DREG_REGID_RSD2_LOW                     0x00000215
-#define DREG_REGID_RSD2_HIGH                    0x00000216
-#define DREG_REGID_RSD3_LOW                     0x00000217
-#define DREG_REGID_RSD3_HIGH                    0x00000218
-#define DREG_REGID_SRAR_HIGH                    0x0000021A
-#define DREG_REGID_SRAR_LOW                     0x0000021B
-#define DREG_REGID_DMA_STATE                    0x0000021C
-#define DREG_REGID_CURRENT_DMA_STREAM           0x0000021D
-#define DREG_REGID_NEXT_DMA_STREAM              0x0000021E
-#define DREG_REGID_CPU_STATUS                   0x00000300
-#define DREG_REGID_MAC_MODE                     0x00000301
-#define DREG_REGID_STACK_AND_REPEAT             0x00000302
-#define DREG_REGID_INDEX0                       0x00000304
-#define DREG_REGID_INDEX1                       0x00000305
-#define DREG_REGID_DMA_STATE_0_3                0x00000400
-#define DREG_REGID_DMA_STATE_4_7                0x00000404
-#define DREG_REGID_DMA_STATE_8_11               0x00000408
-#define DREG_REGID_DMA_STATE_12_15              0x0000040C
-#define DREG_REGID_DMA_STATE_16_19              0x00000410
-#define DREG_REGID_DMA_STATE_20_23              0x00000414
-#define DREG_REGID_DMA_STATE_24_27              0x00000418
-#define DREG_REGID_DMA_STATE_28_31              0x0000041C
-#define DREG_REGID_DMA_STATE_32_35              0x00000420
-#define DREG_REGID_DMA_STATE_36_39              0x00000424
-#define DREG_REGID_DMA_STATE_40_43              0x00000428
-#define DREG_REGID_DMA_STATE_44_47              0x0000042C
-#define DREG_REGID_DMA_STATE_48_51              0x00000430
-#define DREG_REGID_DMA_STATE_52_55              0x00000434
-#define DREG_REGID_DMA_STATE_56_59              0x00000438
-#define DREG_REGID_DMA_STATE_60_63              0x0000043C
-#define DREG_REGID_DMA_STATE_64_67              0x00000440
-#define DREG_REGID_DMA_STATE_68_71              0x00000444
-#define DREG_REGID_DMA_STATE_72_75              0x00000448
-#define DREG_REGID_DMA_STATE_76_79              0x0000044C
-#define DREG_REGID_DMA_STATE_80_83              0x00000450
-#define DREG_REGID_DMA_STATE_84_87              0x00000454
-#define DREG_REGID_DMA_STATE_88_91              0x00000458
-#define DREG_REGID_DMA_STATE_92_95              0x0000045C
-#define DREG_REGID_TRAP_SELECT                  0x00000500
-#define DREG_REGID_TRAP_WRITE_0                 0x00000500
-#define DREG_REGID_TRAP_WRITE_1                 0x00000501
-#define DREG_REGID_TRAP_WRITE_2                 0x00000502
-#define DREG_REGID_TRAP_WRITE_3                 0x00000503
-#define DREG_REGID_TRAP_WRITE_4                 0x00000504
-#define DREG_REGID_TRAP_WRITE_5                 0x00000505
-#define DREG_REGID_TRAP_WRITE_6                 0x00000506
-#define DREG_REGID_TRAP_WRITE_7                 0x00000507
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_WRITE_8                 0x00000510
-#define DREG_REGID_TRAP_WRITE_9                 0x00000511
-#define DREG_REGID_TRAP_WRITE_10                0x00000512
-#define DREG_REGID_TRAP_WRITE_11                0x00000513
-#define DREG_REGID_TRAP_WRITE_12                0x00000514
-#define DREG_REGID_TRAP_WRITE_13                0x00000515
-#define DREG_REGID_TRAP_WRITE_14                0x00000516
-#define DREG_REGID_TRAP_WRITE_15                0x00000517
-#define DREG_REGID_TRAP_WRITE_16                0x00000518
-#define DREG_REGID_TRAP_WRITE_17                0x00000519
-#define DREG_REGID_TRAP_WRITE_18                0x0000051A
-#define DREG_REGID_TRAP_WRITE_19                0x0000051B
-#define DREG_REGID_TRAP_WRITE_20                0x0000051C
-#define DREG_REGID_TRAP_WRITE_21                0x0000051D
-#define DREG_REGID_TRAP_WRITE_22                0x0000051E
-#define DREG_REGID_TRAP_WRITE_23                0x0000051F
-#endif
-#endif
-#define DREG_REGID_MAC0_ACC0_LOW                0x00000600
-#define DREG_REGID_MAC0_ACC1_LOW                0x00000601
-#define DREG_REGID_MAC0_ACC2_LOW                0x00000602
-#define DREG_REGID_MAC0_ACC3_LOW                0x00000603
-#define DREG_REGID_MAC1_ACC0_LOW                0x00000604
-#define DREG_REGID_MAC1_ACC1_LOW                0x00000605
-#define DREG_REGID_MAC1_ACC2_LOW                0x00000606
-#define DREG_REGID_MAC1_ACC3_LOW                0x00000607
-#define DREG_REGID_MAC0_ACC0_MID                0x00000608
-#define DREG_REGID_MAC0_ACC1_MID                0x00000609
-#define DREG_REGID_MAC0_ACC2_MID                0x0000060A
-#define DREG_REGID_MAC0_ACC3_MID                0x0000060B
-#define DREG_REGID_MAC1_ACC0_MID                0x0000060C
-#define DREG_REGID_MAC1_ACC1_MID                0x0000060D
-#define DREG_REGID_MAC1_ACC2_MID                0x0000060E
-#define DREG_REGID_MAC1_ACC3_MID                0x0000060F
-#define DREG_REGID_MAC0_ACC0_HIGH               0x00000610
-#define DREG_REGID_MAC0_ACC1_HIGH               0x00000611
-#define DREG_REGID_MAC0_ACC2_HIGH               0x00000612
-#define DREG_REGID_MAC0_ACC3_HIGH               0x00000613
-#define DREG_REGID_MAC1_ACC0_HIGH               0x00000614
-#define DREG_REGID_MAC1_ACC1_HIGH               0x00000615
-#define DREG_REGID_MAC1_ACC2_HIGH               0x00000616
-#define DREG_REGID_MAC1_ACC3_HIGH               0x00000617
-#define DREG_REGID_RSHOUT_LOW                   0x00000620
-#define DREG_REGID_RSHOUT_MID                   0x00000628
-#define DREG_REGID_RSHOUT_HIGH                  0x00000630
-
-/*
- *  The following defines are for the flags in the DMA stream requestor write
- */
-#define DSRWP_DSR_MASK                          0x0000000F
-#define DSRWP_DSR_BG_RQ                         0x00000001
-#define DSRWP_DSR_PRIORITY_MASK                 0x00000006
-#define DSRWP_DSR_PRIORITY_0                    0x00000000
-#define DSRWP_DSR_PRIORITY_1                    0x00000002
-#define DSRWP_DSR_PRIORITY_2                    0x00000004
-#define DSRWP_DSR_PRIORITY_3                    0x00000006
-#define DSRWP_DSR_RQ_PENDING                    0x00000008
-
-/*
- *  The following defines are for the flags in the trap write port register.
- */
-#define TWPR_TW_MASK                            0x0000FFFF
-#define TWPR_TW_SHIFT                           0
-
-/*
- *  The following defines are for the flags in the stack pointer write
- *  register.
- */
-#define SPWR_STKP_MASK                          0x0000000F
-#define SPWR_STKP_SHIFT                         0
-
-/*
- *  The following defines are for the flags in the SP interrupt register.
- */
-#define SPIR_FRI                                0x00000001
-#define SPIR_DOI                                0x00000002
-#define SPIR_GPI2                               0x00000004
-#define SPIR_GPI3                               0x00000008
-#define SPIR_IP0                                0x00000010
-#define SPIR_IP1                                0x00000020
-#define SPIR_IP2                                0x00000040
-#define SPIR_IP3                                0x00000080
-
-/*
- *  The following defines are for the flags in the functional group 1 register.
- */
-#define FGR1_F1S_MASK                           0x0000FFFF
-#define FGR1_F1S_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the SP clock status register.
- */
-#define SPCS_FRI                                0x00000001
-#define SPCS_DOI                                0x00000002
-#define SPCS_GPI2                               0x00000004
-#define SPCS_GPI3                               0x00000008
-#define SPCS_IP0                                0x00000010
-#define SPCS_IP1                                0x00000020
-#define SPCS_IP2                                0x00000040
-#define SPCS_IP3                                0x00000080
-#define SPCS_SPRUN                              0x00000100
-#define SPCS_SLEEP                              0x00000200
-#define SPCS_FG                                 0x00000400
-#define SPCS_ORUN                               0x00000800
-#define SPCS_IRQ                                0x00001000
-#define SPCS_FGN_MASK                           0x0000E000
-#define SPCS_FGN_SHIFT                          13
-
-/*
- *  The following defines are for the flags in the SP DMA requestor status
- *  register.
- */
-#define SDSR_DCS_MASK                           0x000000FF
-#define SDSR_DCS_SHIFT                          0
-#define SDSR_DCS_NONE                           0x00000007
-
-/*
- *  The following defines are for the flags in the frame timer register.
- */
-#define FRMT_FTV_MASK                           0x0000FFFF
-#define FRMT_FTV_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the frame timer current count
- *  register.
- */
-#define FRCC_FCC_MASK                           0x0000FFFF
-#define FRCC_FCC_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the frame timer save count
- *  register.
- */
-#define FRSC_FCS_MASK                           0x0000FFFF
-#define FRSC_FCS_SHIFT                          0
-
-/*
- *  The following define the various flags stored in the scatter/gather
- *  descriptors.
- */
-#define DMA_SG_NEXT_ENTRY_MASK                  0x00000FF8
-#define DMA_SG_SAMPLE_END_MASK                  0x0FFF0000
-#define DMA_SG_SAMPLE_END_FLAG                  0x10000000
-#define DMA_SG_LOOP_END_FLAG                    0x20000000
-#define DMA_SG_SIGNAL_END_FLAG                  0x40000000
-#define DMA_SG_SIGNAL_PAGE_FLAG                 0x80000000
-#define DMA_SG_NEXT_ENTRY_SHIFT                 3
-#define DMA_SG_SAMPLE_END_SHIFT                 16
-
-/*
- *  The following define the offsets of the fields within the on-chip generic
- *  DMA requestor.
- */
-#define DMA_RQ_CONTROL1                         0x00000000
-#define DMA_RQ_CONTROL2                         0x00000004
-#define DMA_RQ_SOURCE_ADDR                      0x00000008
-#define DMA_RQ_DESTINATION_ADDR                 0x0000000C
-#define DMA_RQ_NEXT_PAGE_ADDR                   0x00000010
-#define DMA_RQ_NEXT_PAGE_SGDESC                 0x00000014
-#define DMA_RQ_LOOP_START_ADDR                  0x00000018
-#define DMA_RQ_POST_LOOP_ADDR                   0x0000001C
-#define DMA_RQ_PAGE_MAP_ADDR                    0x00000020
-
-/*
- *  The following defines are for the flags in the first control word of the
- *  on-chip generic DMA requestor.
- */
-#define DMA_RQ_C1_COUNT_MASK                    0x000003FF
-#define DMA_RQ_C1_DESTINATION_SCATTER           0x00001000
-#define DMA_RQ_C1_SOURCE_GATHER                 0x00002000
-#define DMA_RQ_C1_DONE_FLAG                     0x00004000
-#define DMA_RQ_C1_OPTIMIZE_STATE                0x00008000
-#define DMA_RQ_C1_SAMPLE_END_STATE_MASK         0x00030000
-#define DMA_RQ_C1_FULL_PAGE                     0x00000000
-#define DMA_RQ_C1_BEFORE_SAMPLE_END             0x00010000
-#define DMA_RQ_C1_PAGE_MAP_ERROR                0x00020000
-#define DMA_RQ_C1_AT_SAMPLE_END                 0x00030000
-#define DMA_RQ_C1_LOOP_END_STATE_MASK           0x000C0000
-#define DMA_RQ_C1_NOT_LOOP_END                  0x00000000
-#define DMA_RQ_C1_BEFORE_LOOP_END               0x00040000
-#define DMA_RQ_C1_2PAGE_LOOP_BEGIN              0x00080000
-#define DMA_RQ_C1_LOOP_BEGIN                    0x000C0000
-#define DMA_RQ_C1_PAGE_MAP_MASK                 0x00300000
-#define DMA_RQ_C1_PM_NONE_PENDING               0x00000000
-#define DMA_RQ_C1_PM_NEXT_PENDING               0x00100000
-#define DMA_RQ_C1_PM_RESERVED                   0x00200000
-#define DMA_RQ_C1_PM_LOOP_NEXT_PENDING          0x00300000
-#define DMA_RQ_C1_WRITEBACK_DEST_FLAG           0x00400000
-#define DMA_RQ_C1_WRITEBACK_SRC_FLAG            0x00800000
-#define DMA_RQ_C1_DEST_SIZE_MASK                0x07000000
-#define DMA_RQ_C1_DEST_LINEAR                   0x00000000
-#define DMA_RQ_C1_DEST_MOD16                    0x01000000
-#define DMA_RQ_C1_DEST_MOD32                    0x02000000
-#define DMA_RQ_C1_DEST_MOD64                    0x03000000
-#define DMA_RQ_C1_DEST_MOD128                   0x04000000
-#define DMA_RQ_C1_DEST_MOD256                   0x05000000
-#define DMA_RQ_C1_DEST_MOD512                   0x06000000
-#define DMA_RQ_C1_DEST_MOD1024                  0x07000000
-#define DMA_RQ_C1_DEST_ON_HOST                  0x08000000
-#define DMA_RQ_C1_SOURCE_SIZE_MASK              0x70000000
-#define DMA_RQ_C1_SOURCE_LINEAR                 0x00000000
-#define DMA_RQ_C1_SOURCE_MOD16                  0x10000000
-#define DMA_RQ_C1_SOURCE_MOD32                  0x20000000
-#define DMA_RQ_C1_SOURCE_MOD64                  0x30000000
-#define DMA_RQ_C1_SOURCE_MOD128                 0x40000000
-#define DMA_RQ_C1_SOURCE_MOD256                 0x50000000
-#define DMA_RQ_C1_SOURCE_MOD512                 0x60000000
-#define DMA_RQ_C1_SOURCE_MOD1024                0x70000000
-#define DMA_RQ_C1_SOURCE_ON_HOST                0x80000000
-#define DMA_RQ_C1_COUNT_SHIFT                   0
-
-/*
- *  The following defines are for the flags in the second control word of the
- *  on-chip generic DMA requestor.
- */
-#define DMA_RQ_C2_VIRTUAL_CHANNEL_MASK          0x0000003F
-#define DMA_RQ_C2_VIRTUAL_SIGNAL_MASK           0x00000300
-#define DMA_RQ_C2_NO_VIRTUAL_SIGNAL             0x00000000
-#define DMA_RQ_C2_SIGNAL_EVERY_DMA              0x00000100
-#define DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG        0x00000200
-#define DMA_RQ_C2_SIGNAL_DEST_PINGPONG          0x00000300
-#define DMA_RQ_C2_AUDIO_CONVERT_MASK            0x0000F000
-#define DMA_RQ_C2_AC_NONE                       0x00000000
-#define DMA_RQ_C2_AC_8_TO_16_BIT                0x00001000
-#define DMA_RQ_C2_AC_MONO_TO_STEREO             0x00002000
-#define DMA_RQ_C2_AC_ENDIAN_CONVERT             0x00004000
-#define DMA_RQ_C2_AC_SIGNED_CONVERT             0x00008000
-#define DMA_RQ_C2_LOOP_END_MASK                 0x0FFF0000
-#define DMA_RQ_C2_LOOP_MASK                     0x30000000
-#define DMA_RQ_C2_NO_LOOP                       0x00000000
-#define DMA_RQ_C2_ONE_PAGE_LOOP                 0x10000000
-#define DMA_RQ_C2_TWO_PAGE_LOOP                 0x20000000
-#define DMA_RQ_C2_MULTI_PAGE_LOOP               0x30000000
-#define DMA_RQ_C2_SIGNAL_LOOP_BACK              0x40000000
-#define DMA_RQ_C2_SIGNAL_POST_BEGIN_PAGE        0x80000000
-#define DMA_RQ_C2_VIRTUAL_CHANNEL_SHIFT         0
-#define DMA_RQ_C2_LOOP_END_SHIFT                16
-
-/*
- *  The following defines are for the flags in the source and destination words
- *  of the on-chip generic DMA requestor.
- */
-#define DMA_RQ_SD_ADDRESS_MASK                  0x0000FFFF
-#define DMA_RQ_SD_MEMORY_ID_MASK                0x000F0000
-#define DMA_RQ_SD_SP_PARAM_ADDR                 0x00000000
-#define DMA_RQ_SD_SP_SAMPLE_ADDR                0x00010000
-#define DMA_RQ_SD_SP_PROGRAM_ADDR               0x00020000
-#define DMA_RQ_SD_SP_DEBUG_ADDR                 0x00030000
-#define DMA_RQ_SD_OMNIMEM_ADDR                  0x000E0000
-#define DMA_RQ_SD_END_FLAG                      0x40000000
-#define DMA_RQ_SD_ERROR_FLAG                    0x80000000
-#define DMA_RQ_SD_ADDRESS_SHIFT                 0
-
-/*
- *  The following defines are for the flags in the page map address word of the
- *  on-chip generic DMA requestor.
- */
-#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_MASK   0x00000FF8
-#define DMA_RQ_PMA_PAGE_TABLE_MASK              0xFFFFF000
-#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_SHIFT  3
-#define DMA_RQ_PMA_PAGE_TABLE_SHIFT             12
-
-#define BA1_VARIDEC_BUF_1       0x000
-
-#define BA1_PDTC                0x0c0    /* BA1_PLAY_DMA_TRANSACTION_COUNT_REG */
-#define BA1_PFIE                0x0c4    /* BA1_PLAY_FORMAT_&_INTERRUPT_ENABLE_REG */
-#define BA1_PBA                 0x0c8    /* BA1_PLAY_BUFFER_ADDRESS */
-#define BA1_PVOL                0x0f8    /* BA1_PLAY_VOLUME_REG */
-#define BA1_PSRC                0x288    /* BA1_PLAY_SAMPLE_RATE_CORRECTION_REG */
-#define BA1_PCTL                0x2a4    /* BA1_PLAY_CONTROL_REG */
-#define BA1_PPI                 0x2b4    /* BA1_PLAY_PHASE_INCREMENT_REG */
-
-#define BA1_CCTL                0x064    /* BA1_CAPTURE_CONTROL_REG */
-#define BA1_CIE                 0x104    /* BA1_CAPTURE_INTERRUPT_ENABLE_REG */
-#define BA1_CBA                 0x10c    /* BA1_CAPTURE_BUFFER_ADDRESS */
-#define BA1_CSRC                0x2c8    /* BA1_CAPTURE_SAMPLE_RATE_CORRECTION_REG */
-#define BA1_CCI                 0x2d8    /* BA1_CAPTURE_COEFFICIENT_INCREMENT_REG */
-#define BA1_CD                  0x2e0    /* BA1_CAPTURE_DELAY_REG */
-#define BA1_CPI                 0x2f4    /* BA1_CAPTURE_PHASE_INCREMENT_REG */
-#define BA1_CVOL                0x2f8    /* BA1_CAPTURE_VOLUME_REG */
-
-#define BA1_CFG1                0x134    /* BA1_CAPTURE_FRAME_GROUP_1_REG */
-#define BA1_CFG2                0x138    /* BA1_CAPTURE_FRAME_GROUP_2_REG */
-#define BA1_CCST                0x13c    /* BA1_CAPTURE_CONSTANT_REG */
-#define BA1_CSPB                0x340    /* BA1_CAPTURE_SPB_ADDRESS */
-
-/*
- *
- */
-
-#define CS461X_MODE_OUTPUT	(1<<0)	 /* MIDI UART - output */ 
-#define CS461X_MODE_INPUT	(1<<1)	 /* MIDI UART - input */
-
-//****************************************************************************
-//
-// The following define the offsets of the AC97 shadow registers, which appear
-// as a virtual extension to the base address register zero memory range.
-//
-//****************************************************************************
-#define AC97_REG_OFFSET_MASK                    0x0000007EL
-#define AC97_CODEC_NUMBER_MASK                  0x00003000L
-
-#define BA0_AC97_RESET                          0x00001000L
-#define BA0_AC97_MASTER_VOLUME                  0x00001002L
-#define BA0_AC97_HEADPHONE_VOLUME               0x00001004L
-#define BA0_AC97_MASTER_VOLUME_MONO             0x00001006L
-#define BA0_AC97_MASTER_TONE                    0x00001008L
-#define BA0_AC97_PC_BEEP_VOLUME                 0x0000100AL
-#define BA0_AC97_PHONE_VOLUME                   0x0000100CL
-#define BA0_AC97_MIC_VOLUME                     0x0000100EL
-#define BA0_AC97_LINE_IN_VOLUME                 0x00001010L
-#define BA0_AC97_CD_VOLUME                      0x00001012L
-#define BA0_AC97_VIDEO_VOLUME                   0x00001014L
-#define BA0_AC97_AUX_VOLUME                     0x00001016L
-#define BA0_AC97_PCM_OUT_VOLUME                 0x00001018L
-#define BA0_AC97_RECORD_SELECT                  0x0000101AL
-#define BA0_AC97_RECORD_GAIN                    0x0000101CL
-#define BA0_AC97_RECORD_GAIN_MIC                0x0000101EL
-#define BA0_AC97_GENERAL_PURPOSE                0x00001020L
-#define BA0_AC97_3D_CONTROL                     0x00001022L
-#define BA0_AC97_MODEM_RATE                     0x00001024L
-#define BA0_AC97_POWERDOWN                      0x00001026L
-#define BA0_AC97_EXT_AUDIO_ID                   0x00001028L
-#define BA0_AC97_EXT_AUDIO_POWER                0x0000102AL
-#define BA0_AC97_PCM_FRONT_DAC_RATE             0x0000102CL
-#define BA0_AC97_PCM_SURR_DAC_RATE              0x0000102EL
-#define BA0_AC97_PCM_LFE_DAC_RATE               0x00001030L
-#define BA0_AC97_PCM_LR_ADC_RATE                0x00001032L
-#define BA0_AC97_MIC_ADC_RATE                   0x00001034L
-#define BA0_AC97_6CH_VOL_C_LFE                  0x00001036L
-#define BA0_AC97_6CH_VOL_SURROUND               0x00001038L
-#define BA0_AC97_RESERVED_3A                    0x0000103AL
-#define BA0_AC97_EXT_MODEM_ID                   0x0000103CL
-#define BA0_AC97_EXT_MODEM_POWER                0x0000103EL
-#define BA0_AC97_LINE1_CODEC_RATE               0x00001040L
-#define BA0_AC97_LINE2_CODEC_RATE               0x00001042L
-#define BA0_AC97_HANDSET_CODEC_RATE             0x00001044L
-#define BA0_AC97_LINE1_CODEC_LEVEL              0x00001046L
-#define BA0_AC97_LINE2_CODEC_LEVEL              0x00001048L
-#define BA0_AC97_HANDSET_CODEC_LEVEL            0x0000104AL
-#define BA0_AC97_GPIO_PIN_CONFIG                0x0000104CL
-#define BA0_AC97_GPIO_PIN_TYPE                  0x0000104EL
-#define BA0_AC97_GPIO_PIN_STICKY                0x00001050L
-#define BA0_AC97_GPIO_PIN_WAKEUP                0x00001052L
-#define BA0_AC97_GPIO_PIN_STATUS                0x00001054L
-#define BA0_AC97_MISC_MODEM_AFE_STAT            0x00001056L
-#define BA0_AC97_RESERVED_58                    0x00001058L
-#define BA0_AC97_CRYSTAL_REV_N_FAB_ID           0x0000105AL
-#define BA0_AC97_TEST_AND_MISC_CTRL             0x0000105CL
-#define BA0_AC97_AC_MODE                        0x0000105EL
-#define BA0_AC97_MISC_CRYSTAL_CONTROL           0x00001060L
-#define BA0_AC97_LINE1_HYPRID_CTRL              0x00001062L
-#define BA0_AC97_VENDOR_RESERVED_64             0x00001064L
-#define BA0_AC97_VENDOR_RESERVED_66             0x00001066L
-#define BA0_AC97_SPDIF_CONTROL                  0x00001068L
-#define BA0_AC97_VENDOR_RESERVED_6A             0x0000106AL
-#define BA0_AC97_VENDOR_RESERVED_6C             0x0000106CL
-#define BA0_AC97_VENDOR_RESERVED_6E             0x0000106EL
-#define BA0_AC97_VENDOR_RESERVED_70             0x00001070L
-#define BA0_AC97_VENDOR_RESERVED_72             0x00001072L
-#define BA0_AC97_VENDOR_RESERVED_74             0x00001074L
-#define BA0_AC97_CAL_ADDRESS                    0x00001076L
-#define BA0_AC97_CAL_DATA                       0x00001078L
-#define BA0_AC97_VENDOR_RESERVED_7A             0x0000107AL
-#define BA0_AC97_VENDOR_ID1                     0x0000107CL
-#define BA0_AC97_VENDOR_ID2                     0x0000107EL
-#endif				/* __CS461X_H */
diff --git a/sound/oss/cs461x_image.h b/sound/oss/cs461x_image.h
deleted file mode 100644
index b5c5a46..0000000
--- a/sound/oss/cs461x_image.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/****************************************************************************
- * "CWCIMAGE.H"-- For CS46XX. Ver 1.04
- *      Copyright 1998-2001 (c) Cirrus Logic Corp.
- *      Version 1.04
- ****************************************************************************
- */
-#ifndef __CS_IMAGE_H
-#define __CS_IMAGE_H
-
-#define CLEAR__COUNT     3
-#define FILL__COUNT      4
-#define BA1__DWORD_SIZE  13*1024+512
-
-static struct
-{
-        unsigned BA1__DestByteOffset;
-        unsigned BA1__SourceSize;
-} ClrStat[CLEAR__COUNT] ={ {0x00000000, 0x00003000 },
-                           {0x00010000, 0x00003800 },
-                           {0x00020000, 0x00007000 } };
-
-static u32 FillArray1[]={
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00200040,0x00008010,0x00000000,
-0x00000000,0x80000001,0x00000001,0x00060000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00900080,0x00000173,0x00000000,
-0x00000000,0x00000010,0x00800000,0x00900000,
-0xf2c0000f,0x00000200,0x00000000,0x00010600,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x330300c2,
-0x06000000,0x00000000,0x80008000,0x80008000,
-0x3fc0000f,0x00000301,0x00010400,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00b00000,0x00d0806d,0x330480c3,
-0x04800000,0x00000001,0x00800001,0x0000ffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x066a0600,0x06350070,0x0000929d,0x929d929d,
-0x00000000,0x0000735a,0x00000600,0x00000000,
-0x929d735a,0x00000000,0x00010000,0x735a735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000804f,0x000000c3,
-0x05000000,0x00a00010,0x00000000,0x80008000,
-0x00000000,0x00000000,0x00000700,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000080,0x00a00000,0x0000809a,0x000000c2,
-0x07400000,0x00000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x000107a0,
-0x00c80028,0x000000c2,0x06800000,0x00000000,
-0x06e00080,0x00300000,0x000080bb,0x000000c9,
-0x07a00000,0x04000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x00000780,
-0x00c80028,0x000000c5,0xff800000,0x00000000,
-0x00640080,0x00c00000,0x00008197,0x000000c9,
-0x07800000,0x04000000,0x80008000,0xffffffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000805e,0x000000c1,
-0x00000000,0x00800000,0x80008000,0x80008000,
-0x00020000,0x0000ffff,0x00000000,0x00000000};
-
-static u32 FillArray2[]={
-0x929d0600,0x929d929d,0x929d929d,0x929d0000,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x00100635,0x060b013f,0x00000004,
-0x00000001,0x007a0002,0x00000000,0x066e0610,
-0x0105929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
-0x00000000,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x00000000,0x06400136,
-0x0000270f,0x00010000,0x007a0000,0x00000000,
-0x068e0645,0x0105929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x735a0100,0x00000000,0x00000000,0x00000000};
-
-static u32 FillArray3[]={
-0x00000000,0x00000000,0x00000000,0x00010004};
-
-static u32 FillArray4[]={
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00001705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00009705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00011705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00019705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00021705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00029705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00031705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00039705,0x00001400,0x000a411e,0x00001003,
-0x000fe19e,0x00001003,0x0009c730,0x00001003,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00009705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00011705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00019705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00021705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00029705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00031705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00039705,0x00001400,0x000a211e,0x00001003,
-0x0000a730,0x00001008,0x000e2730,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x00000000,0x00000000,0x000f619c,0x00001003,
-0x0007f801,0x000c0000,0x00000037,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0000373c,0x00001000,0x00000000,0x00000000,
-0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000273c,0x00001000,
-0x00000033,0x00001000,0x000e679e,0x00001003,
-0x00007705,0x00001400,0x000ac71e,0x00001003,
-0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000a730,0x00001003,
-0x00000033,0x00001000,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x000c0000,
-0x00000032,0x00001000,0x0000273d,0x00001000,
-0x0004a730,0x00001003,0x00000f41,0x00097140,
-0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-0x00002725,0x000aa400,0x00013705,0x00093a00,
-0x0000002e,0x0009d6c0,0x00038630,0x00001004,
-0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
-0x00000000,0x000c70e0,0x0007d182,0x0002c640,
-0x00000630,0x00001004,0x000799b8,0x0002c6c0,
-0x00031705,0x00092240,0x00039f05,0x000932c0,
-0x0003520a,0x00000000,0x00040731,0x0000100b,
-0x00010705,0x000b20c0,0x00000000,0x000eba44,
-0x00032108,0x000c60c4,0x00065208,0x000c2917,
-0x000406b0,0x00001007,0x00012f05,0x00036880,
-0x0002818e,0x000c0000,0x0004410a,0x00000000,
-0x00040630,0x00001007,0x00029705,0x000c0000,
-0x00000000,0x00000000,0x00003fc1,0x0003fc40,
-0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
-0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
-0x000037c1,0x00000000,0x00003fc1,0x000991c0,
-0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
-0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
-0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
-0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
-0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
-0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
-0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
-0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
-0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
-0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
-0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
-0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
-0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
-0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
-0x000683ad,0x00095241,0x00020f05,0x000991c1,
-0x00000000,0x00000000,0x00086f88,0x00001000,
-0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
-0x0009de81,0x000bd300,0x0009d601,0x000b1700,
-0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
-0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
-0x000a1681,0x000b97c0,0x00021601,0x00002500,
-0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
-0x00021681,0x00002d00,0x00020f81,0x000bd800,
-0x000a0701,0x000b5bc0,0x00021601,0x00003500,
-0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
-0x00021681,0x00003d00,0x00020f81,0x000b1d00,
-0x000a0701,0x000b1fc0,0x00021601,0x00020500,
-0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
-0x00021681,0x00020d00,0x00020f81,0x000bde80,
-0x000a0701,0x000bdfc0,0x00021601,0x00021500,
-0x00020f81,0x000b9341,0x00020701,0x000b53c1,
-0x00021681,0x00021d00,0x000a0f81,0x000d0380,
-0x0000b601,0x000b15c0,0x00007b01,0x00000000,
-0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
-0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
-0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
-0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
-0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
-0x0007e48a,0x00000000,0x00011f05,0x00084080,
-0x00000000,0x00000000,0x00001705,0x000b3540,
-0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
-0x00055488,0x00000000,0x0000d482,0x0003fc40,
-0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
-0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
-0x000c86b0,0x00001007,0x00008281,0x000bb240,
-0x0000b801,0x000b7140,0x00007888,0x00000000,
-0x0000073c,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x00055288,0x000c555c,
-0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-0x0000fa88,0x00000000,0x00000032,0x00001000,
-0x0000073d,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x0008c01c,0x00001003,
-0x00002705,0x00001008,0x0008b201,0x000c1392,
-0x0000ba01,0x00000000,0x00008731,0x00001400,
-0x0004c108,0x000fe0c4,0x00057488,0x00000000,
-0x000a6388,0x00001001,0x0008b334,0x000bc141,
-0x0003020e,0x00000000,0x000886b0,0x00001008,
-0x00003625,0x000c5dfa,0x000a638a,0x00001001,
-0x0008020e,0x00001002,0x0008a6b0,0x00001008,
-0x0007f301,0x00000000,0x00000000,0x00000000,
-0x00002725,0x000a8c40,0x000000ae,0x00000000,
-0x000d8630,0x00001008,0x00000000,0x000c74e0,
-0x0007d182,0x0002d640,0x000a8630,0x00001008,
-0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5,
-0x0007420a,0x000c0000,0x00062208,0x000c4117,
-0x00070630,0x00001009,0x00000000,0x000c0000,
-0x0001022e,0x00000000,0x0003a630,0x00001009,
-0x00000000,0x000c0000,0x00000036,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x0002a730,0x00001008,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0002a730,0x00001008,
-0x00000033,0x00001000,0x0002a705,0x00001008,
-0x00007a01,0x000c0000,0x000e6288,0x000d550a,
-0x0006428a,0x00000000,0x00060730,0x0000100a,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
-0x00057488,0x00000000,0x00033b94,0x00081140,
-0x000183ae,0x00000000,0x000786b0,0x0000100b,
-0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-0x00042731,0x00001003,0x0007aab0,0x00034880,
-0x00048fb0,0x0000100a,0x00057488,0x00000000,
-0x00033b94,0x00081140,0x000183ae,0x00000000,
-0x000806b0,0x0000100b,0x00022f05,0x00000000,
-0x00007401,0x00091140,0x00048f05,0x000951c0,
-0x00042731,0x00001003,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x000fe19e,0x00001003,0x00000000,0x00000000,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00000f41,0x00097140,0x0000a841,0x0009b240,
-0x0000a0c1,0x0009f040,0x0001c641,0x00093540,
-0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44,
-0x00055208,0x00000000,0x00010705,0x000a2880,
-0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5,
-0x0004ef0a,0x000c0000,0x00012f05,0x00036880,
-0x00065308,0x000c2997,0x000d86b0,0x0000100a,
-0x0004410a,0x000d40c7,0x00000000,0x00000000,
-0x00080730,0x00001004,0x00056f0a,0x000ea105,
-0x00000000,0x00000000,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x0000273d,0x00001000,0x00000000,0x000eba44,
-0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x00000000,0x000e5084,
-0x00000000,0x000eba44,0x00087401,0x000e4782,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x0007c108,0x000c0000,
-0x0007e721,0x000bed40,0x00005f25,0x000badc0,
-0x0003ba97,0x000beb80,0x00065590,0x000b2e00,
-0x00033217,0x00003ec0,0x00065590,0x000b8e40,
-0x0003ed80,0x000491c0,0x00073fb0,0x00074c80,
-0x000283a0,0x0000100c,0x000ee388,0x00042970,
-0x00008301,0x00021ef2,0x000b8f14,0x0000000f,
-0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6,
-0x000032ac,0x000c3916,0x0004edc2,0x00074c80,
-0x00078898,0x00001000,0x00038894,0x00000032,
-0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6,
-0x0004edc2,0x000c1956,0x0000722c,0x00034a00,
-0x00041705,0x0009ed40,0x00058730,0x00001400,
-0x000d7488,0x000c3a00,0x00048f05,0x00000000};
-
-static struct
-{   u32 Offset;
-    u32 Size;
-    u32 *pFill;
-} FillStat[FILL__COUNT] = {
-                            {0x00000000, sizeof(FillArray1), FillArray1},
-                            {0x00001800, sizeof(FillArray2), FillArray2},
-                            {0x000137f0, sizeof(FillArray3), FillArray3},
-                            {0x00020000, sizeof(FillArray4), FillArray4}
-                          };
-
-
-#endif
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
deleted file mode 100644
index 2a1f0d9..0000000
--- a/sound/oss/cs46xx.c
+++ /dev/null
@@ -1,5444 +0,0 @@
-/*
- *	Crystal SoundFusion CS46xx driver
- *
- *	Copyright 1998-2001 Cirrus Logic Corporation <pcaudio@crystal.cirrus.com>
- *						<twoller@crystal.cirrus.com>
- *	Copyright 1999-2000 Jaroslav Kysela <perex@suse.cz>
- *	Copyright 2000 Alan Cox <alan@redhat.com>
- *
- *	The core of this code is taken from the ALSA project driver by 
- *	Jaroslav. Please send Jaroslav the credit for the driver and 
- *	report bugs in this port to <alan@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.
- *
- *	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.
- *	Current maintainers:
- *		Cirrus Logic Corporation, Thomas Woller (tw)
- *			<twoller@crystal.cirrus.com>
- *		Nils Faerber (nf)
- *			<nils@kernelconcepts.de>
- *		Thanks to David Pollard for testing.
- *
- *	Changes:
- *	20000909-nf	Changed cs_read, cs_write and drain_dac
- *	20001025-tw	Separate Playback/Capture structs and buffers.
- *			Added Scatter/Gather support for Playback.
- *			Added Capture.
- *	20001027-nf	Port to kernel 2.4.0-test9, some clean-ups
- *			Start of powermanagement support (CS46XX_PM).
- *	20001128-tw	Add module parm for default buffer order.
- *			added DMA_GFP flag to kmalloc dma buffer allocs.
- *			backfill silence to eliminate stuttering on
- *			underruns.
- *	20001201-tw	add resyncing of swptr on underruns.
- *	20001205-tw-nf	fixed GETOSPACE ioctl() after open()
- *	20010113-tw	patch from Hans Grobler general cleanup.
- *	20010117-tw	2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0
- *	20010118-tw	basic PM support for 2.2.16+ and 2.4.0/2.4.2.
- *	20010228-dh	patch from David Huggins - cs_update_ptr recursion.
- *	20010409-tw	add hercules game theatre XP amp code.
- *	20010420-tw	cleanup powerdown/up code.
- *	20010521-tw	eliminate pops, and fixes for powerdown.
- *	20010525-tw	added fixes for thinkpads with powerdown logic.
- *	20010723-sh     patch from Horms (Simon Horman) -
- *	                SOUND_PCM_READ_BITS returns bits as set in driver
- *	                rather than a logical or of the possible values.
- *	                Various ioctls handle the case where the device
- *	                is open for reading or writing but not both better.
- *
- *	Status:
- *	Playback/Capture supported from 8k-48k.
- *	16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
- *
- *	APM/PM - 2.2.x APM is enabled and functioning fine. APM can also
- *	be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
- *	definition.
- *
- *      Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
- *	so, use the drain/polarity to enable.  
- *	hercules_egpio_disable set to 1, will force a 0 to EGPIODR.
- *
- *	VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
- *	the external amplifier for the "back" speakers, since we do not
- *	support the secondary codec then this external amp is also not
- *	turned on.
- */
- 
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/ac97_codec.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include "cs46xxpm.h"
-#include "cs46xx_wrapper-24.h"
-#include "cs461x.h"
-
-/* MIDI buffer sizes */
-#define CS_MIDIINBUF  500
-#define CS_MIDIOUTBUF 500
-
-#define ADC_RUNNING	1
-#define DAC_RUNNING	2
-
-#define CS_FMT_16BIT	1		/* These are fixed in fact */
-#define CS_FMT_STEREO	2
-#define CS_FMT_MASK	3
-
-#define CS_TYPE_ADC	1
-#define CS_TYPE_DAC	2
-
-#define CS_TRUE 	1
-#define CS_FALSE 	0
-
-#define CS_INC_USE_COUNT(m) (atomic_inc(m))
-#define CS_DEC_USE_COUNT(m) (atomic_dec(m))
-#define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m))
-#define CS_IN_USE(m) (atomic_read(m) != 0)
-
-#define CS_DBGBREAKPOINT {__asm__("INT $3");}
-/*
- *	CS461x definitions
- */
- 
-#define CS461X_BA0_SIZE		0x2000
-#define CS461X_BA1_DATA0_SIZE	0x3000
-#define CS461X_BA1_DATA1_SIZE	0x3800
-#define CS461X_BA1_PRG_SIZE	0x7000
-#define CS461X_BA1_REG_SIZE	0x0100
-
-#define GOF_PER_SEC	200
-
-#define CSDEBUG_INTERFACE 1
-#define CSDEBUG 1
-/*
- * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG
- *
- *
- * CSDEBUG is usual mode is set to 1, then use the
- * cs_debuglevel and cs_debugmask to turn on or off debugging.
- * Debug level of 1 has been defined to be kernel errors and info
- * that should be printed on any released driver.
- */
-#if CSDEBUG
-#define CS_DBGOUT(mask,level,x) if ((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;}
-#else
-#define CS_DBGOUT(mask,level,x) 
-#endif
-/*
- * cs_debugmask areas
- */
-#define CS_INIT	 	0x00000001		/* initialization and probe functions */
-#define CS_ERROR 	0x00000002		/* tmp debugging bit placeholder */
-#define CS_INTERRUPT	0x00000004		/* interrupt handler (separate from all other) */
-#define CS_FUNCTION 	0x00000008		/* enter/leave functions */
-#define CS_WAVE_WRITE 	0x00000010		/* write information for wave */
-#define CS_WAVE_READ 	0x00000020		/* read information for wave */
-#define CS_MIDI_WRITE 	0x00000040		/* write information for midi */
-#define CS_MIDI_READ 	0x00000080		/* read information for midi */
-#define CS_MPU401_WRITE 0x00000100		/* write information for mpu401 */
-#define CS_MPU401_READ 	0x00000200		/* read information for mpu401 */
-#define CS_OPEN		0x00000400		/* all open functions in the driver */
-#define CS_RELEASE	0x00000800		/* all release functions in the driver */
-#define CS_PARMS	0x00001000		/* functional and operational parameters */
-#define CS_IOCTL	0x00002000		/* ioctl (non-mixer) */
-#define CS_PM		0x00004000		/* PM */
-#define CS_TMP		0x10000000		/* tmp debug mask bit */
-
-#define CS_IOCTL_CMD_SUSPEND	0x1	// suspend
-#define CS_IOCTL_CMD_RESUME	0x2	// resume
-
-#if CSDEBUG
-static unsigned long cs_debuglevel = 1;			/* levels range from 1-9 */
-module_param(cs_debuglevel, ulong, 0644);
-static unsigned long cs_debugmask = CS_INIT | CS_ERROR;	/* use CS_DBGOUT with various mask values */
-module_param(cs_debugmask, ulong, 0644);
-#endif
-static unsigned long hercules_egpio_disable;  /* if non-zero set all EGPIO to 0 */
-module_param(hercules_egpio_disable, ulong, 0);
-static unsigned long initdelay = 700;  /* PM delay in millisecs */
-module_param(initdelay, ulong, 0);
-static unsigned long powerdown = -1;  /* turn on/off powerdown processing in driver */
-module_param(powerdown, ulong, 0);
-#define DMABUF_DEFAULTORDER 3
-static unsigned long defaultorder = DMABUF_DEFAULTORDER;
-module_param(defaultorder, ulong, 0);
-
-static int external_amp;
-module_param(external_amp, bool, 0);
-static int thinkpad;
-module_param(thinkpad, bool, 0);
-
-/*
-* set the powerdown module parm to 0 to disable all 
-* powerdown. also set thinkpad to 1 to disable powerdown, 
-* but also to enable the clkrun functionality.
-*/
-static unsigned cs_powerdown = 1;
-static unsigned cs_laptop_wait = 1;
-
-/* An instance of the 4610 channel */
-struct cs_channel 
-{
-	int used;
-	int num;
-	void *state;
-};
-
-#define CS46XX_MAJOR_VERSION "1"
-#define CS46XX_MINOR_VERSION "28"
-
-#ifdef __ia64__
-#define CS46XX_ARCH	     	"64"	//architecture key
-#else
-#define CS46XX_ARCH	     	"32"	//architecture key
-#endif
-
-static struct list_head cs46xx_devs = { &cs46xx_devs, &cs46xx_devs };
-
-/* magic numbers to protect our data structures */
-#define CS_CARD_MAGIC		0x43525553 /* "CRUS" */
-#define CS_STATE_MAGIC		0x4c4f4749 /* "LOGI" */
-#define NR_HW_CH		3
-
-/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
-#define NR_AC97		2
-
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-
-/* "software" or virtual channel, an instance of opened /dev/dsp */
-struct cs_state {
-	unsigned int magic;
-	struct cs_card *card;	/* Card info */
-
-	/* single open lock mechanism, only used for recording */
-	struct mutex open_mutex;
-	wait_queue_head_t open_wait;
-
-	/* file mode */
-	mode_t open_mode;
-
-	/* virtual channel number */
-	int virt;
-	
-	struct dmabuf {
-		/* wave sample stuff */
-		unsigned int rate;
-		unsigned char fmt, enable;
-
-		/* hardware channel */
-		struct cs_channel *channel;
-		int pringbuf;		/* Software ring slot */
-		void *pbuf;		/* 4K hardware DMA buffer */
-
-		/* OSS buffer management stuff */
-		void *rawbuf;
-		dma_addr_t dma_handle;
-		unsigned buforder;
-		unsigned numfrag;
-		unsigned fragshift;
-		unsigned divisor;
-		unsigned type;
-		void *tmpbuff;			/* tmp buffer for sample conversions */
-		dma_addr_t dmaaddr;
-		dma_addr_t dmaaddr_tmpbuff;
-		unsigned buforder_tmpbuff;	/* Log base 2 of size in bytes.. */
-
-		/* our buffer acts like a circular ring */
-		unsigned hwptr;		/* where dma last started, updated by update_ptr */
-		unsigned swptr;		/* where driver last clear/filled, updated by read/write */
-		int count;		/* bytes to be comsumed or been generated by dma machine */
-		unsigned total_bytes;	/* total bytes dmaed by hardware */
-		unsigned blocks;	/* total blocks */
-
-		unsigned error;		/* number of over/underruns */
-		unsigned underrun;	/* underrun pending before next write has occurred */
-		wait_queue_head_t wait;	/* put process on wait queue when no more space in buffer */
-
-		/* redundant, but makes calculations easier */
-		unsigned fragsize;
-		unsigned dmasize;
-		unsigned fragsamples;
-
-		/* OSS stuff */
-		unsigned mapped:1;
-		unsigned ready:1;
-		unsigned endcleared:1;
-		unsigned SGok:1;
-		unsigned update_flag;
-		unsigned ossfragshift;
-		int ossmaxfrags;
-		unsigned subdivision;
-	} dmabuf;
-	/* Guard against mmap/write/read races */
-	struct mutex sem;
-};
-
-struct cs_card {
-	struct cs_channel channel[2];
-	unsigned int magic;
-
-	/* We keep cs461x cards in a linked list */
-	struct cs_card *next;
-
-	/* The cs461x has a certain amount of cross channel interaction
-	   so we use a single per card lock */
-	spinlock_t lock;
-	
-	/* Keep AC97 sane */
-	spinlock_t ac97_lock;
-
-	/* mixer use count */
-	atomic_t mixer_use_cnt;
-
-	/* PCI device stuff */
-	struct pci_dev *pci_dev;
-	struct list_head list;
-
-	unsigned int pctl, cctl;	/* Hardware DMA flag sets */
-
-	/* soundcore stuff */
-	int dev_audio;
-	int dev_midi;
-
-	/* structures for abstraction of hardware facilities, codecs, banks and channels*/
-	struct ac97_codec *ac97_codec[NR_AC97];
-	struct cs_state *states[2];
-
-	u16 ac97_features;
-	
-	int amplifier;			/* Amplifier control */
-	void (*amplifier_ctrl)(struct cs_card *, int);
-	void (*amp_init)(struct cs_card *);
-	
-	int active;			/* Active clocking */
-	void (*active_ctrl)(struct cs_card *, int);
-	
-	/* hardware resources */
-	unsigned long ba0_addr;
-	unsigned long ba1_addr;
-	u32 irq;
-	
-	/* mappings */
-	void __iomem *ba0;
-	union
-	{
-		struct
-		{
-			u8 __iomem *data0;
-			u8 __iomem *data1;
-			u8 __iomem *pmem;
-			u8 __iomem *reg;
-		} name;
-		u8 __iomem *idx[4];
-	} ba1;
-	
-	/* Function support */
-	struct cs_channel *(*alloc_pcm_channel)(struct cs_card *);
-	struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *);
-	void (*free_pcm_channel)(struct cs_card *, int chan);
-
-	/* /dev/midi stuff */
-	struct {
-		unsigned ird, iwr, icnt;
-		unsigned ord, owr, ocnt;
-		wait_queue_head_t open_wait;
-		wait_queue_head_t iwait;
-		wait_queue_head_t owait;
-		spinlock_t lock;
-		unsigned char ibuf[CS_MIDIINBUF];
-		unsigned char obuf[CS_MIDIOUTBUF];
-		mode_t open_mode;
-		struct mutex open_mutex;
-	} midi;
-	struct cs46xx_pm pm;
-};
-
-static int cs_open_mixdev(struct inode *inode, struct file *file);
-static int cs_release_mixdev(struct inode *inode, struct file *file);
-static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-			unsigned long arg);
-static int cs_hardware_init(struct cs_card *card);
-static int cs46xx_powerup(struct cs_card *card, unsigned int type);
-static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
-static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
-#ifdef CONFIG_PM
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
-static int cs46xx_resume_tbl(struct pci_dev *pcidev);
-#endif
-
-#if CSDEBUG
-
-/* DEBUG ROUTINES */
-
-#define SOUND_MIXER_CS_GETDBGLEVEL 	_SIOWR('M',120, int)
-#define SOUND_MIXER_CS_SETDBGLEVEL 	_SIOWR('M',121, int)
-#define SOUND_MIXER_CS_GETDBGMASK 	_SIOWR('M',122, int)
-#define SOUND_MIXER_CS_SETDBGMASK 	_SIOWR('M',123, int)
-#define SOUND_MIXER_CS_APM	 	_SIOWR('M',124, int)
-
-static void printioctl(unsigned int x)
-{
-    unsigned int i;
-    unsigned char vidx;
-	/* these values are incorrect for the ac97 driver, fix.
-         * Index of mixtable1[] member is Device ID 
-         * and must be <= SOUND_MIXER_NRDEVICES.
-         * Value of array member is index into s->mix.vol[]
-         */
-        static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
-                [SOUND_MIXER_PCM]     = 1,   /* voice */
-                [SOUND_MIXER_LINE1]   = 2,   /* AUX */
-                [SOUND_MIXER_CD]      = 3,   /* CD */
-                [SOUND_MIXER_LINE]    = 4,   /* Line */
-                [SOUND_MIXER_SYNTH]   = 5,   /* FM */
-                [SOUND_MIXER_MIC]     = 6,   /* Mic */
-                [SOUND_MIXER_SPEAKER] = 7,   /* Speaker */
-                [SOUND_MIXER_RECLEV]  = 8,   /* Recording level */
-                [SOUND_MIXER_VOLUME]  = 9    /* Master Volume */
-        };
-        
-    switch (x) {
-	case SOUND_MIXER_CS_GETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") );
-		break;
-	case SOUND_MIXER_CS_GETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGLEVEL: ") );
-		break;
-	case SOUND_MIXER_CS_SETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGMASK: ") );
-		break;
-	case SOUND_MIXER_CS_SETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGLEVEL: ") );
-		break;
-        case OSS_GETVERSION:
-		CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION: ") );
-		break;
-        case SNDCTL_DSP_SYNC:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC: ") );
-		break;
-        case SNDCTL_DSP_SETDUPLEX:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX: ") );
-		break;
-        case SNDCTL_DSP_GETCAPS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS: ") );
-		break;
-        case SNDCTL_DSP_RESET:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET: ") );
-		break;
-        case SNDCTL_DSP_SPEED:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED: ") );
-		break;
-        case SNDCTL_DSP_STEREO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO: ") );
-		break;
-        case SNDCTL_DSP_CHANNELS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS: ") );
-		break;
-        case SNDCTL_DSP_GETFMTS: 
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS: ") );
-		break;
-        case SNDCTL_DSP_SETFMT: 
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT: ") );
-		break;
-        case SNDCTL_DSP_POST:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST: ") );
-		break;
-        case SNDCTL_DSP_GETTRIGGER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER: ") );
-		break;
-        case SNDCTL_DSP_SETTRIGGER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER: ") );
-		break;
-        case SNDCTL_DSP_GETOSPACE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE: ") );
-		break;
-        case SNDCTL_DSP_GETISPACE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE: ") );
-		break;
-        case SNDCTL_DSP_NONBLOCK:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK: ") );
-		break;
-        case SNDCTL_DSP_GETODELAY:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY: ") );
-		break;
-        case SNDCTL_DSP_GETIPTR:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR: ") );
-		break;
-        case SNDCTL_DSP_GETOPTR:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR: ") );
-		break;
-        case SNDCTL_DSP_GETBLKSIZE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE: ") );
-		break;
-        case SNDCTL_DSP_SETFRAGMENT:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT: ") );
-		break;
-        case SNDCTL_DSP_SUBDIVIDE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE: ") );
-		break;
-        case SOUND_PCM_READ_RATE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE: ") );
-		break;
-        case SOUND_PCM_READ_CHANNELS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS: ") );
-		break;
-        case SOUND_PCM_READ_BITS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS: ") );
-		break;
-        case SOUND_PCM_WRITE_FILTER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER: ") );
-		break;
-        case SNDCTL_DSP_SETSYNCRO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO: ") );
-		break;
-        case SOUND_PCM_READ_FILTER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") );
-		break;
-        case SOUND_MIXER_PRIVATE1:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") );
-		break;
-        case SOUND_MIXER_PRIVATE2:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2: ") );
-		break;
-        case SOUND_MIXER_PRIVATE3:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3: ") );
-		break;
-        case SOUND_MIXER_PRIVATE4:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4: ") );
-		break;
-        case SOUND_MIXER_PRIVATE5:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5: ") );
-		break;
-        case SOUND_MIXER_INFO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO: ") );
-		break;
-        case SOUND_OLD_MIXER_INFO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") );
-		break;
-	default:
-		switch (_IOC_NR(x)) {
-			case SOUND_MIXER_VOLUME:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") );
-				break;
-			case SOUND_MIXER_SPEAKER:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER: ") );
-				break;
-			case SOUND_MIXER_RECLEV:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV: ") );
-				break;
-			case SOUND_MIXER_MIC:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC: ") );
-				break;
-			case SOUND_MIXER_SYNTH:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH: ") );
-				break;
-			case SOUND_MIXER_RECSRC: 
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC: ") );
-				break;
-			case SOUND_MIXER_DEVMASK:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK: ") );
-				break;
-			case SOUND_MIXER_RECMASK:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK: ") );
-				break;
-			case SOUND_MIXER_STEREODEVS: 
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS: ") );
-				break;
-			case SOUND_MIXER_CAPS:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:") );
-				break;
-			default:
-				i = _IOC_NR(x);
-				if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) {
-					CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) );
-				} else {
-					CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ",
-							x,i));
-				}
-				break;
-		}
-    }
-    CS_DBGOUT(CS_IOCTL, 4, printk("command = 0x%x IOC_NR=%d\n",x, _IOC_NR(x)) );
-}
-#endif
-
-/*
- *  common I/O routines
- */
-
-static void cs461x_poke(struct cs_card *codec, unsigned long reg, unsigned int val)
-{
-	writel(val, codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
-}
-
-static unsigned int cs461x_peek(struct cs_card *codec, unsigned long reg)
-{
-	return readl(codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
-}
-
-static void cs461x_pokeBA0(struct cs_card *codec, unsigned long reg, unsigned int val)
-{
-	writel(val, codec->ba0 + reg);
-}
-
-static unsigned int cs461x_peekBA0(struct cs_card *codec, unsigned long reg)
-{
-	return readl(codec->ba0 + reg);
-}
-
-
-static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg);
-static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 data);
-
-static struct cs_channel *cs_alloc_pcm_channel(struct cs_card *card)
-{
-	if (card->channel[1].used == 1)
-		return NULL;
-	card->channel[1].used = 1;
-	card->channel[1].num = 1;
-	return &card->channel[1];
-}
-
-static struct cs_channel *cs_alloc_rec_pcm_channel(struct cs_card *card)
-{
-	if (card->channel[0].used == 1)
-		return NULL;
-	card->channel[0].used = 1;
-	card->channel[0].num = 0;
-	return &card->channel[0];
-}
-
-static void cs_free_pcm_channel(struct cs_card *card, int channel)
-{
-	card->channel[channel].state = NULL;
-	card->channel[channel].used = 0;
-}
-
-/*
- * setup a divisor value to help with conversion from
- * 16bit Stereo, down to 8bit stereo/mono or 16bit mono.
- * assign a divisor of 1 if using 16bit Stereo as that is
- * the only format that the static image will capture.
- */
-static void cs_set_divisor(struct dmabuf *dmabuf)
-{
-	if (dmabuf->type == CS_TYPE_DAC)
-		dmabuf->divisor = 1;
-	else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
-	    (dmabuf->fmt & CS_FMT_16BIT))
-		dmabuf->divisor = 2;
-	else if ((dmabuf->fmt & CS_FMT_STEREO) &&
-	    !(dmabuf->fmt & CS_FMT_16BIT))
-		dmabuf->divisor = 2;
-	else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
-	    !(dmabuf->fmt & CS_FMT_16BIT))
-		dmabuf->divisor = 4;
-	else
-		dmabuf->divisor = 1;
-
-	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, printk(
-		"cs46xx: cs_set_divisor()- %s %d\n",
-			(dmabuf->type == CS_TYPE_ADC) ? "ADC" : "DAC", 
-			dmabuf->divisor) );
-}
-
-/*
-* mute some of the more prevalent registers to avoid popping.
-*/
-static void cs_mute(struct cs_card *card, int state) 
-{
-	struct ac97_codec *dev = card->ac97_codec[0];
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()+ %s\n",
-		(state == CS_TRUE) ? "Muting" : "UnMuting"));
-
-	if (state == CS_TRUE) {
-	/*
-	* fix pops when powering up on thinkpads
-	*/
-		card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, 
-				(u8)BA0_AC97_MASTER_VOLUME); 
-		card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, 
-				(u8)BA0_AC97_HEADPHONE_VOLUME); 
-		card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, 
-				(u8)BA0_AC97_MASTER_VOLUME_MONO); 
-		card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, 
-				(u8)BA0_AC97_PCM_OUT_VOLUME);
-			
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
-		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
-		cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
-	} else {
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume);
-		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume);
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono);
-		cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume);
-	}
-	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()-\n"));
-}
-
-/* set playback sample rate */
-static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
-{	
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned int tmp1, tmp2;
-	unsigned int phiIncr;
-	unsigned int correctionPerGOF, correctionPerSec;
-	unsigned long flags;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()+ %d\n",rate) );
-
-	/*
-	 *  Compute the values used to drive the actual sample rate conversion.
-	 *  The following formulas are being computed, using inline assembly
-	 *  since we need to use 64 bit arithmetic to compute the values:
-	 *
-	 *  phiIncr = floor((Fs,in * 2^26) / Fs,out)
-	 *  correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
-         *                                   GOF_PER_SEC)
-         *  ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
-         *                       GOF_PER_SEC * correctionPerGOF
-	 *
-	 *  i.e.
-	 *
-	 *  phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
-	 *  correctionPerGOF:correctionPerSec =
-	 *      dividend:remainder(ulOther / GOF_PER_SEC)
-	 */
-	tmp1 = rate << 16;
-	phiIncr = tmp1 / 48000;
-	tmp1 -= phiIncr * 48000;
-	tmp1 <<= 10;
-	phiIncr <<= 10;
-	tmp2 = tmp1 / 48000;
-	phiIncr += tmp2;
-	tmp1 -= tmp2 * 48000;
-	correctionPerGOF = tmp1 / GOF_PER_SEC;
-	tmp1 -= correctionPerGOF * GOF_PER_SEC;
-	correctionPerSec = tmp1;
-
-	/*
-	 *  Fill in the SampleRateConverter control block.
-	 */
-	spin_lock_irqsave(&state->card->lock, flags);
-	cs461x_poke(state->card, BA1_PSRC,
-	  ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
-	cs461x_poke(state->card, BA1_PPI, phiIncr);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	dmabuf->rate = rate;
-	
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()- %d\n",rate) );
-	return rate;
-}
-
-/* set recording sample rate */
-static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned int phiIncr, coeffIncr, tmp1, tmp2;
-	unsigned int correctionPerGOF, correctionPerSec, initialDelay;
-	unsigned int frameGroupLength, cnt;
-	unsigned long flags;
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()+ %d\n",rate) );
-
-	/*
-	 *  We can only decimate by up to a factor of 1/9th the hardware rate.
-	 *  Correct the value if an attempt is made to stray outside that limit.
-	 */
-	if ((rate * 9) < 48000)
-		rate = 48000 / 9;
-
-	/*
-	 *  We cannot capture at at rate greater than the Input Rate (48000).
-	 *  Return an error if an attempt is made to stray outside that limit.
-	 */
-	if (rate > 48000)
-		rate = 48000;
-
-	/*
-	 *  Compute the values used to drive the actual sample rate conversion.
-	 *  The following formulas are being computed, using inline assembly
-	 *  since we need to use 64 bit arithmetic to compute the values:
-	 *
-	 *     coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
-	 *     phiIncr = floor((Fs,in * 2^26) / Fs,out)
-	 *     correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
-	 *                                GOF_PER_SEC)
-	 *     correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
-	 *                          GOF_PER_SEC * correctionPerGOF
-	 *     initialDelay = ceil((24 * Fs,in) / Fs,out)
-	 *
-	 * i.e.
-	 *
-	 *     coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
-	 *     phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
-	 *     correctionPerGOF:correctionPerSec =
-	 * 	    dividend:remainder(ulOther / GOF_PER_SEC)
-	 *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
-	 */
-	tmp1 = rate << 16;
-	coeffIncr = tmp1 / 48000;
-	tmp1 -= coeffIncr * 48000;
-	tmp1 <<= 7;
-	coeffIncr <<= 7;
-	coeffIncr += tmp1 / 48000;
-	coeffIncr ^= 0xFFFFFFFF;
-	coeffIncr++;
-	tmp1 = 48000 << 16;
-	phiIncr = tmp1 / rate;
-	tmp1 -= phiIncr * rate;
-	tmp1 <<= 10;
-	phiIncr <<= 10;
-	tmp2 = tmp1 / rate;
-	phiIncr += tmp2;
-	tmp1 -= tmp2 * rate;
-	correctionPerGOF = tmp1 / GOF_PER_SEC;
-	tmp1 -= correctionPerGOF * GOF_PER_SEC;
-	correctionPerSec = tmp1;
-	initialDelay = ((48000 * 24) + rate - 1) / rate;
-
-	/*
-	 *  Fill in the VariDecimate control block.
-	 */
-	spin_lock_irqsave(&card->lock, flags);
-	cs461x_poke(card, BA1_CSRC,
-		((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
-	cs461x_poke(card, BA1_CCI, coeffIncr);
-	cs461x_poke(card, BA1_CD,
-		(((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
-	cs461x_poke(card, BA1_CPI, phiIncr);
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	/*
-	 *  Figure out the frame group length for the write back task.  Basically,
-	 *  this is just the factors of 24000 (2^6*3*5^3) that are not present in
-	 *  the output sample rate.
-	 */
-	frameGroupLength = 1;
-	for (cnt = 2; cnt <= 64; cnt *= 2) {
-		if (((rate / cnt) * cnt) != rate)
-			frameGroupLength *= 2;
-	}
-	if (((rate / 3) * 3) != rate) {
-		frameGroupLength *= 3;
-	}
-	for (cnt = 5; cnt <= 125; cnt *= 5) {
-		if (((rate / cnt) * cnt) != rate) 
-			frameGroupLength *= 5;
-        }
-
-	/*
-	 * Fill in the WriteBack control block.
-	 */
-	spin_lock_irqsave(&card->lock, flags);
-	cs461x_poke(card, BA1_CFG1, frameGroupLength);
-	cs461x_poke(card, BA1_CFG2, (0x00800000 | frameGroupLength));
-	cs461x_poke(card, BA1_CCST, 0x0000FFFF);
-	cs461x_poke(card, BA1_CSPB, ((65536 * rate) / 24000));
-	cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF);
-	spin_unlock_irqrestore(&card->lock, flags);
-	dmabuf->rate = rate;
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) );
-	return rate;
-}
-
-/* prepare channel attributes for playback */ 
-static void cs_play_setup(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-        unsigned int tmp, Count, playFormat;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") );
-        cs461x_poke(card, BA1_PVOL, 0x80008000);
-        if (!dmabuf->SGok)
-               cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf));
-    
-        Count = 4;                                                          
-        playFormat=cs461x_peek(card, BA1_PFIE);                             
-        if ((dmabuf->fmt & CS_FMT_STEREO)) {                                
-                playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO;                 
-                Count *= 2;                                                 
-        } else
-                playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO;                  
-                                                                            
-        if ((dmabuf->fmt & CS_FMT_16BIT)) {                                 
-                playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT                    
-                           | DMA_RQ_C2_AC_SIGNED_CONVERT);                  
-                Count *= 2;                                                 
-        } else
-                playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT                     
-                           | DMA_RQ_C2_AC_SIGNED_CONVERT);                  
-                                                                            
-        cs461x_poke(card, BA1_PFIE, playFormat);                            
-                                                                            
-        tmp = cs461x_peek(card, BA1_PDTC);                                  
-        tmp &= 0xfffffe00;                                                  
-        cs461x_poke(card, BA1_PDTC, tmp | --Count);                         
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") );
-}
-
-static struct InitStruct
-{
-    u32 off;
-    u32 val;
-} InitArray[] = { {0x00000040, 0x3fc0000f},
-                  {0x0000004c, 0x04800000},
-
-                  {0x000000b3, 0x00000780},
-                  {0x000000b7, 0x00000000},
-                  {0x000000bc, 0x07800000},
-
-                  {0x000000cd, 0x00800000},
-                };
-
-/*
- * "SetCaptureSPValues()" -- Initialize record task values before each
- * 	capture startup.  
- */
-static void SetCaptureSPValues(struct cs_card *card)
-{
-	unsigned i, offset;
-	CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") );
-	for (i = 0; i < sizeof(InitArray) / sizeof(struct InitStruct); i++) {
-		offset = InitArray[i].off*4; /* 8bit to 32bit offset value */
-		cs461x_poke(card, offset, InitArray[i].val );
-	}
-	CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()-\n") );
-}
-
-/* prepare channel attributes for recording */
-static void cs_rec_setup(struct cs_state *state)
-{
-	struct cs_card *card = state->card;
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n"));
-	SetCaptureSPValues(card);
-
-	/*
-	 * set the attenuation to 0dB 
-	 */
-	cs461x_poke(card, BA1_CVOL, 0x80008000);
-
-	/*
-	 * set the physical address of the capture buffer into the SP
-	 */
-	cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf));
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") );
-}
-
-
-/* get current playback/recording dma buffer pointer (byte offset from LBA),
-   called with spinlock held! */
-   
-static inline unsigned cs_get_dma_addr(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 offset;
-	
-	if ( (!(dmabuf->enable & DAC_RUNNING)) &&
-	     (!(dmabuf->enable & ADC_RUNNING) ) )
-	{
-		CS_DBGOUT(CS_ERROR, 2, printk(
-			"cs46xx: ERROR cs_get_dma_addr(): not enabled \n") );
-		return 0;
-	}
-		
-	/*
-	 * granularity is byte boundary, good part.
-	 */
-	if (dmabuf->enable & DAC_RUNNING)
-		offset = cs461x_peek(state->card, BA1_PBA);                                  
-	else /* ADC_RUNNING must be set */
-		offset = cs461x_peek(state->card, BA1_CBA);                                  
-
-	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9, 
-		printk("cs46xx: cs_get_dma_addr() %d\n",offset) );
-	offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf;
-	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, 
-		printk("cs46xx: cs_get_dma_addr()- %d\n",offset) );
-	return offset;
-}
-
-static void resync_dma_ptrs(struct cs_state *state)
-{
-	struct dmabuf *dmabuf;
-	
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") );
-	if (state) {
-		dmabuf = &state->dmabuf;
-		dmabuf->hwptr=dmabuf->swptr = 0;
-		dmabuf->pringbuf = 0;
-	}
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") );
-}
-	
-/* Stop recording (lock held) */
-static inline void __stop_adc(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned int tmp;
-	
-	dmabuf->enable &= ~ADC_RUNNING;
-	
-	tmp = cs461x_peek(card, BA1_CCTL);
-	tmp &= 0xFFFF0000;
-	cs461x_poke(card, BA1_CCTL, tmp );
-}
-
-static void stop_adc(struct cs_state *state)
-{
-	unsigned long flags;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") );
-	spin_lock_irqsave(&state->card->lock, flags);
-	__stop_adc(state);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") );
-}
-
-static void start_adc(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned long flags;
-	unsigned int tmp;
-
-	spin_lock_irqsave(&card->lock, flags);
-	if (!(dmabuf->enable & ADC_RUNNING) && 
-	     ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) 
-	       && dmabuf->ready) && 
-	       ((card->pm.flags & CS46XX_PM_IDLE) || 
-	        (card->pm.flags & CS46XX_PM_RESUMED)) )
-	{
-		dmabuf->enable |= ADC_RUNNING;
-		cs_set_divisor(dmabuf);
-		tmp = cs461x_peek(card, BA1_CCTL);
-		tmp &= 0xFFFF0000;
-		tmp |= card->cctl;
-		CS_DBGOUT(CS_FUNCTION, 2, printk(
-			"cs46xx: start_adc() poke 0x%x \n",tmp) );
-		cs461x_poke(card, BA1_CCTL, tmp);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* stop playback (lock held) */
-static inline void __stop_dac(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned int tmp;
-
-	dmabuf->enable &= ~DAC_RUNNING;
-	
-	tmp=cs461x_peek(card, BA1_PCTL);
-	tmp&=0xFFFF;
-	cs461x_poke(card, BA1_PCTL, tmp);
-}
-
-static void stop_dac(struct cs_state *state)
-{
-	unsigned long flags;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") );
-	spin_lock_irqsave(&state->card->lock, flags);
-	__stop_dac(state);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") );
-}	
-
-static void start_dac(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned long flags;
-	int tmp;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") );
-	spin_lock_irqsave(&card->lock, flags);
-	if (!(dmabuf->enable & DAC_RUNNING) && 
-	    ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) &&
-	       ((card->pm.flags & CS46XX_PM_IDLE) || 
-	        (card->pm.flags & CS46XX_PM_RESUMED)) )
-	{
-		dmabuf->enable |= DAC_RUNNING;
-		tmp = cs461x_peek(card, BA1_PCTL);
-		tmp &= 0xFFFF;
-		tmp |= card->pctl;
-		CS_DBGOUT(CS_PARMS, 6, printk(
-		    "cs46xx: start_dac() poke card=%p tmp=0x%.08x addr=%p \n",
-		    card, (unsigned)tmp, 
-		    card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) );
-		cs461x_poke(card, BA1_PCTL, tmp);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") );
-}
-
-#define DMABUF_MINORDER 1
-
-/*
- * allocate DMA buffer, playback and recording buffers are separate.
- */
-static int alloc_dmabuf(struct cs_state *state)
-{
-
-	struct cs_card *card=state->card;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	void *rawbuf = NULL;
-	void *tmpbuff = NULL;
-	int order;
-	struct page *map, *mapend;
-	unsigned long df;
-	
-	dmabuf->ready  = dmabuf->mapped = 0;
-	dmabuf->SGok = 0;
-/*
-* check for order within limits, but do not overwrite value.
-*/
-	if ((defaultorder > 1) && (defaultorder < 12))
-		df = defaultorder;
-	else
-		df = 2;	
-
-	for (order = df; order >= DMABUF_MINORDER; order--)
-		if ((rawbuf = (void *)pci_alloc_consistent(
-			card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr)))
-			    break;
-	if (!rawbuf) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			"cs46xx: alloc_dmabuf(): unable to allocate rawbuf\n"));
-		return -ENOMEM;
-	}
-	dmabuf->buforder = order;
-	dmabuf->rawbuf = rawbuf;
-	// Now mark the pages as reserved; otherwise the 
-	// remap_pfn_range() in cs46xx_mmap doesn't work.
-	// 1. get index to last page in mem_map array for rawbuf.
-	mapend = virt_to_page(dmabuf->rawbuf + 
-		(PAGE_SIZE << dmabuf->buforder) - 1);
-
-	// 2. mark each physical page in range as 'reserved'.
-	for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
-		cs4x_mem_map_reserve(map);
-
-	CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: alloc_dmabuf(): allocated %ld (order = %d) bytes at %p\n",
-	       PAGE_SIZE << order, order, rawbuf) );
-
-/*
-*  only allocate the conversion buffer for the ADC
-*/
-	if (dmabuf->type == CS_TYPE_DAC) {
-		dmabuf->tmpbuff = NULL;
-		dmabuf->buforder_tmpbuff = 0;
-		return 0;
-	}
-/*
- * now the temp buffer for 16/8 conversions
- */
-
-	tmpbuff = (void *) pci_alloc_consistent(
-		card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr_tmpbuff);
-
-	if (!tmpbuff)
-		return -ENOMEM;
-	CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: allocated %ld (order = %d) bytes at %p\n",
-	       PAGE_SIZE << order, order, tmpbuff) );
-
-	dmabuf->tmpbuff = tmpbuff;
-	dmabuf->buforder_tmpbuff = order;
-	
-	// Now mark the pages as reserved; otherwise the 
-	// remap_pfn_range() in cs46xx_mmap doesn't work.
-	// 1. get index to last page in mem_map array for rawbuf.
-	mapend = virt_to_page(dmabuf->tmpbuff + 
-		(PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
-
-	// 2. mark each physical page in range as 'reserved'.
-	for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
-		cs4x_mem_map_reserve(map);
-	return 0;
-}
-
-/* free DMA buffer */
-static void dealloc_dmabuf(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct page *map, *mapend;
-
-	if (dmabuf->rawbuf) {
-		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend = virt_to_page(dmabuf->rawbuf + 
-				(PAGE_SIZE << dmabuf->buforder) - 1);
-		for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
-			cs4x_mem_map_unreserve(map);
-		free_dmabuf(state->card, dmabuf);
-	}
-
-	if (dmabuf->tmpbuff) {
-		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend = virt_to_page(dmabuf->tmpbuff +
-				(PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
-		for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
-			cs4x_mem_map_unreserve(map);
-		free_dmabuf2(state->card, dmabuf);
-	}
-
-	dmabuf->rawbuf = NULL;
-	dmabuf->tmpbuff = NULL;
-	dmabuf->mapped = dmabuf->ready = 0;
-	dmabuf->SGok = 0;
-}
-
-static int __prog_dmabuf(struct cs_state *state)
-{
-        struct dmabuf *dmabuf = &state->dmabuf;
-        unsigned long flags;
-        unsigned long allocated_pages, allocated_bytes;                     
-        unsigned long tmp1, tmp2, fmt=0;                                           
-        unsigned long *ptmp = (unsigned long *) dmabuf->pbuf;               
-        unsigned long SGarray[9], nSGpages=0;                               
-        int ret;
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n"));
-/*
- * check for CAPTURE and use only non-sg for initial release
- */
-	if (dmabuf->type == CS_TYPE_ADC) {
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n"));
-		/* 
-		 * add in non-sg support for capture.
-		 */
-		spin_lock_irqsave(&state->card->lock, flags);
-	/* add code to reset the rawbuf memory. TRW */
-		resync_dma_ptrs(state);
-		dmabuf->total_bytes = dmabuf->blocks = 0;
-		dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
-
-		dmabuf->SGok = 0;                                                   
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* allocate DMA buffer if not allocated yet */
-		if (!dmabuf->rawbuf || !dmabuf->tmpbuff)
-			if ((ret = alloc_dmabuf(state)))
-				return ret; 
-	/*
-	 * static image only supports 16Bit signed, stereo - hard code fmt
-	 */
-		fmt = CS_FMT_16BIT | CS_FMT_STEREO;
-
-		dmabuf->numfrag = 2;                                        
-		dmabuf->fragsize = 2048;                                    
-		dmabuf->fragsamples = 2048 >> sample_shift[fmt];    
-		dmabuf->dmasize = 4096;                                     
-		dmabuf->fragshift = 11;                                     
-
-		memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80,
-		       dmabuf->dmasize);
-        	memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80, 
-			PAGE_SIZE<<dmabuf->buforder_tmpbuff);      
-
-		/*
-		 *      Now set up the ring
-		 */
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		cs_rec_setup(state);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* set the ready flag for the dma buffer */
-		dmabuf->ready = 1;
-
-		CS_DBGOUT(CS_PARMS, 4, printk(
-			"cs46xx: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d "
-			"fragsize=%d dmasize=%d\n",
-			    dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-			    dmabuf->fragsize, dmabuf->dmasize) );
-
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n"));
-		return 0;
-	} else if (dmabuf->type == CS_TYPE_DAC) {
-	/*
-	 * Must be DAC
-	 */
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n"));
-		spin_lock_irqsave(&state->card->lock, flags);
-		resync_dma_ptrs(state);
-		dmabuf->total_bytes = dmabuf->blocks = 0;
-		dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
-
-		dmabuf->SGok = 0;                                                   
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* allocate DMA buffer if not allocated yet */
-		if (!dmabuf->rawbuf)
-			if ((ret = alloc_dmabuf(state)))
-				return ret;
-
-		allocated_pages = 1 << dmabuf->buforder;                            
-		allocated_bytes = allocated_pages*PAGE_SIZE;                        
-										    
-		if (allocated_pages < 2) {
-			CS_DBGOUT(CS_FUNCTION, 4, printk(
-			    "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n",
-				(unsigned)allocated_pages));
-			return -ENOMEM;
-		}
-										    
-		/* Use all the pages allocated, fragsize 4k. */
-		/* Use 'pbuf' for S/G page map table. */
-		dmabuf->SGok = 1;           /* Use S/G. */
-
-		nSGpages = allocated_bytes/4096;    /* S/G pages always 4k. */
-										    
-		     /* Set up S/G variables. */
-		*ptmp = virt_to_bus(dmabuf->rawbuf);                                
-		*(ptmp + 1) = 0x00000008;
-		for (tmp1 = 1; tmp1 < nSGpages; tmp1++) {
-			*(ptmp + 2 * tmp1) = virt_to_bus((dmabuf->rawbuf) + 4096 * tmp1);
-			if (tmp1 == nSGpages - 1)
-				tmp2 = 0xbfff0000;
-			else                                                        
-				tmp2 = 0x80000000 + 8 * (tmp1 + 1);
-			*(ptmp + 2 * tmp1 + 1) = tmp2;
-		}                                                                   
-		SGarray[0] = 0x82c0200d;                                            
-		SGarray[1] = 0xffff0000;                                            
-		SGarray[2] = *ptmp;                                                 
-		SGarray[3] = 0x00010600;                                            
-		SGarray[4] = *(ptmp+2);                                             
-		SGarray[5] = 0x80000010;                                            
-		SGarray[6] = *ptmp;
-		SGarray[7] = *(ptmp+2);
-		SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10;
-
-		if (dmabuf->SGok) {
-			dmabuf->numfrag = nSGpages;
-			dmabuf->fragsize = 4096;
-			dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt];
-			dmabuf->fragshift = 12;
-			dmabuf->dmasize = dmabuf->numfrag * 4096;
-		} else {
-			SGarray[0] = 0xf2c0000f;                                    
-			SGarray[1] = 0x00000200;                                    
-			SGarray[2] = 0;                                             
-			SGarray[3] = 0x00010600;                                    
-			SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0; 
-			dmabuf->numfrag = 2;                                        
-			dmabuf->fragsize = 2048;                                    
-			dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt];    
-			dmabuf->dmasize = 4096;                                     
-			dmabuf->fragshift = 11;                                     
-		}
-		for (tmp1 = 0; tmp1 < sizeof(SGarray) / 4; tmp1++)
-			cs461x_poke(state->card, BA1_PDTC+tmp1 * 4, SGarray[tmp1]);
-
-		memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
-		       dmabuf->dmasize);
-
-		/*
-		 *      Now set up the ring
-		 */
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		cs_play_setup(state);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* set the ready flag for the dma buffer */
-		dmabuf->ready = 1;
-
-		CS_DBGOUT(CS_PARMS, 4, printk(
-			"cs46xx: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d "
-			"fragsize=%d dmasize=%d\n",
-			    dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-			    dmabuf->fragsize, dmabuf->dmasize) );
-
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n"));
-		return 0;
-	} else {
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n",
-			dmabuf->type));
-	}
-	return 1;
-}
-
-static int prog_dmabuf(struct cs_state *state)
-{
-	int ret;
-	
-	mutex_lock(&state->sem);
-	ret = __prog_dmabuf(state);
-	mutex_unlock(&state->sem);
-	
-	return ret;
-}
-
-static void cs_clear_tail(struct cs_state *state)
-{
-}
-
-static int drain_dac(struct cs_state *state, int nonblock)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card=state->card;
-	unsigned long flags;
-	unsigned long tmo;
-	int count;
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()+ \n"));
-	if (dmabuf->mapped || !dmabuf->ready)
-	{
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0, not ready\n"));
-		return 0;
-	}
-
-	add_wait_queue(&dmabuf->wait, &wait);
-	for (;;) {
-		/* It seems that we have to set the current state to TASK_INTERRUPTIBLE
-		   every time to make the process really go to sleep */
-		current->state = TASK_INTERRUPTIBLE;
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		count = dmabuf->count;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (count <= 0)
-			break;
-
-		if (signal_pending(current))
-			break;
-
-		if (nonblock) {
-			remove_wait_queue(&dmabuf->wait, &wait);
-			current->state = TASK_RUNNING;
-			return -EBUSY;
-		}
-
-		tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
-		tmo >>= sample_shift[dmabuf->fmt];
-		tmo += (2048*HZ)/dmabuf->rate;
-		
-		if (!schedule_timeout(tmo ? tmo : 1) && tmo){
-			printk(KERN_ERR "cs46xx: drain_dac, dma timeout? %d\n", count);
-			break;
-		}
-	}
-	remove_wait_queue(&dmabuf->wait, &wait);
-	current->state = TASK_RUNNING;
-	if (signal_pending(current)) {
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n"));
-		/*
-		* set to silence and let that clear the fifos.
-		*/
-		cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC);
-		return -ERESTARTSYS;
-	}
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0\n"));
-	return 0;
-}
-
-
-/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */
-static void cs_update_ptr(struct cs_card *card, int wake)
-{
-	struct cs_state *state;
-	struct dmabuf *dmabuf;
-	unsigned hwptr;
-	int diff;
-
-	/* error handling and process wake up for ADC */
-	state = card->states[0];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		if (dmabuf->enable & ADC_RUNNING) {
-			/* update hardware pointer */
-			hwptr = cs_get_dma_addr(state);
-
-			diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-			CS_DBGOUT(CS_PARMS, 9, printk(
-				"cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n", 
-				hwptr,diff) );
-			dmabuf->hwptr = hwptr;
-			dmabuf->total_bytes += diff;
-			dmabuf->count += diff;
-			if (dmabuf->count > dmabuf->dmasize)
-				dmabuf->count = dmabuf->dmasize;
-
-			if (dmabuf->mapped) {
-				if (wake && dmabuf->count >= (signed)dmabuf->fragsize)
-					wake_up(&dmabuf->wait);
-			} else {
-				if (wake && dmabuf->count > 0)
-					wake_up(&dmabuf->wait);
-			}
-		}
-	}
-
-/*
- * Now the DAC
- */
-	state = card->states[1];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		/* error handling and process wake up for DAC */
-		if (dmabuf->enable & DAC_RUNNING) {
-			/* update hardware pointer */
-			hwptr = cs_get_dma_addr(state);
-
-			diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-			CS_DBGOUT(CS_PARMS, 9, printk(
-				"cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n", 
-				hwptr,diff) );
-			dmabuf->hwptr = hwptr;
-			dmabuf->total_bytes += diff;
-			if (dmabuf->mapped) {
-				dmabuf->count += diff;
-				if (wake && dmabuf->count >= (signed)dmabuf->fragsize)
-					wake_up(&dmabuf->wait);
-				/*
-				 * other drivers use fragsize, but don't see any sense
-				 * in that, since dmasize is the buffer asked for
-				 * via mmap.
-				 */
-				if (dmabuf->count > dmabuf->dmasize)
-					dmabuf->count &= dmabuf->dmasize-1;
-			} else {
-				dmabuf->count -= diff;
-				/*
-				 * backfill with silence and clear out the last 
-				 * "diff" number of bytes.
-				 */
-				if (hwptr >= diff) {
-					memset(dmabuf->rawbuf + hwptr - diff, 
-						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff);
-				} else {
-					memset(dmabuf->rawbuf, 
-						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
-						(unsigned)hwptr);
-					memset((char *)dmabuf->rawbuf + 
-							dmabuf->dmasize + hwptr - diff,
-						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, 
-						diff - hwptr); 
-				}
-
-				if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
-					CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
-					  "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n",
-					  	dmabuf->count));
-					/* 
-					* buffer underrun or buffer overrun, reset the
-					* count of bytes written back to 0.
-					*/
-					if (dmabuf->count < 0)
-						dmabuf->underrun = 1;
-					dmabuf->count = 0;
-					dmabuf->error++;
-				}
-				if (wake && dmabuf->count < (signed)dmabuf->dmasize / 2)
-					wake_up(&dmabuf->wait);
-			}
-		}
-	}
-}
-
-
-/* hold spinlock for the following! */
-static void cs_handle_midi(struct cs_card *card)
-{
-        unsigned char ch;
-        int wake;
-        unsigned temp1;
-
-        wake = 0;
-        while (!(cs461x_peekBA0(card,  BA0_MIDSR) & MIDSR_RBE)) {
-                ch = cs461x_peekBA0(card, BA0_MIDRP);
-                if (card->midi.icnt < CS_MIDIINBUF) {
-                        card->midi.ibuf[card->midi.iwr] = ch;
-                        card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF;
-                        card->midi.icnt++;
-                }
-                wake = 1;
-        }
-        if (wake)
-                wake_up(&card->midi.iwait);
-        wake = 0;
-        while (!(cs461x_peekBA0(card,  BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) {
-                temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff;
-                cs461x_pokeBA0(card, BA0_MIDWP,temp1);
-                card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF;
-                card->midi.ocnt--;
-                if (card->midi.ocnt < CS_MIDIOUTBUF-16)
-                        wake = 1;
-        }
-        if (wake)
-                wake_up(&card->midi.owait);
-}
-
-static irqreturn_t cs_interrupt(int irq, void *dev_id)
-{
-	struct cs_card *card = (struct cs_card *)dev_id;
-	/* Single channel card */
-	struct cs_state *recstate = card->channel[0].state;
-	struct cs_state *playstate = card->channel[1].state;
-	u32 status;
-
-	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n"));
-
-	spin_lock(&card->lock);
-
-	status = cs461x_peekBA0(card, BA0_HISR);
-	
-	if ((status & 0x7fffffff) == 0) {
-		cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
-		spin_unlock(&card->lock);
-		return IRQ_HANDLED;	/* Might be IRQ_NONE.. */
-	}
-	
-	/*
-	 * check for playback or capture interrupt only
-	 */
-	if (((status & HISR_VC0) && playstate && playstate->dmabuf.ready) ||
-	    (((status & HISR_VC1) && recstate && recstate->dmabuf.ready))) {
-		CS_DBGOUT(CS_INTERRUPT, 8, printk(
-			"cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status));
-		cs_update_ptr(card, CS_TRUE);
-	}
-
-        if (status & HISR_MIDI)
-                cs_handle_midi(card);
-	
- 	/* clear 'em */
-	cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
-	spin_unlock(&card->lock);
-	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n"));
-	return IRQ_HANDLED;
-}
-
-
-/**********************************************************************/
-
-static ssize_t cs_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-        struct cs_card *card = file->private_data;
-        ssize_t ret;
-        unsigned long flags;
-        unsigned ptr;
-        int cnt;
-
-        if (!access_ok(VERIFY_WRITE, buffer, count))
-                return -EFAULT;
-        ret = 0;
-        while (count > 0) {
-                spin_lock_irqsave(&card->lock, flags);
-                ptr = card->midi.ird;
-                cnt = CS_MIDIINBUF - ptr;
-                if (card->midi.icnt < cnt)
-                        cnt = card->midi.icnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                if (cnt > count)
-                        cnt = count;
-                if (cnt <= 0) {
-                        if (file->f_flags & O_NONBLOCK)
-                                return ret ? ret : -EAGAIN;
-                        interruptible_sleep_on(&card->midi.iwait);
-                        if (signal_pending(current))
-                                return ret ? ret : -ERESTARTSYS;
-                        continue;
-                }
-                if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt))
-                        return ret ? ret : -EFAULT;
-                ptr = (ptr + cnt) % CS_MIDIINBUF;
-                spin_lock_irqsave(&card->lock, flags);
-                card->midi.ird = ptr;
-                card->midi.icnt -= cnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                count -= cnt;
-                buffer += cnt;
-                ret += cnt;
-        }
-        return ret;
-}
-
-
-static ssize_t cs_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-        struct cs_card *card = file->private_data;
-        ssize_t ret;
-        unsigned long flags;
-        unsigned ptr;
-        int cnt;
-
-        if (!access_ok(VERIFY_READ, buffer, count))
-                return -EFAULT;
-        ret = 0;
-        while (count > 0) {
-                spin_lock_irqsave(&card->lock, flags);
-                ptr = card->midi.owr;
-                cnt = CS_MIDIOUTBUF - ptr;
-                if (card->midi.ocnt + cnt > CS_MIDIOUTBUF)
-                        cnt = CS_MIDIOUTBUF - card->midi.ocnt;
-                if (cnt <= 0)
-                        cs_handle_midi(card);
-                spin_unlock_irqrestore(&card->lock, flags);
-                if (cnt > count)
-                        cnt = count;
-                if (cnt <= 0) {
-                        if (file->f_flags & O_NONBLOCK)
-                                return ret ? ret : -EAGAIN;
-                        interruptible_sleep_on(&card->midi.owait);
-                        if (signal_pending(current))
-                                return ret ? ret : -ERESTARTSYS;
-                        continue;
-                }
-                if (copy_from_user(card->midi.obuf + ptr, buffer, cnt))
-                        return ret ? ret : -EFAULT;
-                ptr = (ptr + cnt) % CS_MIDIOUTBUF;
-                spin_lock_irqsave(&card->lock, flags);
-                card->midi.owr = ptr;
-                card->midi.ocnt += cnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                count -= cnt;
-                buffer += cnt;
-                ret += cnt;
-                spin_lock_irqsave(&card->lock, flags);
-                cs_handle_midi(card);
-                spin_unlock_irqrestore(&card->lock, flags);
-        }
-        return ret;
-}
-
-
-static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait)
-{
-        struct cs_card *card = file->private_data;
-        unsigned long flags;
-        unsigned int mask = 0;
-
-        if (file->f_flags & FMODE_WRITE)
-                poll_wait(file, &card->midi.owait, wait);
-        if (file->f_flags & FMODE_READ)
-                poll_wait(file, &card->midi.iwait, wait);
-        spin_lock_irqsave(&card->lock, flags);
-        if (file->f_flags & FMODE_READ) {
-                if (card->midi.icnt > 0)
-                        mask |= POLLIN | POLLRDNORM;
-        }
-        if (file->f_flags & FMODE_WRITE) {
-                if (card->midi.ocnt < CS_MIDIOUTBUF)
-                        mask |= POLLOUT | POLLWRNORM;
-        }
-        spin_unlock_irqrestore(&card->lock, flags);
-        return mask;
-}
-
-
-static int cs_midi_open(struct inode *inode, struct file *file)
-{
-        unsigned int minor = iminor(inode);
-        struct cs_card *card = NULL;
-        unsigned long flags;
-	struct list_head *entry;
-
-	list_for_each(entry, &cs46xx_devs) {
-		card = list_entry(entry, struct cs_card, list);
-		if (card->dev_midi == minor)
-			break;
-	}
-
-	if (entry == &cs46xx_devs)
-		return -ENODEV;
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
-			"cs46xx: cs46xx_midi_open(): Error - unable to find card struct\n"));
-		return -ENODEV;
-	}
-
-        file->private_data = card;
-        /* wait for device to become free */
-        mutex_lock(&card->midi.open_mutex);
-        while (card->midi.open_mode & file->f_mode) {
-                if (file->f_flags & O_NONBLOCK) {
-                        mutex_unlock(&card->midi.open_mutex);
-                        return -EBUSY;
-                }
-                mutex_unlock(&card->midi.open_mutex);
-                interruptible_sleep_on(&card->midi.open_wait);
-                if (signal_pending(current))
-                        return -ERESTARTSYS;
-                mutex_lock(&card->midi.open_mutex);
-        }
-        spin_lock_irqsave(&card->midi.lock, flags);
-        if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) {
-                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
-                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
-                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
-                cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f);            /* Enable xmit, rcv. */
-                cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);   /* Enable interrupts */
-        }
-        if (file->f_mode & FMODE_READ)
-                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
-        if (file->f_mode & FMODE_WRITE)
-                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
-        spin_unlock_irqrestore(&card->midi.lock, flags);
-        card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE));
-        mutex_unlock(&card->midi.open_mutex);
-        return 0;
-}
-
-
-static int cs_midi_release(struct inode *inode, struct file *file)
-{
-        struct cs_card *card = file->private_data;
-        DECLARE_WAITQUEUE(wait, current);
-        unsigned long flags;
-        unsigned count, tmo;
-
-        if (file->f_mode & FMODE_WRITE) {
-                current->state = TASK_INTERRUPTIBLE;
-                add_wait_queue(&card->midi.owait, &wait);
-                for (;;) {
-                        spin_lock_irqsave(&card->midi.lock, flags);
-                        count = card->midi.ocnt;
-                        spin_unlock_irqrestore(&card->midi.lock, flags);
-                        if (count <= 0)
-                                break;
-                        if (signal_pending(current))
-                                break;
-                        if (file->f_flags & O_NONBLOCK)
-                        	break;
-                        tmo = (count * HZ) / 3100;
-                        if (!schedule_timeout(tmo ? : 1) && tmo)
-                                printk(KERN_DEBUG "cs46xx: midi timed out??\n");
-                }
-                remove_wait_queue(&card->midi.owait, &wait);
-                current->state = TASK_RUNNING;
-        }
-        mutex_lock(&card->midi.open_mutex);
-        card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE)));
-        mutex_unlock(&card->midi.open_mutex);
-        wake_up(&card->midi.open_wait);
-        return 0;
-}
-
-/*
- *   Midi file operations struct.
- */
-static /*const*/ struct file_operations cs_midi_fops = {
-	CS_OWNER	CS_THIS_MODULE
-	.llseek		= no_llseek,
-	.read		= cs_midi_read,
-	.write		= cs_midi_write,
-	.poll		= cs_midi_poll,
-	.open		= cs_midi_open,
-	.release	= cs_midi_release,
-};
-
-/*
- *
- * CopySamples copies 16-bit stereo signed samples from the source to the
- * destination, possibly converting down to unsigned 8-bit and/or mono.
- * count specifies the number of output bytes to write.
- *
- *  Arguments:
- *
- *  dst             - Pointer to a destination buffer.
- *  src             - Pointer to a source buffer
- *  count           - The number of bytes to copy into the destination buffer.
- *  fmt             - CS_FMT_16BIT and/or CS_FMT_STEREO bits
- *  dmabuf          - pointer to the dma buffer structure
- *
- * NOTES: only call this routine if the output desired is not 16 Signed Stereo
- * 	
- *
- */
-static void CopySamples(char *dst, char *src, int count, unsigned fmt, 
-		struct dmabuf *dmabuf)
-{
-    s32 s32AudioSample;
-    s16 *psSrc = (s16 *)src;
-    s16 *psDst = (s16 *)dst;
-    u8 *pucDst = (u8 *)dst;
-
-    CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: CopySamples()+ ") );
-    CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
-	" dst=%p src=%p count=%d fmt=0x%x\n",
-	dst,src,count,fmt) );
-
-    /*
-     * See if the data should be output as 8-bit unsigned stereo.
-     */
-    if ((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
-        /*
-         * Convert each 16-bit signed stereo sample to 8-bit unsigned 
-	 * stereo using rounding.
-         */
-        psSrc = (s16 *)src;
-	count = count / 2;
-        while (count--)
-            *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8);
-    }
-    /*
-     * See if the data should be output at 8-bit unsigned mono.
-     */
-    else if (!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
-        /*
-         * Convert each 16-bit signed stereo sample to 8-bit unsigned 
-	 * mono using averaging and rounding.
-         */
-        psSrc = (s16 *)src;
-	count = count / 2;
-        while (count--) {
-	    s32AudioSample = ((*psSrc) + (*(psSrc + 1))) / 2 + (s32)0x80;
-	    if (s32AudioSample > 0x7fff)
-	    	s32AudioSample = 0x7fff;
-            *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8);
-	    psSrc += 2;
-        }
-    }
-    /*
-     * See if the data should be output at 16-bit signed mono.
-     */
-    else if (!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT)) {
-        /*
-         * Convert each 16-bit signed stereo sample to 16-bit signed 
-	 * mono using averaging.
-         */
-        psSrc = (s16 *)src;
-	count = count / 2;
-        while (count--) {
-            *(psDst++) = (s16)((*psSrc) + (*(psSrc + 1))) / 2;
-	    psSrc += 2;
-        }
-    }
-}
-
-/*
- * cs_copy_to_user()
- * replacement for the standard copy_to_user, to allow for a conversion from
- * 16 bit to 8 bit and from stereo to mono, if the record conversion is active.  
- * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo, 
- * so we convert from any of the other format combinations.
- */
-static unsigned cs_copy_to_user(
-	struct cs_state *s, 
-	void __user *dest, 
-	void *hwsrc, 
-	unsigned cnt, 
-	unsigned *copied)
-{
-	struct dmabuf *dmabuf = &s->dmabuf;
-	void *src = hwsrc;  /* default to the standard destination buffer addr */
-
-	CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO 
-		"cs_copy_to_user()+ fmt=0x%x cnt=%d dest=%p\n",
-		dmabuf->fmt,(unsigned)cnt,dest) );
-
-	if (cnt > dmabuf->dmasize)
-		cnt = dmabuf->dmasize;
-	if (!cnt) {
-		*copied = 0;
-		return 0;
-	}
-	if (dmabuf->divisor != 1) {
-		if (!dmabuf->tmpbuff) {
-			*copied = cnt / dmabuf->divisor;
-			return 0;
-		}
-
-		CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt, 
-			dmabuf->fmt, dmabuf);
-		src = dmabuf->tmpbuff;
-		cnt = cnt/dmabuf->divisor;
-	}
-        if (copy_to_user(dest, src, cnt)) {
-		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR 
-			"cs46xx: cs_copy_to_user()- fault dest=%p src=%p cnt=%d\n",
-				dest,src,cnt));
-		*copied = 0;
-		return -EFAULT;
-	}
-	*copied = cnt;
-	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO 
-		"cs46xx: cs_copy_to_user()- copied bytes is %d \n",cnt));
-	return 0;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to
-   the user's buffer.  it is filled by the dma machine and drained by this loop. */
-static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf;
-	ssize_t ret = 0;
-	unsigned long flags;
-	unsigned swptr;
-	int cnt;
-	unsigned copied = 0;
-
-	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()+ %zd\n",count) );
-	state = card->states[0];
-	if (!state)
-		return -ENODEV;
-	dmabuf = &state->dmabuf;
-
-	if (dmabuf->mapped)
-		return -ENXIO;
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-	
-	mutex_lock(&state->sem);
-	if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
-		goto out2;
-
-	add_wait_queue(&state->dmabuf.wait, &wait);
-	while (count > 0) {
-		while (!(card->pm.flags & CS46XX_PM_IDLE)) {
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
-			}
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		swptr = dmabuf->swptr;
-		cnt = dmabuf->dmasize - swptr;
-		if (dmabuf->count < cnt)
-			cnt = dmabuf->count;
-		if (cnt <= 0)
-			__set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (cnt > (count * dmabuf->divisor))
-			cnt = count * dmabuf->divisor;
-		if (cnt <= 0) {
-			/* buffer is empty, start the dma machine and wait for data to be
-			   recorded */
-			start_adc(state);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret)
-					ret = -EAGAIN;
-				goto out;
- 			}
-			mutex_unlock(&state->sem);
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
-			}
-			mutex_lock(&state->sem);
-			if (dmabuf->mapped) {
-				if (!ret)
-					ret = -ENXIO;
-				goto out;
-			}
- 			continue;
-		}
-
-		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO 
-			"_read() copy_to cnt=%d count=%zd ", cnt,count) );
-		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO 
-			" .dmasize=%d .count=%d buffer=%p ret=%zd\n",
-			dmabuf->dmasize,dmabuf->count,buffer,ret));
-
-                if (cs_copy_to_user(state, buffer, 
-			(char *)dmabuf->rawbuf + swptr, cnt, &copied)) {
-			if (!ret)
-				ret = -EFAULT;
-			goto out;
-		}
-                swptr = (swptr + cnt) % dmabuf->dmasize;
-                spin_lock_irqsave(&card->lock, flags);
-                dmabuf->swptr = swptr;
-                dmabuf->count -= cnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                count -= copied;
-                buffer += copied;
-                ret += copied;
-                start_adc(state);
-	}
-out:
-	remove_wait_queue(&state->dmabuf.wait, &wait);
-out2:
-	mutex_unlock(&state->sem);
-	set_current_state(TASK_RUNNING);
-	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()- %zd\n",ret) );
-	return ret;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
-   the soundcard.  it is drained by the dma machine and filled by this loop. */
-static ssize_t cs_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned swptr;
-	int cnt;
-
-	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
-		printk("cs46xx: cs_write called, count = %zd\n", count) );
-	state = card->states[1];
-	if (!state)
-		return -ENODEV;
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-	dmabuf = &state->dmabuf;
-
-	mutex_lock(&state->sem);
-	if (dmabuf->mapped) {
-		ret = -ENXIO;
-		goto out;
-	}
-
-	if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
-		goto out;
-	add_wait_queue(&state->dmabuf.wait, &wait);
-	ret = 0;
-/*
-* Start the loop to read from the user's buffer and write to the dma buffer.
-* check for PM events and underrun/overrun in the loop.
-*/
-	while (count > 0) {
-		while (!(card->pm.flags & CS46XX_PM_IDLE)) {
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
-			}
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		if (dmabuf->count < 0) {
-			/* buffer underrun, we are recovering from sleep_on_timeout,
-			   resync hwptr and swptr */
-			dmabuf->count = 0;
-			dmabuf->swptr = dmabuf->hwptr;
-		}
-		if (dmabuf->underrun) {
-			dmabuf->underrun = 0;
-			dmabuf->hwptr = cs_get_dma_addr(state);
-			dmabuf->swptr = dmabuf->hwptr;
-		}
-
-		swptr = dmabuf->swptr;
-		cnt = dmabuf->dmasize - swptr;
-		if (dmabuf->count + cnt > dmabuf->dmasize)
-			cnt = dmabuf->dmasize - dmabuf->count;
-		if (cnt <= 0)
-			__set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			/* buffer is full, start the dma machine and wait for data to be
-			   played */
-			start_dac(state);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret)
-					ret = -EAGAIN;
-				goto out;
- 			}
-			mutex_unlock(&state->sem);
-			schedule();
- 			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
- 			}
-			mutex_lock(&state->sem);
-			if (dmabuf->mapped) {
-				if (!ret)
-					ret = -ENXIO;
-				goto out;
-			}
- 			continue;
- 		}
-		if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
-			if (!ret)
-				ret = -EFAULT;
-			goto out;
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		swptr = (swptr + cnt) % dmabuf->dmasize;
-		dmabuf->swptr = swptr;
-		dmabuf->count += cnt;
-		if (dmabuf->count > dmabuf->dmasize) {
-			CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk(
-			    "cs46xx: cs_write() d->count > dmasize - resetting\n"));
-			dmabuf->count = dmabuf->dmasize;
-		}
-		dmabuf->endcleared = 0;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-		start_dac(state);
-	}
-out:
-	mutex_unlock(&state->sem);
-	remove_wait_queue(&state->dmabuf.wait, &wait);
-	set_current_state(TASK_RUNNING);
-
-	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, 
-		printk("cs46xx: cs_write()- ret=%zd\n", ret));
-	return ret;
-}
-
-static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct cs_card *card = file->private_data;
-	struct dmabuf *dmabuf;
-	struct cs_state *state;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n"));
-	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) {
-		return -EINVAL;
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			poll_wait(file, &dmabuf->wait, wait);
-		}
-	}
-	if (file->f_mode & FMODE_READ) {
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			poll_wait(file, &dmabuf->wait, wait);
-		}
-	}
-
-	spin_lock_irqsave(&card->lock, flags);
-	cs_update_ptr(card, CS_FALSE);
-	if (file->f_mode & FMODE_READ) {
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			if (dmabuf->count >= (signed)dmabuf->fragsize)
-				mask |= POLLIN | POLLRDNORM;
-		}
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			if (dmabuf->mapped) {
-				if (dmabuf->count >= (signed)dmabuf->fragsize)
-				    mask |= POLLOUT | POLLWRNORM;
-			} else {
-				if ((signed)dmabuf->dmasize >= dmabuf->count 
-					+ (signed)dmabuf->fragsize)
-				    mask |= POLLOUT | POLLWRNORM;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()- (0x%x) \n",
-		mask));
-	return mask;
-}
-
-/*
- *	We let users mmap the ring buffer. Its not the real DMA buffer but
- *	that side of the code is hidden in the IRQ handling. We do a software
- *	emulation of DMA from a 64K or so buffer into a 2K FIFO. 
- *	(the hardware probably deserves a moan here but Crystal send me nice
- *	toys ;)).
- */
- 
-static int cs_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	struct dmabuf *dmabuf;
-	int ret = 0;
-	unsigned long size;
-
-	CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=%p %s %s\n", 
-		file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "",
-		vma->vm_flags & VM_READ ? "VM_READ" : "") );
-
-	if (vma->vm_flags & VM_WRITE) {
-		state = card->states[1];
-		if (state) {
-			CS_DBGOUT(CS_OPEN, 2, printk(
-			  "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") );
-			if ((ret = prog_dmabuf(state)) != 0)
-				return ret;
-		}
-	} else if (vma->vm_flags & VM_READ) {
-		state = card->states[0];
-		if (state) {
-			CS_DBGOUT(CS_OPEN, 2, printk(
-			  "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") );
-			if ((ret = prog_dmabuf(state)) != 0)
-				return ret;
-		}
-	} else {
-		CS_DBGOUT(CS_ERROR, 2, printk(
-		  "cs46xx: cs_mmap() return -EINVAL\n") );
-		return -EINVAL;
-	}
-
-/*
- * For now ONLY support playback, but seems like the only way to use
- * mmap() is to open an FD with RDWR, just read or just write access
- * does not function, get an error back from the kernel.
- * Also, QuakeIII opens with RDWR!  So, there must be something
- * to needing read/write access mapping.  So, allow read/write but 
- * use the DAC only.
- */
-	state = card->states[1];  
-	if (!state) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	mutex_lock(&state->sem);
-	dmabuf = &state->dmabuf;
-	if (cs4x_pgoff(vma) != 0) {
-		ret = -EINVAL;
-		goto out;
-	}
-	size = vma->vm_end - vma->vm_start;
-
-	CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) );
-
-	if (size > (PAGE_SIZE << dmabuf->buforder)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	if (remap_pfn_range(vma, vma->vm_start,
-			     virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
-			     size, vma->vm_page_prot)) {
-		ret = -EAGAIN;
-		goto out;
-	}
-	dmabuf->mapped = 1;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") );
-out:
-	mutex_unlock(&state->sem);
-	return ret;	
-}
-
-static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	struct dmabuf *dmabuf = NULL;
-	unsigned long flags;
-	audio_buf_info abinfo;
-	count_info cinfo;
-	int val, valsave, ret;
-	int mapped = 0;
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-
-	state = card->states[0];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped;
-	}
-	state = card->states[1];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped;
-	}
-		
-#if CSDEBUG
-	printioctl(cmd);
-#endif
-
-	switch (cmd) {
-	case OSS_GETVERSION:
-		return put_user(SOUND_VERSION, p);
-	case SNDCTL_DSP_RESET:
-		/* FIXME: spin_lock ? */
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_dac(state);
-				synchronize_irq(card->irq);
-				dmabuf->ready = 0;
-				resync_dma_ptrs(state);
-				dmabuf->swptr = dmabuf->hwptr = 0;
-				dmabuf->count = dmabuf->total_bytes = 0;
-				dmabuf->blocks = 0;
-				dmabuf->SGok = 0;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_adc(state);
-				synchronize_irq(card->irq);
-				resync_dma_ptrs(state);
-				dmabuf->ready = 0;
-				dmabuf->swptr = dmabuf->hwptr = 0;
-				dmabuf->count = dmabuf->total_bytes = 0;
-				dmabuf->blocks = 0;
-				dmabuf->SGok = 0;
-			}
-		}
-		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") );
-		return 0;
-	case SNDCTL_DSP_SYNC:
-		if (file->f_mode & FMODE_WRITE)
-			return drain_dac(state, file->f_flags & O_NONBLOCK);
-		return 0;
-	case SNDCTL_DSP_SPEED: /* set sample rate */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val >= 0) {
-			if (file->f_mode & FMODE_READ) {
-				state = card->states[0];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_adc(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					cs_set_adc_rate(state, val);
-					cs_set_divisor(dmabuf);
-				}
-			}
-			if (file->f_mode & FMODE_WRITE) {
-				state = card->states[1];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_dac(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					cs_set_dac_rate(state, val);
-					cs_set_divisor(dmabuf);
-				}
-			}
-			CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-			    "cs46xx: cs_ioctl() DSP_SPEED %s %s %d\n",
-				file->f_mode & FMODE_WRITE ? "DAC" : "",
-				file->f_mode & FMODE_READ ? "ADC" : "",
-				dmabuf->rate ) );
-			return put_user(dmabuf->rate, p);
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_dac(state);
-				dmabuf->ready = 0;
-				dmabuf->SGok = 0;
-				if (val)
-					dmabuf->fmt |= CS_FMT_STEREO;
-				else
-					dmabuf->fmt &= ~CS_FMT_STEREO;
-				cs_set_divisor(dmabuf);
-				CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-				    "cs46xx: DSP_STEREO() DAC %s\n",
-				    (dmabuf->fmt & CS_FMT_STEREO) ?
-					"STEREO":"MONO") );
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_adc(state);
-				dmabuf->ready = 0;
-				dmabuf->SGok = 0;
-				if (val)
-					dmabuf->fmt |= CS_FMT_STEREO;
-				else
-					dmabuf->fmt &= ~CS_FMT_STEREO;
-				cs_set_divisor(dmabuf);
-				CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-				    "cs46xx: DSP_STEREO() ADC %s\n",
-				    (dmabuf->fmt & CS_FMT_STEREO) ?
-					"STEREO":"MONO") );
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_GETBLKSIZE:
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if ((val = prog_dmabuf(state)))
-					return val;
-				return put_user(dmabuf->fragsize, p);
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if ((val = prog_dmabuf(state)))
-					return val;
-				return put_user(dmabuf->fragsize/dmabuf->divisor, 
-						p);
-			}
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
-		return put_user(AFMT_S16_LE | AFMT_U8, p);
-	case SNDCTL_DSP_SETFMT: /* Select sample format */
-		if (get_user(val, p))
-			return -EFAULT;
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-		    "cs46xx: cs_ioctl() DSP_SETFMT %s %s %s %s\n",
-			file->f_mode & FMODE_WRITE ? "DAC" : "",
-			file->f_mode & FMODE_READ ? "ADC" : "",
-			val == AFMT_S16_LE ? "16Bit Signed" : "",
-			val == AFMT_U8 ? "8Bit Unsigned" : "") );
-		valsave = val;
-		if (val != AFMT_QUERY) {
-			if (val==AFMT_S16_LE || val==AFMT_U8) {
-				if (file->f_mode & FMODE_WRITE) {
-					state = card->states[1];
-					if (state) {
-						dmabuf = &state->dmabuf;
-						stop_dac(state);
-						dmabuf->ready = 0;
-						dmabuf->SGok = 0;
-						if (val == AFMT_S16_LE)
-							dmabuf->fmt |= CS_FMT_16BIT;
-						else
-							dmabuf->fmt &= ~CS_FMT_16BIT;
-						cs_set_divisor(dmabuf);
-						if ((ret = prog_dmabuf(state)))
-							return ret;
-					}
-				}
-				if (file->f_mode & FMODE_READ) {
-					val = valsave;
-					state = card->states[0];
-					if (state) {
-						dmabuf = &state->dmabuf;
-						stop_adc(state);
-						dmabuf->ready = 0;
-						dmabuf->SGok = 0;
-						if (val == AFMT_S16_LE)
-							dmabuf->fmt |= CS_FMT_16BIT;
-						else
-							dmabuf->fmt &= ~CS_FMT_16BIT;
-						cs_set_divisor(dmabuf);
-						if ((ret = prog_dmabuf(state)))
-							return ret;
-					}
-				}
-			} else {
-				CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk(
-				    "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n",
-					valsave) );
-			}
-		} else {
-			if (file->f_mode & FMODE_WRITE) {
-				state = card->states[1];
-				if (state)
-					dmabuf = &state->dmabuf;
-			} else if (file->f_mode & FMODE_READ) {
-				state = card->states[0];
-				if (state)
-					dmabuf = &state->dmabuf;
-			}
-		}
-		if (dmabuf) {
-			if (dmabuf->fmt & CS_FMT_16BIT)
-				return put_user(AFMT_S16_LE, p);
-			else
-				return put_user(AFMT_U8, p);
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_CHANNELS:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val != 0) {
-			if (file->f_mode & FMODE_WRITE) {
-				state = card->states[1];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_dac(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					if (val > 1)
-						dmabuf->fmt |= CS_FMT_STEREO;
-					else
-						dmabuf->fmt &= ~CS_FMT_STEREO;
-					cs_set_divisor(dmabuf);
-					if (prog_dmabuf(state))
-						return 0;
-				}
-			}
-			if (file->f_mode & FMODE_READ) {
-				state = card->states[0];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_adc(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					if (val > 1)
-						dmabuf->fmt |= CS_FMT_STEREO;
-					else
-						dmabuf->fmt &= ~CS_FMT_STEREO;
-					cs_set_divisor(dmabuf);
-					if (prog_dmabuf(state))
-						return 0;
-				}
-			}
-		}
-		return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
-				p);
-	case SNDCTL_DSP_POST:
-		/*
-		 * There will be a longer than normal pause in the data.
-		 * so... do nothing, because there is nothing that we can do.
-		 */
-		return 0;
-	case SNDCTL_DSP_SUBDIVIDE:
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (dmabuf->subdivision)
-					return -EINVAL;
-				if (get_user(val, p))
-					return -EFAULT;
-				if (val != 1 && val != 2)
-					return -EINVAL;
-				dmabuf->subdivision = val;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (dmabuf->subdivision)
-					return -EINVAL;
-				if (get_user(val, p))
-					return -EFAULT;
-				if (val != 1 && val != 2)
-					return -EINVAL;
-				dmabuf->subdivision = val;
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				dmabuf->ossfragshift = val & 0xffff;
-				dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				dmabuf->ossfragshift = val & 0xffff;
-				dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_GETOSPACE:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			abinfo.fragsize = dmabuf->fragsize;
-			abinfo.fragstotal = dmabuf->numfrag;
-		/*
-		 * for mmap we always have total space available
-		 */
-			if (dmabuf->mapped)
-				abinfo.bytes = dmabuf->dmasize;
-			else
-				abinfo.bytes = dmabuf->dmasize - dmabuf->count;
-
-			abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_GETISPACE:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			abinfo.fragsize = dmabuf->fragsize/dmabuf->divisor;
-			abinfo.bytes = dmabuf->count/dmabuf->divisor;
-			abinfo.fragstotal = dmabuf->numfrag;
-			abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-	case SNDCTL_DSP_GETCAPS:
-		return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
-			    p);
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") );
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (dmabuf->enable & DAC_RUNNING)
-					val |= PCM_ENABLE_INPUT;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			if (state) {
-				state = card->states[0];
-				dmabuf = &state->dmabuf;
-				if (dmabuf->enable & ADC_RUNNING)
-					val |= PCM_ENABLE_OUTPUT;
-			}
-		}
-		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) );
-		return put_user(val, p);
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (val & PCM_ENABLE_INPUT) {
-					if (!dmabuf->ready && (ret = prog_dmabuf(state)))
-						return ret;
-					start_adc(state);
-				} else
-					stop_adc(state);
-			}
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (val & PCM_ENABLE_OUTPUT) {
-					if (!dmabuf->ready && (ret = prog_dmabuf(state)))
-						return ret;
-					start_dac(state);
-				} else
-					stop_dac(state);
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_GETIPTR:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			cinfo.bytes = dmabuf->total_bytes/dmabuf->divisor;
-			cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift;
-			cinfo.ptr = dmabuf->hwptr/dmabuf->divisor;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-			return 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			cinfo.bytes = dmabuf->total_bytes;
-			if (dmabuf->mapped) {
-				cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift) 
-							- dmabuf->blocks;
-				CS_DBGOUT(CS_PARMS, 8, 
-					printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n", 
-					cinfo.bytes,cinfo.blocks,dmabuf->blocks) );
-				dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift;
-			} else {
-				cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
-			}
-			cinfo.ptr = dmabuf->hwptr;
-
-			CS_DBGOUT(CS_PARMS, 4, printk(
-			    "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n",
-				cinfo.bytes,cinfo.blocks,cinfo.ptr) );
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-			return 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_SETDUPLEX:
-		return 0;
-	case SNDCTL_DSP_GETODELAY:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			val = dmabuf->count;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-		} else
-			val = 0;
-		return put_user(val, p);
-	case SOUND_PCM_READ_RATE:
-		if (file->f_mode & FMODE_READ)
-			state = card->states[0];
-		else 
-			state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			return put_user(dmabuf->rate, p);
-		}
-		return put_user(0, p);
-	case SOUND_PCM_READ_CHANNELS:
-		if (file->f_mode & FMODE_READ)
-			state = card->states[0];
-		else 
-			state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
-				p);
-		}
-		return put_user(0, p);
-	case SOUND_PCM_READ_BITS:
-		if (file->f_mode & FMODE_READ)
-			state = card->states[0];
-		else 
-			state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			return put_user((dmabuf->fmt & CS_FMT_16BIT) ? 
-			  	AFMT_S16_LE : AFMT_U8, p);
-
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_MAPINBUF:
-	case SNDCTL_DSP_MAPOUTBUF:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_WRITE_FILTER:
-	case SOUND_PCM_READ_FILTER:
-		return -EINVAL;
-	}
-	return -EINVAL;
-}
-
-
-/*
- *	AMP control - null AMP
- */
- 
-static void amp_none(struct cs_card *card, int change)
-{	
-}
-
-/*
- *	Crystal EAPD mode
- */
- 
-static void amp_voyetra(struct cs_card *card, int change)
-{
-	/* Manage the EAPD bit on the Crystal 4297 
-	   and the Analog AD1885 */
-	   
-	int old = card->amplifier;
-	
-	card->amplifier+=change;
-	if (card->amplifier && !old) {
-		/* Turn the EAPD amp on */
-		cs_ac97_set(card->ac97_codec[0],  AC97_POWER_CONTROL, 
-			cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) |
-				0x8000);
-	} else if(old && !card->amplifier) {
-		/* Turn the EAPD amp off */
-		cs_ac97_set(card->ac97_codec[0],  AC97_POWER_CONTROL, 
-			cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
-				~0x8000);
-	}
-}
-
-		       
-/*
- *	Game Theatre XP card - EGPIO[2] is used to enable the external amp.
- */
- 
-static void amp_hercules(struct cs_card *card, int change)
-{
-	int old = card->amplifier;
-	if (!card) {
-		CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO 
-			"cs46xx: amp_hercules() called before initialized.\n"));
-		return;
-	}
-	card->amplifier+=change;
-	if ((card->amplifier && !old) && !(hercules_egpio_disable)) {
-		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
-			"cs46xx: amp_hercules() external amp enabled\n"));
-		cs461x_pokeBA0(card, BA0_EGPIODR, 
-			EGPIODR_GPOE2);     /* enable EGPIO2 output */
-		cs461x_pokeBA0(card, BA0_EGPIOPTR, 
-			EGPIOPTR_GPPT2);   /* open-drain on output */
-	} else if (old && !card->amplifier) {
-		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
-			"cs46xx: amp_hercules() external amp disabled\n"));
-		cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */
-		cs461x_pokeBA0(card, BA0_EGPIOPTR, 0); /* disable */
-	}
-}
-
-/*
- *	Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
- *	whenever we need to beat on the chip.
- *
- *	The original idea and code for this hack comes from David Kaiser at
- *	Linuxcare. Perhaps one day Crystal will document their chips well
- *	enough to make them useful.
- */
- 
-static void clkrun_hack(struct cs_card *card, int change)
-{
-	struct pci_dev *acpi_dev;
-	u16 control;
-	u8 pp;
-	unsigned long port;
-	int old = card->active;
-	
-	card->active+=change;
-	
-	acpi_dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
-	if (acpi_dev == NULL)
-		return;		/* Not a thinkpad thats for sure */
-
-	/* Find the control port */		
-	pci_read_config_byte(acpi_dev, 0x41, &pp);
-	port = pp << 8;
-
-	/* Read ACPI port */	
-	control = inw(port + 0x10);
-
-	/* Flip CLKRUN off while running */
-	if (!card->active && old) {
-		CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
-			"cs46xx: clkrun() enable clkrun - change=%d active=%d\n",
-				change,card->active));
-		outw(control|0x2000, port+0x10);
-	} else {
-	/*
-	* sometimes on a resume the bit is set, so always reset the bit.
-	*/
-		CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
-			"cs46xx: clkrun() disable clkrun - change=%d active=%d\n",
-				change,card->active));
-		outw(control&~0x2000, port+0x10);
-	}
-	pci_dev_put(acpi_dev);
-}
-
-	
-static int cs_open(struct inode *inode, struct file *file)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state = NULL;
-	struct dmabuf *dmabuf = NULL;
-	struct list_head *entry;
-        unsigned int minor = iminor(inode);
-	int ret = 0;
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=%p %s %s\n",
-		file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
-		file->f_mode & FMODE_READ ? "FMODE_READ" : "") );
-
-	list_for_each(entry, &cs46xx_devs) {
-		card = list_entry(entry, struct cs_card, list);
-
-		if (!((card->dev_audio ^ minor) & ~0xf))
-			break;
-	}
-	if (entry == &cs46xx_devs)
-		return -ENODEV;
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
-			"cs46xx: cs_open(): Error - unable to find audio card struct\n"));
-		return -ENODEV;
-	}
-
-	/*
-	 * hardcode state[0] for capture, [1] for playback
-	 */
-	if (file->f_mode & FMODE_READ) {
-		CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") );
-		if (card->states[0] == NULL) {
-			state = card->states[0] =
-				kzalloc(sizeof(struct cs_state), GFP_KERNEL);
-			if (state == NULL)
-				return -ENOMEM;
-			mutex_init(&state->sem);
-			dmabuf = &state->dmabuf;
-			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-			if (dmabuf->pbuf == NULL) {
-				kfree(state);
-				card->states[0] = NULL;
-				return -ENOMEM;
-			}
-		} else {
-			state = card->states[0];
-			if (state->open_mode & FMODE_READ)
-				return -EBUSY;
-		}
-		dmabuf->channel = card->alloc_rec_pcm_channel(card);
-			
-		if (dmabuf->channel == NULL) {
-			kfree(card->states[0]);
-			card->states[0] = NULL;
-			return -ENODEV;
-		}
-
-		/* Now turn on external AMP if needed */
-		state->card = card;
-		state->card->active_ctrl(state->card, 1);
-		state->card->amplifier_ctrl(state->card, 1);
-		
-		if ((tmp = cs46xx_powerup(card, CS_POWER_ADC))) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs46xx_powerup of ADC failed (0x%x)\n", tmp));
-			return -EIO;
-		}
-
-		dmabuf->channel->state = state;
-		/* initialize the virtual channel */
-		state->virt = 0;
-		state->magic = CS_STATE_MAGIC;
-		init_waitqueue_head(&dmabuf->wait);
-		mutex_init(&state->open_mutex);
-		file->private_data = card;
-
-		mutex_lock(&state->open_mutex);
-
-		/* set default sample format. According to OSS Programmer's Guide  /dev/dsp
-		   should be default to unsigned 8-bits, mono, with sample rate 8kHz and
-		   /dev/dspW will accept 16-bits sample */
-
-		/* Default input is 8bit mono */
-		dmabuf->fmt &= ~CS_FMT_MASK;
-		dmabuf->type = CS_TYPE_ADC;
-		dmabuf->ossfragshift = 0;
-		dmabuf->ossmaxfrags  = 0;
-		dmabuf->subdivision  = 0;
-		cs_set_adc_rate(state, 8000);
-		cs_set_divisor(dmabuf);
-
-		state->open_mode |= FMODE_READ;
-		mutex_unlock(&state->open_mutex);
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") );
-		if (card->states[1] == NULL) {
-			state = card->states[1] =
-				kzalloc(sizeof(struct cs_state), GFP_KERNEL);
-			if (state == NULL)
-				return -ENOMEM;
-			mutex_init(&state->sem);
-			dmabuf = &state->dmabuf;
-			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-			if (dmabuf->pbuf == NULL) {
-				kfree(state);
-				card->states[1] = NULL;
-				return -ENOMEM;
-			}
-		} else {
-			state = card->states[1];
-			if (state->open_mode & FMODE_WRITE)
-				return -EBUSY;
-		}
-		dmabuf->channel = card->alloc_pcm_channel(card);
-			
-		if (dmabuf->channel == NULL) {
-			kfree(card->states[1]);
-			card->states[1] = NULL;
-			return -ENODEV;
-		}
-
-		/* Now turn on external AMP if needed */
-		state->card = card;
-		state->card->active_ctrl(state->card, 1);
-		state->card->amplifier_ctrl(state->card, 1);
-
-		if ((tmp = cs46xx_powerup(card, CS_POWER_DAC))) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs46xx_powerup of DAC failed (0x%x)\n", tmp));
-			return -EIO;
-		}
-		
-		dmabuf->channel->state = state;
-		/* initialize the virtual channel */
-		state->virt = 1;
-		state->magic = CS_STATE_MAGIC;
-		init_waitqueue_head(&dmabuf->wait);
-		mutex_init(&state->open_mutex);
-		file->private_data = card;
-
-		mutex_lock(&state->open_mutex);
-
-		/* set default sample format. According to OSS Programmer's Guide  /dev/dsp
-		   should be default to unsigned 8-bits, mono, with sample rate 8kHz and
-		   /dev/dspW will accept 16-bits sample */
-
-		/* Default output is 8bit mono. */
-		dmabuf->fmt &= ~CS_FMT_MASK;
-		dmabuf->type = CS_TYPE_DAC;
-		dmabuf->ossfragshift = 0;
-		dmabuf->ossmaxfrags  = 0;
-		dmabuf->subdivision  = 0;
-		cs_set_dac_rate(state, 8000);
-		cs_set_divisor(dmabuf);
-
-		state->open_mode |= FMODE_WRITE;
-		mutex_unlock(&state->open_mutex);
-		if ((ret = prog_dmabuf(state)))
-			return ret;
-	}
-	CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n"));
-	return nonseekable_open(inode, file);
-}
-
-static int cs_release(struct inode *inode, struct file *file)
-{
-	struct cs_card *card = file->private_data;
-	struct dmabuf *dmabuf;
-	struct cs_state *state;
-	unsigned int tmp;
-	CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=%p %s %s\n",
-		file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
-		file->f_mode & FMODE_READ ? "FMODE_READ" : ""));
-
-	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ)))
-		return -EINVAL;
-	state = card->states[1];
-	if (state) {
-		if ((state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE)) {
-			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n"));
-			dmabuf = &state->dmabuf;
-			cs_clear_tail(state);
-			drain_dac(state, file->f_flags & O_NONBLOCK);
-			/* stop DMA state machine and free DMA buffers/channels */
-			mutex_lock(&state->open_mutex);
-			stop_dac(state);
-			dealloc_dmabuf(state);
-			state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-			free_page((unsigned long)state->dmabuf.pbuf);
-
-			/* we're covered by the open_mutex */
-			mutex_unlock(&state->open_mutex);
-			state->card->states[state->virt] = NULL;
-			state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-
-			if ((tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE))) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
-					"cs46xx: cs_release_mixdev() powerdown DAC failure (0x%x)\n",tmp) );
-			}
-
-			/* Now turn off external AMP if needed */
-			state->card->amplifier_ctrl(state->card, -1);
-			state->card->active_ctrl(state->card, -1);
-			kfree(state);
-		}
-	}
-
-	state = card->states[0];
-	if (state) {
-		if ((state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ)) {
-			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n"));
-			dmabuf = &state->dmabuf;
-			mutex_lock(&state->open_mutex);
-			stop_adc(state);
-			dealloc_dmabuf(state);
-			state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-			free_page((unsigned long)state->dmabuf.pbuf);
-
-			/* we're covered by the open_mutex */
-			mutex_unlock(&state->open_mutex);
-			state->card->states[state->virt] = NULL;
-			state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-
-			if ((tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE))) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
-					"cs46xx: cs_release_mixdev() powerdown ADC failure (0x%x)\n",tmp) );
-			}
-
-			/* Now turn off external AMP if needed */
-			state->card->amplifier_ctrl(state->card, -1);
-			state->card->active_ctrl(state->card, -1);
-			kfree(state);
-		}
-	}
-
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n"));
-	return 0;
-}
-
-static void printpm(struct cs_card *s)
-{
-	CS_DBGOUT(CS_PM, 9, printk("pm struct:\n"));
-	CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n",
-		(unsigned)s->pm.flags,s->pm.u32CLKCR1_SAVE,s->pm.u32SSPMValue));
-	CS_DBGOUT(CS_PM, 9, printk("u32PPLVCvalue: 0x%x u32PPRVCvalue: 0x%x\n",
-		s->pm.u32PPLVCvalue,s->pm.u32PPRVCvalue));
-	CS_DBGOUT(CS_PM, 9, printk("u32FMLVCvalue: 0x%x u32FMRVCvalue: 0x%x\n",
-		s->pm.u32FMLVCvalue,s->pm.u32FMRVCvalue));
-	CS_DBGOUT(CS_PM, 9, printk("u32GPIORvalue: 0x%x u32JSCTLvalue: 0x%x\n",
-		s->pm.u32GPIORvalue,s->pm.u32JSCTLvalue));
-	CS_DBGOUT(CS_PM, 9, printk("u32SSCR: 0x%x u32SRCSA: 0x%x\n",
-		s->pm.u32SSCR,s->pm.u32SRCSA));
-	CS_DBGOUT(CS_PM, 9, printk("u32DacASR: 0x%x u32AdcASR: 0x%x\n",
-		s->pm.u32DacASR,s->pm.u32AdcASR));
-	CS_DBGOUT(CS_PM, 9, printk("u32DacSR: 0x%x u32AdcSR: 0x%x\n",
-		s->pm.u32DacSR,s->pm.u32AdcSR));
-	CS_DBGOUT(CS_PM, 9, printk("u32MIDCR_Save: 0x%x\n",
-		s->pm.u32MIDCR_Save));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_powerdown: 0x%x _general_purpose 0x%x\n",
-		s->pm.u32AC97_powerdown,s->pm.u32AC97_general_purpose));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume: 0x%x\n",
-		s->pm.u32AC97_master_volume));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_headphone_volume: 0x%x\n",
-		s->pm.u32AC97_headphone_volume));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume_mono: 0x%x\n",
-		s->pm.u32AC97_master_volume_mono));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_pcm_out_volume: 0x%x\n",
-		s->pm.u32AC97_pcm_out_volume));
-	CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_play: 0x%x dmabuf_count_play: %d\n",
-		s->pm.dmabuf_swptr_play,s->pm.dmabuf_count_play));
-	CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_capture: 0x%x dmabuf_count_capture: %d\n",
-		s->pm.dmabuf_swptr_capture,s->pm.dmabuf_count_capture));
-
-}
-
-/****************************************************************************
-*
-*  Suspend - save the ac97 regs, mute the outputs and power down the part.  
-*
-****************************************************************************/
-static void cs46xx_ac97_suspend(struct cs_card *card)
-{
-	int Count,i;
-	struct ac97_codec *dev=card->ac97_codec[0];
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()+\n"));
-
-	if (card->states[1]) {
-		stop_dac(card->states[1]);
-		resync_dma_ptrs(card->states[1]);
-	}
-	if (card->states[0]) {
-		stop_adc(card->states[0]);
-		resync_dma_ptrs(card->states[0]);
-	}
-
-	for (Count = 0x2, i = 0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE)
-			&& (i < CS46XX_AC97_NUMBER_RESTORE_REGS);
-			Count += 2, i++) {
-		card->pm.ac97[i] = cs_ac97_get(dev, BA0_AC97_RESET + Count);
-	}
-/*
-* Save the ac97 volume registers as well as the current powerdown state.
-* Now, mute the all the outputs (master, headphone, and mono), as well
-* as the PCM volume, in preparation for powering down the entire part.
-	card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, 
-			(u8)BA0_AC97_MASTER_VOLUME); 
-	card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, 
-			(u8)BA0_AC97_HEADPHONE_VOLUME); 
-	card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, 
-			(u8)BA0_AC97_MASTER_VOLUME_MONO); 
-	card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, 
-			(u8)BA0_AC97_PCM_OUT_VOLUME);
-*/ 
-/*
-* mute the outputs
-*/
-	cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
-	cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
-	cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
-	cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
-
-/*
-* save the registers that cause pops
-*/
-	card->pm.u32AC97_powerdown = (u32)cs_ac97_get(dev, (u8)AC97_POWER_CONTROL); 
-	card->pm.u32AC97_general_purpose = (u32)cs_ac97_get(dev, (u8)BA0_AC97_GENERAL_PURPOSE); 
-/*
-* And power down everything on the AC97 codec.
-* well, for now, only power down the DAC/ADC and MIXER VREFON components. 
-* trouble with removing VREF.
-*/
-	if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-			CS_POWER_MIXVON, CS_TRUE))) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp));
-	}
-
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n"));
-}
-
-/****************************************************************************
-*
-*  Resume - power up the part and restore its registers..  
-*
-****************************************************************************/
-static void cs46xx_ac97_resume(struct cs_card *card)
-{
-	int Count,i;
-	struct ac97_codec *dev=card->ac97_codec[0];
-
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()+\n"));
-
-/*
-* First, we restore the state of the general purpose register.  This
-* contains the mic select (mic1 or mic2) and if we restore this after
-* we restore the mic volume/boost state and mic2 was selected at
-* suspend time, we will end up with a brief period of time where mic1
-* is selected with the volume/boost settings for mic2, causing
-* acoustic feedback.  So we restore the general purpose register
-* first, thereby getting the correct mic selected before we restore
-* the mic volume/boost.
-*/
-	cs_ac97_set(dev, (u8)BA0_AC97_GENERAL_PURPOSE, 
-		(u16)card->pm.u32AC97_general_purpose);
-/*
-* Now, while the outputs are still muted, restore the state of power
-* on the AC97 part.
-*/
-	cs_ac97_set(dev, (u8)BA0_AC97_POWERDOWN, (u16)card->pm.u32AC97_powerdown);
-	mdelay(5 * cs_laptop_wait);
-/*
-* Restore just the first set of registers, from register number
-* 0x02 to the register number that ulHighestRegToRestore specifies.
-*/
-	for (Count = 0x2, i=0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) &&
-			(i < CS46XX_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) {
-		cs_ac97_set(dev, (u8)(BA0_AC97_RESET + Count), (u16)card->pm.ac97[i]);
-	}
-
-	/* Check if we have to init the amplifier */
-	if (card->amp_init)
-		card->amp_init(card);
-        
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n"));
-}
-
-
-static int cs46xx_restart_part(struct cs_card *card)
-{
-	struct dmabuf *dmabuf;
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk( "cs46xx: cs46xx_restart_part()+\n"));
-	if (card->states[1]) {
-		dmabuf = &card->states[1]->dmabuf;
-		dmabuf->ready = 0;
-		resync_dma_ptrs(card->states[1]);
-		cs_set_divisor(dmabuf);
-		if (__prog_dmabuf(card->states[1])) {
-			CS_DBGOUT(CS_PM | CS_ERROR, 1, 
-				printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() dac error\n"));
-			return -1;
-		}
-		cs_set_dac_rate(card->states[1], dmabuf->rate);
-	}
-	if (card->states[0]) {
-		dmabuf = &card->states[0]->dmabuf;
-		dmabuf->ready = 0;
-		resync_dma_ptrs(card->states[0]);
-		cs_set_divisor(dmabuf);
-		if (__prog_dmabuf(card->states[0])) {
-			CS_DBGOUT(CS_PM | CS_ERROR, 1, 
-				printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() adc error\n"));
-			return -1;
-		}
-		cs_set_adc_rate(card->states[0], dmabuf->rate);
-	}
-	card->pm.flags |= CS46XX_PM_RESUMED;
-	if (card->states[0])
-		start_adc(card->states[0]);
-	if (card->states[1])
-		start_dac(card->states[1]);
-
-	card->pm.flags |= CS46XX_PM_IDLE;
-	card->pm.flags &= ~(CS46XX_PM_SUSPENDING | CS46XX_PM_SUSPENDED 
-			| CS46XX_PM_RESUMING | CS46XX_PM_RESUMED);
-	if (card->states[0])
-		wake_up(&card->states[0]->dmabuf.wait);
-	if (card->states[1])
-		wake_up(&card->states[1]->dmabuf.wait);
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk( "cs46xx: cs46xx_restart_part()-\n"));
-	return 0;
-}
-
-static void cs461x_reset(struct cs_card *card);
-static void cs461x_proc_stop(struct cs_card *card);
-static int cs46xx_suspend(struct cs_card *card, pm_message_t state)
-{
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=%p\n",
-			(unsigned)card->pm.flags,card));
-/*
-* check the current state, only suspend if IDLE
-*/
-	if (!(card->pm.flags & CS46XX_PM_IDLE)) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
-			printk("cs46xx: cs46xx_suspend() unable to suspend, not IDLE\n"));
-		return 1;
-	}
-	card->pm.flags &= ~CS46XX_PM_IDLE;
-	card->pm.flags |= CS46XX_PM_SUSPENDING;
-
-	card->active_ctrl(card,1);
-	
-	tmp = cs461x_peek(card, BA1_PFIE);
-	tmp &= ~0x0000f03f;
-	tmp |=  0x00000010;
-	cs461x_poke(card, BA1_PFIE, tmp);	/* playback interrupt disable */
-
-	tmp = cs461x_peek(card, BA1_CIE);
-	tmp &= ~0x0000003f;
-	tmp |=  0x00000011;
-	cs461x_poke(card, BA1_CIE, tmp);	/* capture interrupt disable */
-
-	/*
-         *  Stop playback DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_PCTL);
-	cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
-	/*
-         *  Stop capture DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_CCTL);
-	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
-	if (card->states[1]) {
-		card->pm.dmabuf_swptr_play = card->states[1]->dmabuf.swptr;
-		card->pm.dmabuf_count_play = card->states[1]->dmabuf.count;
-	}
-	if (card->states[0]) {
-		card->pm.dmabuf_swptr_capture = card->states[0]->dmabuf.swptr;
-		card->pm.dmabuf_count_capture = card->states[0]->dmabuf.count;
-	}
-
-	cs46xx_ac97_suspend(card);
-
-	/*
-         *  Reset the processor.
-         */
-	cs461x_reset(card);
-
-	cs461x_proc_stop(card);
-
-	/*
-	 *  Power down the DAC and ADC.  For now leave the other areas on.
-	 */
-	cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, 0x0300);
-
-	/*
-	 *  Power down the PLL.
-	 */
-	cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-
-	/*
-	 *  Turn off the Processor by turning off the software clock enable flag in 
-	 *  the clock control register.
-	 */
-	tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE;
-	cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
-	card->active_ctrl(card,-1);
-
-	card->pm.flags &= ~CS46XX_PM_SUSPENDING;
-	card->pm.flags |= CS46XX_PM_SUSPENDED;
-
-	printpm(card);
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk("cs46xx: cs46xx_suspend()- flags=0x%x\n",
-			(unsigned)card->pm.flags));
-	return 0;
-}
-
-static int cs46xx_resume(struct cs_card *card)
-{
-	int i;
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n",
-			(unsigned)card->pm.flags));
-	if (!(card->pm.flags & CS46XX_PM_SUSPENDED)) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
-			printk("cs46xx: cs46xx_resume() unable to resume, not SUSPENDED\n"));
-		return 1;
-	}
-	card->pm.flags |= CS46XX_PM_RESUMING;
-	card->pm.flags &= ~CS46XX_PM_SUSPENDED;
-	printpm(card);
-	card->active_ctrl(card, 1);
-
-	for (i = 0; i < 5; i++) {
-		if (cs_hardware_init(card) != 0) {
-			CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
-				"cs46xx: cs46xx_resume()- ERROR in cs_hardware_init()\n"));
-			mdelay(10 * cs_laptop_wait);
-			cs461x_reset(card);
-			continue;
-		}
-		break;
-	}
-	if (i >= 4) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
-			"cs46xx: cs46xx_resume()- cs_hardware_init() failed, retried %d times.\n",i));
-		return 0;
-	}
-
-	if (cs46xx_restart_part(card)) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
-			"cs46xx: cs46xx_resume(): cs46xx_restart_part() returned error\n"));
-	}
-
-	card->active_ctrl(card, -1);
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=0x%x\n",
-		(unsigned)card->pm.flags));
-	return 0;
-}
-
-static /*const*/ struct file_operations cs461x_fops = {
-	CS_OWNER	CS_THIS_MODULE
-	.llseek		= no_llseek,
-	.read		= cs_read,
-	.write		= cs_write,
-	.poll		= cs_poll,
-	.ioctl		= cs_ioctl,
-	.mmap		= cs_mmap,
-	.open		= cs_open,
-	.release	= cs_release,
-};
-
-/* Write AC97 codec registers */
-
-
-static u16 _cs_ac97_get(struct ac97_codec *dev, u8 reg)
-{
-	struct cs_card *card = dev->private_data;
-	int count,loopcnt;
-	unsigned int tmp;
-	u16 ret;
-	
-	/*
-	 *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
-	 *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97 
-	 *  3. Write ACCTL = Control Register = 460h for initiating the write
-	 *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
-	 *  5. if DCV not cleared, break and return error
-	 *  6. Read ACSTS = Status Register = 464h, check VSTS bit
-	 */
-
-	cs461x_peekBA0(card, BA0_ACSDA);
-
-	/*
-	 *  Setup the AC97 control registers on the CS461x to send the
-	 *  appropriate command to the AC97 to perform the read.
-	 *  ACCAD = Command Address Register = 46Ch
-	 *  ACCDA = Command Data Register = 470h
-	 *  ACCTL = Control Register = 460h
-	 *  set DCV - will clear when process completed
-	 *  set CRW - Read command
-	 *  set VFRM - valid frame enabled
-	 *  set ESYN - ASYNC generation enabled
-	 *  set RSTN - ARST# inactive, AC97 codec not reset
-	 */
-
-	cs461x_pokeBA0(card, BA0_ACCAD, reg);
-	cs461x_pokeBA0(card, BA0_ACCDA, 0);
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
-					     ACCTL_VFRM | ACCTL_ESYN |
-					     ACCTL_RSTN);
-
-
-	/*
-	 *  Wait for the read to occur.
-	 */
-	if (!(card->pm.flags & CS46XX_PM_IDLE))
-		loopcnt = 2000;
-	else
-		loopcnt = 500 * cs_laptop_wait;
- 	loopcnt *= cs_laptop_wait;
-	for (count = 0; count < loopcnt; count++) {
-		/*
-		 *  First, we want to wait for a short time.
-	 	 */
-		udelay(10 * cs_laptop_wait);
-		/*
-		 *  Now, check to see if the read has completed.
-		 *  ACCTL = 460h, DCV should be reset by now and 460h = 17h
-		 */
-		if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV))
-			break;
-	}
-
-	/*
-	 *  Make sure the read completed.
-	 */
-	if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-			"cs46xx: AC'97 read problem (ACCTL_DCV), reg = 0x%x returning 0xffff\n", reg));
-		return 0xffff;
-	}
-
-	/*
-	 *  Wait for the valid status bit to go active.
-	 */
-
-	if (!(card->pm.flags & CS46XX_PM_IDLE))
-		loopcnt = 2000;
-	else
-		loopcnt = 1000;
- 	loopcnt *= cs_laptop_wait;
-	for (count = 0; count < loopcnt; count++) {
-		/*
-		 *  Read the AC97 status register.
-		 *  ACSTS = Status Register = 464h
-		 *  VSTS - Valid Status
-		 */
-		if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_VSTS)
-			break;
-		udelay(10 * cs_laptop_wait);
-	}
-	
-	/*
-	 *  Make sure we got valid status.
-	 */
-	if (!((tmp = cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) {
-		CS_DBGOUT(CS_ERROR, 2, printk(KERN_WARNING 
-			"cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x 0xffff \n", 
-				reg, tmp));
-		return 0xffff;
-	}
-
-	/*
-	 *  Read the data returned from the AC97 register.
-	 *  ACSDA = Status Data Register = 474h
-	 */
-	CS_DBGOUT(CS_FUNCTION, 9, printk(KERN_INFO
-		"cs46xx: cs_ac97_get() reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", 
-			reg, cs461x_peekBA0(card, BA0_ACSDA),
-			cs461x_peekBA0(card, BA0_ACCAD)));
-	ret = cs461x_peekBA0(card, BA0_ACSDA);
-	return ret;
-}
-
-static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg)
-{
-	u16 ret;
-	struct cs_card *card = dev->private_data;
-	
-	spin_lock(&card->ac97_lock);
-	ret = _cs_ac97_get(dev, reg);
-	spin_unlock(&card->ac97_lock);
-	return ret;
-}
-
-static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
-{
-	struct cs_card *card = dev->private_data;
-	int count;
-	int val2 = 0;
-	
-	spin_lock(&card->ac97_lock);
-	
-	if (reg == AC97_CD_VOL)
-		val2 = _cs_ac97_get(dev, AC97_CD_VOL);
-
-	/*
-	 *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
-	 *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
-	 *  3. Write ACCTL = Control Register = 460h for initiating the write
-	 *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
-	 *  5. if DCV not cleared, break and return error
-	 */
-
-	/*
-	 *  Setup the AC97 control registers on the CS461x to send the
-	 *  appropriate command to the AC97 to perform the read.
-	 *  ACCAD = Command Address Register = 46Ch
-	 *  ACCDA = Command Data Register = 470h
-	 *  ACCTL = Control Register = 460h
-	 *  set DCV - will clear when process completed
-	 *  reset CRW - Write command
-	 *  set VFRM - valid frame enabled
-	 *  set ESYN - ASYNC generation enabled
-	 *  set RSTN - ARST# inactive, AC97 codec not reset
-         */
-	cs461x_pokeBA0(card, BA0_ACCAD, reg);
-	cs461x_pokeBA0(card, BA0_ACCDA, val);
-	cs461x_peekBA0(card, BA0_ACCTL);
-	cs461x_pokeBA0(card, BA0_ACCTL, 0 | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
-				             ACCTL_ESYN | ACCTL_RSTN);
-	for (count = 0; count < 1000; count++) {
-		/*
-		 *  First, we want to wait for a short time.
-		 */
-		udelay(10 * cs_laptop_wait);
-		/*
-		 *  Now, check to see if the write has completed.
-		 *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
-		 */
-		if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV))
-			break;
-	}
-	/*
-	 *  Make sure the write completed.
-	 */
-	if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-			"cs46xx: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val));
-	}
-
-	spin_unlock(&card->ac97_lock);
-
-	/*
-	 *	Adjust power if the mixer is selected/deselected according
-	 *	to the CD.
-	 *
-	 *	IF the CD is a valid input source (mixer or direct) AND
-	 *		the CD is not muted THEN power is needed
-	 *
-	 *	We do two things. When record select changes the input to
-	 *	add/remove the CD we adjust the power count if the CD is
-	 *	unmuted.
-	 *
-	 *	When the CD mute changes we adjust the power level if the
-	 *	CD was a valid input.
-	 *
-	 *      We also check for CD volume != 0, as the CD mute isn't
-	 *      normally tweaked from userspace.
-	 */
-	 
-	/* CD mute change ? */
-	
-	if (reg == AC97_CD_VOL) {
-		/* Mute bit change ? */
-		if ((val2^val) & 0x8000 ||
-		    ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val)) {
-			/* This is a hack but its cleaner than the alternatives.
-			   Right now card->ac97_codec[0] might be NULL as we are
-			   still doing codec setup. This does an early assignment
-			   to avoid the problem if it occurs */
-			   
-			if (card->ac97_codec[0] == NULL)
-				card->ac97_codec[0] = dev;
-				
-			/* Mute on */
-			if (val & 0x8000 || val == 0x1f1f)
-				card->amplifier_ctrl(card, -1);
-			else { /* Mute off power on */
-				if (card->amp_init)
-					card->amp_init(card);
-				card->amplifier_ctrl(card, 1);
-			}
-		}
-	}
-}
-
-/* OSS /dev/mixer file operation methods */
-
-static int cs_open_mixdev(struct inode *inode, struct file *file)
-{
-	int i = 0;
-	unsigned int minor = iminor(inode);
-	struct cs_card *card = NULL;
-	struct list_head *entry;
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
-		  printk(KERN_INFO "cs46xx: cs_open_mixdev()+\n"));
-
-	list_for_each(entry, &cs46xx_devs) {
-		card = list_entry(entry, struct cs_card, list);
-		for (i = 0; i < NR_AC97; i++)
-			if (card->ac97_codec[i] != NULL &&
-			    card->ac97_codec[i]->dev_mixer == minor)
-				goto match;
-	}
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
-			printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
-		return -ENODEV;
-	}
- match:
-	if (!card->ac97_codec[i])
-		return -ENODEV;
-	file->private_data = card->ac97_codec[i];
-
-	card->active_ctrl(card,1);
-	if (!CS_IN_USE(&card->mixer_use_cnt)) {
-		if ((tmp = cs46xx_powerup(card, CS_POWER_MIXVON))) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs_open_mixdev() powerup failure (0x%x)\n", tmp));
-			return -EIO;
-		}
-	}
-	card->amplifier_ctrl(card, 1);
-	CS_INC_USE_COUNT(&card->mixer_use_cnt);
-	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
-		  printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n"));
-	return nonseekable_open(inode, file);
-}
-
-static int cs_release_mixdev(struct inode *inode, struct file *file)
-{
-	unsigned int minor = iminor(inode);
-	struct cs_card *card = NULL;
-	struct list_head *entry;
-	int i;
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
-		  printk(KERN_INFO "cs46xx: cs_release_mixdev()+\n"));
-	list_for_each(entry, &cs46xx_devs)
-	{
-		card = list_entry(entry, struct cs_card, list);
-		for (i = 0; i < NR_AC97; i++)
-			if (card->ac97_codec[i] != NULL &&
-			    card->ac97_codec[i]->dev_mixer == minor)
-				goto match;
-	}
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
-			printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
-		return -ENODEV;
-	}
-match:
-	if (!CS_DEC_AND_TEST(&card->mixer_use_cnt)) {
-		CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
-			  printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n"));
-		card->active_ctrl(card, -1);
-		card->amplifier_ctrl(card, -1);
-		return 0;
-	}
-/*
-* ok, no outstanding mixer opens, so powerdown.
-*/
-	if ((tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE))) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n", tmp));
-		card->active_ctrl(card, -1);
-		card->amplifier_ctrl(card, -1);
-		return -EIO;
-	}
-	card->active_ctrl(card, -1);
-	card->amplifier_ctrl(card, -1);
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
-		  printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n"));
-	return 0;
-}
-
-static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-			unsigned long arg)
-{
-	struct ac97_codec *codec = file->private_data;
-	struct cs_card *card = NULL;
-	struct list_head *entry;
-	unsigned long __user *p = (long __user *)arg;
-#if CSDEBUG_INTERFACE
-        int val;
-
-	if (	(cmd == SOUND_MIXER_CS_GETDBGMASK) ||
-		(cmd == SOUND_MIXER_CS_SETDBGMASK) ||
-		(cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||
-		(cmd == SOUND_MIXER_CS_SETDBGLEVEL) ||
-		(cmd == SOUND_MIXER_CS_APM)) {
-		switch (cmd) {
-		case SOUND_MIXER_CS_GETDBGMASK:
-			return put_user(cs_debugmask, p);
-		case SOUND_MIXER_CS_GETDBGLEVEL:
-			return put_user(cs_debuglevel, p);
-		case SOUND_MIXER_CS_SETDBGMASK:
-			if (get_user(val, p))
-				return -EFAULT;
-			cs_debugmask = val;
-			return 0;
-		case SOUND_MIXER_CS_SETDBGLEVEL:
-			if (get_user(val, p))
-				return -EFAULT;
-			cs_debuglevel = val;
-			return 0;
-		case SOUND_MIXER_CS_APM:
-			if (get_user(val, p))
-				return -EFAULT;
-			if (val == CS_IOCTL_CMD_SUSPEND) {
-				list_for_each(entry, &cs46xx_devs) {
-					card = list_entry(entry, struct cs_card, list);
-					cs46xx_suspend(card, PMSG_ON);
-				}
-
-			} else if (val == CS_IOCTL_CMD_RESUME) {
-				list_for_each(entry, &cs46xx_devs) {
-					card = list_entry(entry, struct cs_card, list);
-					cs46xx_resume(card);
-				}
-			} else {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
-				    "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n",
-					val));
-			}
-			return 0;
-		default:
-			CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
-				"cs46xx: mixer_ioctl(): ERROR unknown debug cmd\n"));
-			return 0;
-		}
-	}
-#endif
-	return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static /*const*/ struct file_operations cs_mixer_fops = {
-	CS_OWNER	CS_THIS_MODULE
-	.llseek		= no_llseek,
-	.ioctl		= cs_ioctl_mixdev,
-	.open		= cs_open_mixdev,
-	.release	= cs_release_mixdev,
-};
-
-/* AC97 codec initialisation. */
-static int __init cs_ac97_init(struct cs_card *card)
-{
-	int num_ac97 = 0;
-	int ready_2nd = 0;
-	struct ac97_codec *codec;
-	u16 eid;
-
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_ac97_init()+\n") );
-
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-		if ((codec = ac97_alloc_codec()) == NULL)
-			return -ENOMEM;
-
-		/* initialize some basic codec information, other fields will be filled
-		   in ac97_probe_codec */
-		codec->private_data = card;
-		codec->id = num_ac97;
-
-		codec->codec_read = cs_ac97_get;
-		codec->codec_write = cs_ac97_set;
-	
-		if (ac97_probe_codec(codec) == 0) {
-			CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-				"cs46xx: cs_ac97_init()- codec number %d not found\n",
-					num_ac97) );
-			card->ac97_codec[num_ac97] = NULL;
-			break;
-		}
-		CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-			"cs46xx: cs_ac97_init() found codec %d\n",num_ac97));
-
-		eid = cs_ac97_get(codec, AC97_EXTENDED_ID);
-		
-		if (eid == 0xFFFF) {
-			printk(KERN_WARNING "cs46xx: codec %d not present\n",num_ac97);
-			ac97_release_codec(codec);
-			break;
-		}
-		
-		card->ac97_features = eid;
-			
-		if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) {
-			printk(KERN_ERR "cs46xx: couldn't register mixer!\n");
-			ac97_release_codec(codec);
-			break;
-		}
-		card->ac97_codec[num_ac97] = codec;
-
-		CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-			"cs46xx: cs_ac97_init() ac97_codec[%d] set to %p\n",
-				(unsigned int)num_ac97,
-				codec));
-		/* if there is no secondary codec at all, don't probe any more */
-		if (!ready_2nd)
-		{
-			num_ac97 += 1;
-			break;
-		}
-	}
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_ac97_init()- %d\n", (unsigned int)num_ac97));
-	return num_ac97;
-}
-
-/*
- * load the static image into the DSP
- */
-#include "cs461x_image.h"
-static void cs461x_download_image(struct cs_card *card)
-{
-    unsigned i, j, temp1, temp2, offset, count;
-    unsigned char __iomem *pBA1 = ioremap(card->ba1_addr, 0x40000);
-    for (i = 0; i < CLEAR__COUNT; i++) {
-        offset = ClrStat[i].BA1__DestByteOffset;
-        count  = ClrStat[i].BA1__SourceSize;
-        for (temp1 = offset; temp1 < (offset + count); temp1 += 4)
-              writel(0, pBA1+temp1);
-    }
-
-    for (i = 0; i < FILL__COUNT; i++) {
-        temp2 = FillStat[i].Offset;
-        for (j = 0; j < (FillStat[i].Size) / 4; j++) {
-            temp1 = (FillStat[i]).pFill[j];
-            writel(temp1, pBA1+temp2 + j * 4);
-        }
-    }
-    iounmap(pBA1);
-}
-
-/*
- *  Chip reset
- */
-
-static void cs461x_reset(struct cs_card *card)
-{
-	int idx;
-
-	/*
-	 *  Write the reset bit of the SP control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, SPCR_RSTSP);
-
-	/*
-	 *  Write the control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, SPCR_DRQEN);
-
-	/*
-	 *  Clear the trap registers.
-	 */
-	for (idx = 0; idx < 8; idx++) {
-		cs461x_poke(card, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
-		cs461x_poke(card, BA1_TWPR, 0xFFFF);
-	}
-	cs461x_poke(card, BA1_DREG, 0);
-
-	/*
-	 *  Set the frame timer to reflect the number of cycles per frame.
-	 */
-	cs461x_poke(card, BA1_FRMT, 0xadf);
-}
-
-static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type)
-{
-	int idx, loop, startfifo=0, endfifo=0, powerdown1 = 0;
-	unsigned int tmp;
-
-	/*
-	 *  See if the devices are powered down.  If so, we must power them up first
-	 *  or they will not respond.
-	 */
-	if (!((tmp = cs461x_peekBA0(card, BA0_CLKCR1)) & CLKCR1_SWCE)) {
-		cs461x_pokeBA0(card, BA0_CLKCR1, tmp | CLKCR1_SWCE);
-		powerdown1 = 1;
-	}
-
-	/*
-	 *  We want to clear out the serial port FIFOs so we don't end up playing
-	 *  whatever random garbage happens to be in them.  We fill the sample FIFOS
-	 *  with zero (silence).
-         */
-	cs461x_pokeBA0(card, BA0_SERBWP, 0);
-
-	/*
-	* Check for which FIFO locations to clear, if we are currently
-	* playing or capturing then we don't want to put in 128 bytes of
-	* "noise".
-	 */
-	if (type & CS_TYPE_DAC) {
-		startfifo = 128;
-		endfifo = 256;
-	}
-	if (type & CS_TYPE_ADC) {
-		startfifo = 0;
-		if (!endfifo)
-			endfifo = 128;
-	}
-	/*
-	 *  Fill sample FIFO locations (256 locations total).
-	 */
-	for (idx = startfifo; idx < endfifo; idx++) {
-		/*
-		 *  Make sure the previous FIFO write operation has completed.
-		 */
-		for (loop = 0; loop < 5; loop++) {
-			udelay(50);
-			if (!(cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY))
-				break;
-		}
-		if (cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY) {
-			if (powerdown1)
-				cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-		}
-		/*
-		 *  Write the serial port FIFO index.
-		 */
-		cs461x_pokeBA0(card, BA0_SERBAD, idx);
-		/*
-		 *  Tell the serial port to load the new value into the FIFO location.
-		 */
-		cs461x_pokeBA0(card, BA0_SERBCM, SERBCM_WRC);
-	}
-	/*
-	 *  Now, if we powered up the devices, then power them back down again.
-	 *  This is kinda ugly, but should never happen.
-	 */
-	if (powerdown1)
-		cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-}
-
-
-static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag)
-{
-	int count;
-	unsigned int tmp=0,muted=0;
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
-		"cs46xx: cs461x_powerdown()+ type=0x%x\n",type));
-	if (!cs_powerdown && !suspendflag) {
-		CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-			"cs46xx: cs461x_powerdown() DISABLED exiting\n"));
-		return 0;
-	}
-	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-		"cs46xx: cs461x_powerdown() powerdown reg=0x%x\n",tmp));
-/*
-* if powering down only the VREF, and not powering down the DAC/ADC,
-* then do not power down the VREF, UNLESS both the DAC and ADC are not
-* currently powered down.  If powering down DAC and ADC, then
-* it is possible to power down the VREF (ON).
-*/
-	if (((type & CS_POWER_MIXVON) &&
-		 (!(type & CS_POWER_ADC) || (!(type & CS_POWER_DAC))))
-	      && 
-		((tmp & CS_AC97_POWER_CONTROL_ADC_ON) ||
-		 (tmp & CS_AC97_POWER_CONTROL_DAC_ON))) {
-		CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-			"cs46xx: cs461x_powerdown()- 0  unable to powerdown. tmp=0x%x\n",tmp));
-		return 0;
-	}
-/*
-* for now, always keep power to the mixer block.
-* not sure why it's a problem but it seems to be if we power off.
-*/
-	type &= ~CS_POWER_MIXVON;
-	type &= ~CS_POWER_MIXVOFF;
-
-	/*
-	 *  Power down indicated areas.
-	 */
-	if (type & CS_POWER_MIXVOFF) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVOFF\n"));
-		/*
-		 *  Power down the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_MIXVOFF;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVOFF_ON))
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown MIXVOFF failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_MIXVON) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVON\n"));
-		/*
-		 *  Power down the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_MIXVON;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVON_ON))
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVON_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown MIXVON failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_ADC) {
-		/*
-		 *  Power down the ADC on the AC97 card.  
-		 */
-		CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()+ ADC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_ADC_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_ADC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
-
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_ADC_ON))
-					break;
-			}
-
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_ADC_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown ADC failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_DAC) {
-		/*
-		 *  Power down the DAC on the AC97 card.  
-		 */
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ DAC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_DAC_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_DAC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_DAC_ON))
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_DAC_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown DAC failed\n"));
-				return 1;
-			}
-		}
-	}
-	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	if (muted)
-		cs_mute(card, CS_FALSE);
-	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
-		"cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp));
-	return 0;
-}
-
-static int cs46xx_powerup(struct cs_card *card, unsigned int type)
-{
-	int count;
-	unsigned int tmp = 0, muted = 0;
-
-	CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-		"cs46xx: cs46xx_powerup()+ type=0x%x\n",type));
-	/*
-	* check for VREF and powerup if need to.
-	*/
-	if (type & CS_POWER_MIXVON)
-		type |= CS_POWER_MIXVOFF;
-	if (type & (CS_POWER_DAC | CS_POWER_ADC))
-		type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF;
-
-	/*
-	 *  Power up indicated areas.
-	 */
-	if (type & CS_POWER_MIXVOFF) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVOFF\n"));
-		/*
-		 *  Power up the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_MIXVOFF;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVOFF_ON)
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup MIXVOFF failed\n"));
-				return 1;
-			}
-		}
-	}
-	if(type & CS_POWER_MIXVON) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVON\n"));
-		/*
-		 *  Power up the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_MIXVON;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVON_ON)
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVON_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup MIXVON failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_ADC) {
-		/*
-		 *  Power up the ADC on the AC97 card.  
-		 */
-		CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs46xx_powerup()+ ADC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_ADC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_ADC_ON)
-					break;
-			}
-
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_ADC_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup ADC failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_DAC) {
-		/*
-		 *  Power up the DAC on the AC97 card.  
-		 */
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ DAC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_DAC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_DAC_ON)
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_DAC_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup DAC failed\n"));
-				return 1;
-			}
-		}
-	}
-	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	if (muted)
-		cs_mute(card, CS_FALSE);
-	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
-		"cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp));
-	return 0;
-}
-
-static void cs461x_proc_start(struct cs_card *card)
-{
-	int cnt;
-
-	/*
-	 *  Set the frame timer to reflect the number of cycles per frame.
-	 */
-	cs461x_poke(card, BA1_FRMT, 0xadf);
-	/*
-	 *  Turn on the run, run at frame, and DMA enable bits in the local copy of
-	 *  the SP control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
-	/*
-	 *  Wait until the run at frame bit resets itself in the SP control
-	 *  register.
-	 */
-	for (cnt = 0; cnt < 25; cnt++) {
-		udelay(50);
-		if (!(cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR))
-			break;
-	}
-
-	if (cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR)
-		printk(KERN_WARNING "cs46xx: SPCR_RUNFR never reset\n");
-}
-
-static void cs461x_proc_stop(struct cs_card *card)
-{
-	/*
-	 *  Turn off the run, run at frame, and DMA enable bits in the local copy of
-	 *  the SP control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, 0);
-}
-
-static int cs_hardware_init(struct cs_card *card)
-{
-	unsigned long end_time;
-	unsigned int tmp,count;
-	
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_hardware_init()+\n") );
-	/* 
-	 *  First, blast the clock control register to zero so that the PLL starts
-         *  out in a known state, and blast the master serial port control register
-         *  to zero so that the serial ports also start out in a known state.
-         */
-        cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-        cs461x_pokeBA0(card, BA0_SERMC1, 0);
-
-	/*
-	 *  If we are in AC97 mode, then we must set the part to a host controlled
-         *  AC-link.  Otherwise, we won't be able to bring up the link.
-         */        
-        cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03);	/* 1.03 card */
-        /* cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); */ /* 2.00 card */
-
-        /*
-         *  Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
-         *  spec) and then drive it high.  This is done for non AC97 modes since
-         *  there might be logic external to the CS461x that uses the ARST# line
-         *  for a reset.
-         */
-        cs461x_pokeBA0(card, BA0_ACCTL, 1);
-        udelay(50);
-        cs461x_pokeBA0(card, BA0_ACCTL, 0);
-        udelay(50);
-        cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_RSTN);
-
-	/*
-	 *  The first thing we do here is to enable sync generation.  As soon
-	 *  as we start receiving bit clock, we'll start producing the SYNC
-	 *  signal.
-	 */
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
-
-	/*
-	 *  Now wait for a short while to allow the AC97 part to start
-	 *  generating bit clock (so we don't try to start the PLL without an
-	 *  input clock).
-	 */
-	mdelay(5 * cs_laptop_wait);		/* 1 should be enough ?? (and pigs might fly) */
-
-	/*
-	 *  Set the serial port timing configuration, so that
-	 *  the clock control circuit gets its clock from the correct place.
-	 */
-	cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97);
-
-	/*
-	* The part seems to not be ready for a while after a resume.
-	* so, if we are resuming, then wait for 700 mils.  Note that 600 mils
-	* is not enough for some platforms! tested on an IBM Thinkpads and 
-	* reference cards.
-	*/
-	if (!(card->pm.flags & CS46XX_PM_IDLE))
-		mdelay(initdelay);
-	/*
-	 *  Write the selected clock control setup to the hardware.  Do not turn on
-	 *  SWCE yet (if requested), so that the devices clocked by the output of
-	 *  PLL are not clocked until the PLL is stable.
-	 */
-	cs461x_pokeBA0(card, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
-	cs461x_pokeBA0(card, BA0_PLLM, 0x3a);
-	cs461x_pokeBA0(card, BA0_CLKCR2, CLKCR2_PDIVS_8);
-
-	/*
-	 *  Power up the PLL.
-	 */
-	cs461x_pokeBA0(card, BA0_CLKCR1, CLKCR1_PLLP);
-
-	/*
-         *  Wait until the PLL has stabilized.
-	 */
-	mdelay(5 * cs_laptop_wait);		/* Again 1 should be enough ?? */
-
-	/*
-	 *  Turn on clocking of the core so that we can setup the serial ports.
-	 */
-	tmp = cs461x_peekBA0(card, BA0_CLKCR1) | CLKCR1_SWCE;
-	cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
-	/*
-	 *  Fill the serial port FIFOs with silence.
-	 */
-	cs461x_clear_serial_FIFOs(card,CS_TYPE_DAC | CS_TYPE_ADC);
-
-	/*
-	 *  Set the serial port FIFO pointer to the first sample in the FIFO.
-	 */
-	/* cs461x_pokeBA0(card, BA0_SERBSP, 0); */
-
-	/*
-	 *  Write the serial port configuration to the part.  The master
-	 *  enable bit is not set until all other values have been written.
-	 */
-	cs461x_pokeBA0(card, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
-	cs461x_pokeBA0(card, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
-	cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
-
-
-	mdelay(5 * cs_laptop_wait);		/* Shouldnt be needed ?? */
-	
-/*
-* If we are resuming under 2.2.x then we cannot schedule a timeout,
-* so just spin the CPU.
-*/
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-	/*
-	 * Wait for the card ready signal from the AC97 card.
-	 */
-		end_time = jiffies + 3 * (HZ >> 2);
-		do {
-		/*
-		 *  Read the AC97 status register to see if we've seen a CODEC READY
-		 *  signal from the AC97 card.
-		 */
-			if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)
-				break;
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout(1);
-		} while (time_before(jiffies, end_time));
-	} else {
-		for (count = 0; count < 100; count++) {
-		// First, we want to wait for a short time.
-			udelay(25 * cs_laptop_wait);
-
-			if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)
-				break;
-		}
-	}
-
-	/*
-	 *  Make sure CODEC is READY.
-	 */
-	if (!(cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING  
-			"cs46xx: create - never read card ready from AC'97\n"));
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING  
-			"cs46xx: probably not a bug, try using the CS4232 driver,\n"));
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING  
-			"cs46xx: or turn off any automatic Power Management support in the BIOS.\n"));
-		return -EIO;
-	}
-
-	/*
-	 *  Assert the vaid frame signal so that we can start sending commands
-	 *  to the AC97 card.
-	 */
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
-
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-	/*
-	 *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
-	 *  the card is pumping ADC data across the AC-link.
-	 */
-		end_time = jiffies + 3 * (HZ >> 2);
-		do {
-			/*
-			 *  Read the input slot valid register and see if input slots 3 and
-			 *  4 are valid yet.
-			 */
-			if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
-				break;
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout(1);
-		} while (time_before(jiffies, end_time));
-	} else {
-		for (count = 0; count < 100; count++) {
-		// First, we want to wait for a short time.
-			udelay(25 * cs_laptop_wait);
-
-			if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
-				break;
-		}
-	}
-	/*
-	 *  Make sure input slots 3 and 4 are valid.  If not, then return
-	 *  an error.
-	 */
-	if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4)) {
-		printk(KERN_WARNING "cs46xx: create - never read ISV3 & ISV4 from AC'97\n");
-		return -EIO;
-	}
-
-	/*
-	 *  Now, assert valid frame and the slot 3 and 4 valid bits.  This will
-	 *  commense the transfer of digital audio data to the AC97 card.
-	 */
-	cs461x_pokeBA0(card, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
-
-	/*
-	 *  Turn off the Processor by turning off the software clock enable flag in 
-	 *  the clock control register.
-	 */
-	/* tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; */
-	/* cs461x_pokeBA0(card, BA0_CLKCR1, tmp); */
-
-	/*
-         *  Reset the processor.
-         */
-	cs461x_reset(card);
-
-	/*
-         *  Download the image to the processor.
-	 */
-	
-	cs461x_download_image(card);
-
-	/*
-         *  Stop playback DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_PCTL);
-	card->pctl = tmp & 0xffff0000;
-	cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
-	/*
-         *  Stop capture DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_CCTL);
-	card->cctl = tmp & 0x0000ffff;
-	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
-	/* initialize AC97 codec and register /dev/mixer */
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-		if (cs_ac97_init(card) <= 0) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs_ac97_init() failure\n"));
-			return -EIO;
-		}
-	} else {
-		cs46xx_ac97_resume(card);
-	}
-	
-	cs461x_proc_start(card);
-
-	/*
-	 *  Enable interrupts on the part.
-	 */
-	cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);
-
-	tmp = cs461x_peek(card, BA1_PFIE);
-	tmp &= ~0x0000f03f;
-	cs461x_poke(card, BA1_PFIE, tmp);	/* playback interrupt enable */
-
-	tmp = cs461x_peek(card, BA1_CIE);
-	tmp &= ~0x0000003f;
-	tmp |=  0x00000001;
-	cs461x_poke(card, BA1_CIE, tmp);	/* capture interrupt enable */	
-
-	/*
-	 *  If IDLE then Power down the part.  We will power components up 
-	 *  when we need them.  
-	 */
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-		if (!cs_powerdown) {
-			if ((tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC |
-					CS_POWER_MIXVON))) {
-				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-					"cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) );
-				return -EIO;
-			}
-		} else {
-			if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-					CS_POWER_MIXVON, CS_FALSE))) {
-				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-					"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
-				return -EIO;
-			}
-		}
-	}
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_hardware_init()- 0\n"));
-	return 0;
-}
-
-/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
-   until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-   
-/*
- *	Card subid table
- */
- 
-struct cs_card_type
-{
-	u16 vendor;
-	u16 id;
-	char *name;
-	void (*amp)(struct cs_card *, int);
-	void (*amp_init)(struct cs_card *);
-	void (*active)(struct cs_card *, int);
-};
-
-static struct cs_card_type cards[] = {
-	{
-		.vendor	= 0x1489,
-		.id	= 0x7001,
-		.name	= "Genius Soundmaker 128 value",
-		.amp	= amp_none,
-	},
-	{
-		.vendor	= 0x5053,
-		.id	= 0x3357,
-		.name	= "Voyetra",
-		.amp	= amp_voyetra,
-	},
-	{
-		.vendor	= 0x1071,
-		.id	= 0x6003,
-		.name	= "Mitac MI6020/21",
-		.amp	= amp_voyetra,
-	},
-	{
-		.vendor	= 0x14AF,
-		.id	= 0x0050,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0050,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0051,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0052,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0053,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0054,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0xa010,
-		.name	= "Hercules Fortissimo II",
-		.amp	= amp_none,
-	},
-	/* Not sure if the 570 needs the clkrun hack */
-	{
-		.vendor	= PCI_VENDOR_ID_IBM,
-		.id	= 0x0132,
-		.name	= "Thinkpad 570",
-		.amp	= amp_none,
-		.active	= clkrun_hack,
-	},
-	{
-		.vendor	= PCI_VENDOR_ID_IBM,
-		.id	= 0x0153,
-		.name	= "Thinkpad 600X/A20/T20",
-		.amp	= amp_none,
-		.active	= clkrun_hack,
-	},
-	{
-		.vendor	= PCI_VENDOR_ID_IBM,
-		.id	= 0x1010,
-		.name	= "Thinkpad 600E (unsupported)",
-	},
-	{
-		.name	= "Card without SSID set",
-	},
-	{ 0, },
-};
-
-MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela, <pcaudio@crystal.cirrus.com>");
-MODULE_DESCRIPTION("Crystal SoundFusion Audio Support");
-MODULE_LICENSE("GPL");
-
-static const char cs46xx_banner[] = KERN_INFO "Crystal 4280/46xx + AC97 Audio, version " CS46XX_MAJOR_VERSION "." CS46XX_MINOR_VERSION "." CS46XX_ARCH ", " __TIME__ " " __DATE__ "\n";
-static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n";
-
-static int __devinit cs46xx_probe(struct pci_dev *pci_dev,
-				  const struct pci_device_id *pciid)
-{
-	int i, j;
-	u16 ss_card, ss_vendor;
-	struct cs_card *card;
-	dma_addr_t dma_mask;
-	struct cs_card_type *cp = &cards[0];
-
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2,
-		  printk(KERN_INFO "cs46xx: probe()+\n"));
-
-	dma_mask = 0xffffffff;	/* this enables playback and recording */
-	if (pci_enable_device(pci_dev)) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
-			 "cs46xx: pci_enable_device() failed\n"));
-		return -1;
-	}
-	if (!RSRCISMEMORYREGION(pci_dev, 0) ||
-	    !RSRCISMEMORYREGION(pci_dev, 1)) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			 "cs46xx: probe()- Memory region not assigned\n"));
-		return -1;
-	}
-	if (pci_dev->irq == 0) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			 "cs46xx: probe() IRQ not assigned\n"));
-		return -1;
-	}
-	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-		      "cs46xx: probe() architecture does not support 32bit PCI busmaster DMA\n"));
-		return -1;
-	}
-	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
-	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card);
-
-	if ((card = kzalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "cs46xx: out of memory\n");
-		return -ENOMEM;
-	}
-	card->ba0_addr = RSRCADDRESS(pci_dev, 0);
-	card->ba1_addr = RSRCADDRESS(pci_dev, 1);
-	card->pci_dev = pci_dev;
-	card->irq = pci_dev->irq;
-	card->magic = CS_CARD_MAGIC;
-	spin_lock_init(&card->lock);
-	spin_lock_init(&card->ac97_lock);
-
-	pci_set_master(pci_dev);
-
-	printk(cs46xx_banner);
-	printk(KERN_INFO "cs46xx: Card found at 0x%08lx and 0x%08lx, IRQ %d\n",
-	       card->ba0_addr, card->ba1_addr, card->irq);
-
-	card->alloc_pcm_channel = cs_alloc_pcm_channel;
-	card->alloc_rec_pcm_channel = cs_alloc_rec_pcm_channel;
-	card->free_pcm_channel = cs_free_pcm_channel;
-	card->amplifier_ctrl = amp_none;
-	card->active_ctrl = amp_none;
-
-	while (cp->name)
-	{
-		if (cp->vendor == ss_vendor && cp->id == ss_card) {
-			card->amplifier_ctrl = cp->amp;
-			if (cp->active)
-				card->active_ctrl = cp->active;
-			if (cp->amp_init)
-				card->amp_init = cp->amp_init;
-			break;
-		}
-		cp++;
-	}
-	if (cp->name == NULL) {
-		printk(KERN_INFO "cs46xx: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
-			ss_vendor, ss_card, card->ba0_addr, card->ba1_addr,  card->irq);
-	} else {
-		printk(KERN_INFO "cs46xx: %s (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
-			cp->name, ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq);
-	}
-	
-	if (card->amplifier_ctrl == NULL) {
-		card->amplifier_ctrl = amp_none;
-		card->active_ctrl = clkrun_hack;
-	}		
-
-	if (external_amp == 1) {
-		printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n");
-		card->amplifier_ctrl = amp_voyetra;
-	}
-
-	if (thinkpad == 1) {
-		printk(KERN_INFO "cs46xx: Activating CLKRUN hack for Thinkpad.\n");
-		card->active_ctrl = clkrun_hack;
-	}
-/*
-* The thinkpads don't work well without runtime updating on their kernel 
-* delay values (or any laptop with variable CPU speeds really).
-* so, just to be safe set the init delay to 2100.  Eliminates
-* failures on T21 Thinkpads.  remove this code when the udelay
-* and mdelay kernel code is replaced by a pm timer, or the delays
-* work well for battery and/or AC power both.
-*/
-	if (card->active_ctrl == clkrun_hack) {
-		initdelay = 2100;
-		cs_laptop_wait = 5;
-	}
-	if ((card->active_ctrl == clkrun_hack) && !(powerdown == 1)) {
-/*
-* for some currently unknown reason, powering down the DAC and ADC component
-* blocks on thinkpads causes some funky behavior... distoorrrtion and ac97 
-* codec access problems.  probably the serial clock becomes unsynced. 
-* added code to sync the chips back up, but only helped about 70% the time.
-*/
-		cs_powerdown = 0;
-	}
-	if (powerdown == 0)
-		cs_powerdown = 0;
-	card->active_ctrl(card, 1);
-
-	/* claim our iospace and irq */
-	
-	card->ba0 = ioremap_nocache(card->ba0_addr, CS461X_BA0_SIZE);
-	card->ba1.name.data0 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
-	card->ba1.name.data1 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
-	card->ba1.name.pmem = ioremap_nocache(card->ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
-	card->ba1.name.reg = ioremap_nocache(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
-	
-	CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO 
-		"cs46xx: card=%p card->ba0=%p\n",card,card->ba0) );
-	CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO 
-		"cs46xx: card->ba1=%p %p %p %p\n",
-			card->ba1.name.data0,
-			card->ba1.name.data1,
-			card->ba1.name.pmem,
-			card->ba1.name.reg) );
-
-	if (card->ba0 == 0 || card->ba1.name.data0 == 0 ||
-		card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 ||
-		card->ba1.name.reg == 0)
-		goto fail2;
-		
-	if (request_irq(card->irq, &cs_interrupt, IRQF_SHARED, "cs46xx", card)) {
-		printk(KERN_ERR "cs46xx: unable to allocate irq %d\n", card->irq);
-		goto fail2;
-	}
-	/* register /dev/dsp */
-	if ((card->dev_audio = register_sound_dsp(&cs461x_fops, -1)) < 0) {
-		printk(KERN_ERR "cs46xx: unable to register dsp\n");
-		goto fail;
-	}
-
-        /* register /dev/midi */
-        if ((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0)
-                printk(KERN_ERR "cs46xx: unable to register midi\n");
-                
-	card->pm.flags |= CS46XX_PM_IDLE;
-	for (i = 0; i < 5; i++) {
-		if (cs_hardware_init(card) != 0) {
-			CS_DBGOUT(CS_ERROR, 4, printk(
-				"cs46xx: ERROR in cs_hardware_init()... retrying\n"));
-			for (j = 0; j < NR_AC97; j++)
-				if (card->ac97_codec[j] != NULL) {
-					unregister_sound_mixer(card->ac97_codec[j]->dev_mixer);
-					ac97_release_codec(card->ac97_codec[j]);
-				}
-			mdelay(10 * cs_laptop_wait);
-			continue;
-		}
-		break;
-	}
-	if(i >= 4) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
-			"cs46xx: cs46xx_probe()- cs_hardware_init() failed, retried %d times.\n",i));
-                unregister_sound_dsp(card->dev_audio);
-                if (card->dev_midi)
-                        unregister_sound_midi(card->dev_midi);
-                goto fail;
-	}
-
-        init_waitqueue_head(&card->midi.open_wait);
-        mutex_init(&card->midi.open_mutex);
-        init_waitqueue_head(&card->midi.iwait);
-        init_waitqueue_head(&card->midi.owait);
-        cs461x_pokeBA0(card, BA0_MIDCR, MIDCR_MRST);   
-        cs461x_pokeBA0(card, BA0_MIDCR, 0);   
-
-	/* 
-	* Check if we have to init the amplifier, but probably already done
-	* since the CD logic in the ac97 init code will turn on the ext amp.
-	*/
-	if (cp->amp_init)
-		cp->amp_init(card);
-        card->active_ctrl(card, -1);
-
-	PCI_SET_DRIVER_DATA(pci_dev, card);
-	PCI_SET_DMA_MASK(pci_dev, dma_mask);
-	list_add(&card->list, &cs46xx_devs);
-
-	CS_DBGOUT(CS_PM, 9, printk(KERN_INFO "cs46xx: pm.flags=0x%x card=%p\n",
-		(unsigned)card->pm.flags,card));
-
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
-		"cs46xx: probe()- device allocated successfully\n"));
-        return 0;
-
-fail:
-	free_irq(card->irq, card);
-fail2:
-	if (card->ba0)
-		iounmap(card->ba0);
-	if (card->ba1.name.data0)
-		iounmap(card->ba1.name.data0);
-	if (card->ba1.name.data1)
-		iounmap(card->ba1.name.data1);
-	if (card->ba1.name.pmem)
-		iounmap(card->ba1.name.pmem);
-	if (card->ba1.name.reg)
-		iounmap(card->ba1.name.reg);
-	kfree(card);
-	CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO
-		"cs46xx: probe()- no device allocated\n"));
-	return -ENODEV;
-} // probe_cs46xx
-
-// --------------------------------------------------------------------- 
-
-static void __devexit cs46xx_remove(struct pci_dev *pci_dev)
-{
-	struct cs_card *card = PCI_GET_DRIVER_DATA(pci_dev);
-	int i;
-	unsigned int tmp;
-	
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
-		 "cs46xx: cs46xx_remove()+\n"));
-
-	card->active_ctrl(card,1);
-	
-	tmp = cs461x_peek(card, BA1_PFIE);
-	tmp &= ~0x0000f03f;
-	tmp |=  0x00000010;
-	cs461x_poke(card, BA1_PFIE, tmp);	/* playback interrupt disable */
-
-	tmp = cs461x_peek(card, BA1_CIE);
-	tmp &= ~0x0000003f;
-	tmp |=  0x00000011;
-	cs461x_poke(card, BA1_CIE, tmp);	/* capture interrupt disable */
-
-	/*
-         *  Stop playback DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_PCTL);
-	cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
-	/*
-         *  Stop capture DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_CCTL);
-	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
-	/*
-         *  Reset the processor.
-         */
-	cs461x_reset(card);
-
-	cs461x_proc_stop(card);
-
-	/*
-	 *  Power down the DAC and ADC.  We will power them up (if) when we need
-	 *  them.
-	 */
-	if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-			CS_POWER_MIXVON, CS_TRUE))) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
-	}
-
-	/*
-	 *  Power down the PLL.
-	 */
-	cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-
-	/*
-	 *  Turn off the Processor by turning off the software clock enable flag in 
-	 *  the clock control register.
-	 */
-	tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE;
-	cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
-	card->active_ctrl(card,-1);
-
-	/* free hardware resources */
-	free_irq(card->irq, card);
-	iounmap(card->ba0);
-	iounmap(card->ba1.name.data0);
-	iounmap(card->ba1.name.data1);
-	iounmap(card->ba1.name.pmem);
-	iounmap(card->ba1.name.reg);
-	
-	/* unregister audio devices */
-	for (i = 0; i < NR_AC97; i++)
-		if (card->ac97_codec[i] != NULL) {
-			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			ac97_release_codec(card->ac97_codec[i]);
-		}
-	unregister_sound_dsp(card->dev_audio);
-        if (card->dev_midi)
-                unregister_sound_midi(card->dev_midi);
-	list_del(&card->list);
-	kfree(card);
-	PCI_SET_DRIVER_DATA(pci_dev,NULL);
-
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
-		 "cs46xx: cs46xx_remove()-: remove successful\n"));
-}
-
-enum {
-	CS46XX_4610 = 0,
-	CS46XX_4612,  	/* same as 4630 */
-	CS46XX_4615,  	/* same as 4624 */
-};
-
-static struct pci_device_id cs46xx_pci_tbl[] = {
-	{
-		.vendor	     = PCI_VENDOR_ID_CIRRUS,
-		.device	     = PCI_DEVICE_ID_CIRRUS_4610,
-		.subvendor   = PCI_ANY_ID,
-		.subdevice   = PCI_ANY_ID,
-		.driver_data = CS46XX_4610,
-	},
-	{
-		.vendor	     = PCI_VENDOR_ID_CIRRUS,
-		.device	     = PCI_DEVICE_ID_CIRRUS_4612,
-		.subvendor   = PCI_ANY_ID,
-		.subdevice   = PCI_ANY_ID,
-		.driver_data = CS46XX_4612,
-	},
-	{
-		.vendor	     = PCI_VENDOR_ID_CIRRUS,
-		.device	     = PCI_DEVICE_ID_CIRRUS_4615,
-		.subvendor   = PCI_ANY_ID,
-		.subdevice   = PCI_ANY_ID,
-		.driver_data = CS46XX_4615,
-	},
-	{ 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, cs46xx_pci_tbl);
-
-static struct pci_driver cs46xx_pci_driver = {
-	.name	  = "cs46xx",
-	.id_table = cs46xx_pci_tbl,
-	.probe	  = cs46xx_probe,
-	.remove	  = __devexit_p(cs46xx_remove),
-#ifdef CONFIG_PM
-	.suspend  = cs46xx_suspend_tbl,
-	.resume	  = cs46xx_resume_tbl,
-#endif
-};
-
-static int __init cs46xx_init_module(void)
-{
-	int rtn = 0;
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO 
-		"cs46xx: cs46xx_init_module()+ \n"));
-	rtn = pci_register_driver(&cs46xx_pci_driver);
-
-	if (rtn == -ENODEV) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk( 
-			"cs46xx: Unable to detect valid cs46xx device\n"));
-	}
-
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs46xx: cs46xx_init_module()- (%d)\n",rtn));
-	return rtn;
-}
-
-static void __exit cs46xx_cleanup_module(void)
-{
-	pci_unregister_driver(&cs46xx_pci_driver);
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs46xx: cleanup_cs46xx() finished\n"));
-}
-
-module_init(cs46xx_init_module);
-module_exit(cs46xx_cleanup_module);
-
-#ifdef CONFIG_PM
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
-{
-	struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 2, 
-		printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n"));
-	cs46xx_suspend(s, state);
-	return 0;
-}
-
-static int cs46xx_resume_tbl(struct pci_dev *pcidev)
-{
-	struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 2, 
-		printk(KERN_INFO "cs46xx: cs46xx_resume_tbl request\n"));
-	cs46xx_resume(s);
-	return 0;
-}
-#endif
diff --git a/sound/oss/cs46xx_wrapper-24.h b/sound/oss/cs46xx_wrapper-24.h
deleted file mode 100644
index f68e011..0000000
--- a/sound/oss/cs46xx_wrapper-24.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
-*
-*      "cs46xx_wrapper.c" --  Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
-*            -- tom woller (twoller@crystal.cirrus.com) or
-*               (pcaudio@crystal.cirrus.com).
-*
-*      This program is free software; you can redistribute it and/or modify
-*      it under the terms of the GNU General Public License as published by
-*      the Free Software Foundation; either version 2 of the License, or
-*      (at your option) any later version.
-*
-*      This program is distributed in the hope that it will be useful,
-*      but WITHOUT ANY WARRANTY; without even the implied warranty of
-*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*      GNU General Public License for more details.
-*
-*      You should have received a copy of the GNU General Public License
-*      along with this program; if not, write to the Free Software
-*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* 01/11/2001 trw - new file from cs4281 wrapper code. 
-*
-*******************************************************************************/
-#ifndef __CS46XX_WRAPPER24_H
-#define __CS46XX_WRAPPER24_H
-
-#include <linux/spinlock.h>
-
-#define CS_OWNER .owner =
-#define CS_THIS_MODULE THIS_MODULE,
-static inline void cs46xx_null(struct pci_dev *pcidev) { return; }
-#define cs4x_mem_map_reserve(page) SetPageReserved(page)
-#define cs4x_mem_map_unreserve(page) ClearPageReserved(page)
-
-#define free_dmabuf(card, dmabuf) \
-	pci_free_consistent((card)->pci_dev, \
-			    PAGE_SIZE << (dmabuf)->buforder, \
-			    (dmabuf)->rawbuf, (dmabuf)->dmaaddr);
-#define free_dmabuf2(card, dmabuf) \
-	pci_free_consistent((card)->pci_dev, \
-				    PAGE_SIZE << (dmabuf)->buforder_tmpbuff, \
-				    (dmabuf)->tmpbuff, (dmabuf)->dmaaddr_tmpbuff);
-#define cs4x_pgoff(vma) ((vma)->vm_pgoff)
-
-#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
-	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
-#define RSRCISMEMORYREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
-	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
-#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
-#define PCI_GET_DRIVER_DATA pci_get_drvdata
-#define PCI_SET_DRIVER_DATA pci_set_drvdata
-#define PCI_SET_DMA_MASK(pcidev,mask) pcidev->dma_mask = mask
-
-#endif
diff --git a/sound/oss/cs46xxpm.h b/sound/oss/cs46xxpm.h
deleted file mode 100644
index 2932b6e..0000000
--- a/sound/oss/cs46xxpm.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
-*
-*      "cs46xxpm.h" --  Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
-*            -- tom woller (twoller@crystal.cirrus.com) or
-*               (pcaudio@crystal.cirrus.com).
-*
-*      This program is free software; you can redistribute it and/or modify
-*      it under the terms of the GNU General Public License as published by
-*      the Free Software Foundation; either version 2 of the License, or
-*      (at your option) any later version.
-*
-*      This program is distributed in the hope that it will be useful,
-*      but WITHOUT ANY WARRANTY; without even the implied warranty of
-*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*      GNU General Public License for more details.
-*
-*      You should have received a copy of the GNU General Public License
-*      along with this program; if not, write to the Free Software
-*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* 12/22/00 trw - new file. 
-*
-*******************************************************************************/
-#ifndef __CS46XXPM_H
-#define __CS46XXPM_H
-
-#define CS46XX_AC97_HIGHESTREGTORESTORE 0x26
-#define CS46XX_AC97_NUMBER_RESTORE_REGS (CS46XX_AC97_HIGHESTREGTORESTORE/2-1)
-
-/* PM state defintions */
-#define CS46XX_PM_NOT_REGISTERED	0x1000
-#define CS46XX_PM_IDLE			0x0001
-#define CS46XX_PM_SUSPENDING		0x0002
-#define CS46XX_PM_SUSPENDED		0x0004
-#define CS46XX_PM_RESUMING		0x0008
-#define CS46XX_PM_RESUMED		0x0010
-
-#define CS_POWER_DAC			0x0001
-#define CS_POWER_ADC			0x0002
-#define CS_POWER_MIXVON			0x0004
-#define CS_POWER_MIXVOFF		0x0008
-#define CS_AC97_POWER_CONTROL_ON	0xf000  /* always on bits (inverted) */
-#define CS_AC97_POWER_CONTROL_ADC	0x0100
-#define CS_AC97_POWER_CONTROL_DAC	0x0200
-#define CS_AC97_POWER_CONTROL_MIXVON	0x0400
-#define CS_AC97_POWER_CONTROL_MIXVOFF	0x0800
-#define CS_AC97_POWER_CONTROL_ADC_ON	0x0001
-#define CS_AC97_POWER_CONTROL_DAC_ON	0x0002
-#define CS_AC97_POWER_CONTROL_MIXVON_ON	0x0004
-#define CS_AC97_POWER_CONTROL_MIXVOFF_ON 0x0008
-
-struct cs46xx_pm {
-	unsigned long flags;
-	u32 u32CLKCR1_SAVE,u32SSPMValue,u32PPLVCvalue,u32PPRVCvalue;
-	u32 u32FMLVCvalue,u32FMRVCvalue,u32GPIORvalue,u32JSCTLvalue,u32SSCR;
-	u32 u32SRCSA,u32DacASR,u32AdcASR,u32DacSR,u32AdcSR,u32MIDCR_Save;
-	u32 u32SSPM_BITS;
-	u32 ac97[CS46XX_AC97_NUMBER_RESTORE_REGS];
-	u32 u32AC97_master_volume, u32AC97_headphone_volume, u32AC97_master_volume_mono;
-	u32 u32AC97_pcm_out_volume, u32AC97_powerdown, u32AC97_general_purpose;
-	u32 u32hwptr_playback,u32hwptr_capture;
-	unsigned dmabuf_swptr_play;
-	int dmabuf_count_play;
-	unsigned dmabuf_swptr_capture;
-	int dmabuf_count_capture;
-};
-
-#endif
diff --git a/sound/oss/emu10k1/8010.h b/sound/oss/emu10k1/8010.h
deleted file mode 100644
index 61c6c42..0000000
--- a/sound/oss/emu10k1/8010.h
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
- **********************************************************************
- *     8010.h
- *     Copyright 1999-2001 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date		    Author	    Summary of changes
- *     ----		    ------	    ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox	    Cleaned of 8bit chars, DOS
- *					    line endings
- *     December 8, 1999     Jon Taylor	    Added lots of new register info
- *     May 16, 2001         Daniel Bertrand Added unofficial DBG register info
- *     Oct-Nov 2001         D.B.            Added unofficial Audigy registers 
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _8010_H
-#define _8010_H
-
-#include <linux/types.h>
-
-// Driver version:
-#define MAJOR_VER 0
-#define MINOR_VER 20
-#define DRIVER_VERSION "0.20a"
-
-
-// Audigy specify registers are prefixed with 'A_'
-
-/************************************************************************************************/
-/* PCI function 0 registers, address = <val> + PCIBASE0						*/
-/************************************************************************************************/
-
-#define PTR			0x00		/* Indexed register set pointer register	*/
-						/* NOTE: The CHANNELNUM and ADDRESS words can	*/
-						/* be modified independently of each other.	*/
-#define PTR_CHANNELNUM_MASK	0x0000003f	/* For each per-channel register, indicates the	*/
-						/* channel number of the register to be		*/
-						/* accessed.  For non per-channel registers the	*/
-						/* value should be set to zero.			*/
-#define PTR_ADDRESS_MASK	0x07ff0000	/* Register index				*/
-
-#define DATA			0x04		/* Indexed register set data register		*/
-
-#define IPR			0x08		/* Global interrupt pending register		*/
-						/* Clear pending interrupts by writing a 1 to	*/
-						/* the relevant bits and zero to the other bits	*/
-
-/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
-#define A_IPR_MIDITRANSBUFEMPTY2	0x10000000	/* MIDI UART transmit buffer empty		*/
-#define A_IPR_MIDIRECVBUFEMPTY2	0x08000000	/* MIDI UART receive buffer empty		*/
-
-#define IPR_SAMPLERATETRACKER	0x01000000	/* Sample rate tracker lock status change	*/
-#define IPR_FXDSP		0x00800000	/* Enable FX DSP interrupts			*/
-#define IPR_FORCEINT		0x00400000	/* Force Sound Blaster interrupt		*/
-#define IPR_PCIERROR		0x00200000	/* PCI bus error				*/
-#define IPR_VOLINCR		0x00100000	/* Volume increment button pressed		*/
-#define IPR_VOLDECR		0x00080000	/* Volume decrement button pressed		*/
-#define IPR_MUTE		0x00040000	/* Mute button pressed				*/
-#define IPR_MICBUFFULL		0x00020000	/* Microphone buffer full			*/
-#define IPR_MICBUFHALFFULL	0x00010000	/* Microphone buffer half full			*/
-#define IPR_ADCBUFFULL		0x00008000	/* ADC buffer full				*/
-#define IPR_ADCBUFHALFFULL	0x00004000	/* ADC buffer half full				*/
-#define IPR_EFXBUFFULL		0x00002000	/* Effects buffer full				*/
-#define IPR_EFXBUFHALFFULL	0x00001000	/* Effects buffer half full			*/
-#define IPR_GPSPDIFSTATUSCHANGE	0x00000800	/* GPSPDIF channel status change		*/
-#define IPR_CDROMSTATUSCHANGE	0x00000400	/* CD-ROM channel status change			*/
-#define IPR_INTERVALTIMER	0x00000200	/* Interval timer terminal count		*/
-#define IPR_MIDITRANSBUFEMPTY	0x00000100	/* MIDI UART transmit buffer empty		*/
-#define IPR_MIDIRECVBUFEMPTY	0x00000080	/* MIDI UART receive buffer empty		*/
-#define IPR_CHANNELLOOP		0x00000040	/* One or more channel loop interrupts pending	*/
-#define IPR_CHANNELNUMBERMASK	0x0000003f	/* When IPR_CHANNELLOOP is set, indicates the	*/
-						/* Highest set channel in CLIPL or CLIPH.  When	*/
-						/* IP is written with CL set, the bit in CLIPL	*/
-						/* or CLIPH corresponding to the CIN value 	*/
-						/* written will be cleared.			*/
-#define A_IPR_MIDITRANSBUFEMPTY1	IPR_MIDITRANSBUFEMPTY	/* MIDI UART transmit buffer empty		*/
-#define A_IPR_MIDIRECVBUFEMPTY1	IPR_MIDIRECVBUFEMPTY	/* MIDI UART receive buffer empty		*/
-
-
-
-#define INTE			0x0c		/* Interrupt enable register			*/
-#define INTE_VIRTUALSB_MASK	0xc0000000	/* Virtual Soundblaster I/O port capture	*/
-#define INTE_VIRTUALSB_220	0x00000000	/* Capture at I/O base address 0x220-0x22f	*/
-#define INTE_VIRTUALSB_240	0x40000000	/* Capture at I/O base address 0x240		*/
-#define INTE_VIRTUALSB_260	0x80000000	/* Capture at I/O base address 0x260		*/
-#define INTE_VIRTUALSB_280	0xc0000000	/* Capture at I/O base address 0x280		*/
-#define INTE_VIRTUALMPU_MASK	0x30000000	/* Virtual MPU I/O port capture			*/
-#define INTE_VIRTUALMPU_300	0x00000000	/* Capture at I/O base address 0x300-0x301	*/
-#define INTE_VIRTUALMPU_310	0x10000000	/* Capture at I/O base address 0x310		*/
-#define INTE_VIRTUALMPU_320	0x20000000	/* Capture at I/O base address 0x320		*/
-#define INTE_VIRTUALMPU_330	0x30000000	/* Capture at I/O base address 0x330		*/
-#define INTE_MASTERDMAENABLE	0x08000000	/* Master DMA emulation at 0x000-0x00f		*/
-#define INTE_SLAVEDMAENABLE	0x04000000	/* Slave DMA emulation at 0x0c0-0x0df		*/
-#define INTE_MASTERPICENABLE	0x02000000	/* Master PIC emulation at 0x020-0x021		*/
-#define INTE_SLAVEPICENABLE	0x01000000	/* Slave PIC emulation at 0x0a0-0x0a1		*/
-#define INTE_VSBENABLE		0x00800000	/* Enable virtual Soundblaster			*/
-#define INTE_ADLIBENABLE	0x00400000	/* Enable AdLib emulation at 0x388-0x38b	*/
-#define INTE_MPUENABLE		0x00200000	/* Enable virtual MPU				*/
-#define INTE_FORCEINT		0x00100000	/* Continuously assert INTAN			*/
-
-#define INTE_MRHANDENABLE	0x00080000	/* Enable the "Mr. Hand" logic			*/
-						/* NOTE: There is no reason to use this under	*/
-						/* Linux, and it will cause odd hardware 	*/
-						/* behavior and possibly random segfaults and	*/
-						/* lockups if enabled.				*/
-
-/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
-#define A_INTE_MIDITXENABLE2	0x00020000	/* Enable MIDI transmit-buffer-empty interrupts	*/
-#define A_INTE_MIDIRXENABLE2	0x00010000	/* Enable MIDI receive-buffer-empty interrupts	*/
-
-
-#define INTE_SAMPLERATETRACKER	0x00002000	/* Enable sample rate tracker interrupts	*/
-						/* NOTE: This bit must always be enabled       	*/
-#define INTE_FXDSPENABLE	0x00001000	/* Enable FX DSP interrupts			*/
-#define INTE_PCIERRORENABLE	0x00000800	/* Enable PCI bus error interrupts		*/
-#define INTE_VOLINCRENABLE	0x00000400	/* Enable volume increment button interrupts	*/
-#define INTE_VOLDECRENABLE	0x00000200	/* Enable volume decrement button interrupts	*/
-#define INTE_MUTEENABLE		0x00000100	/* Enable mute button interrupts		*/
-#define INTE_MICBUFENABLE	0x00000080	/* Enable microphone buffer interrupts		*/
-#define INTE_ADCBUFENABLE	0x00000040	/* Enable ADC buffer interrupts			*/
-#define INTE_EFXBUFENABLE	0x00000020	/* Enable Effects buffer interrupts		*/
-#define INTE_GPSPDIFENABLE	0x00000010	/* Enable GPSPDIF status interrupts		*/
-#define INTE_CDSPDIFENABLE	0x00000008	/* Enable CDSPDIF status interrupts		*/
-#define INTE_INTERVALTIMERENB	0x00000004	/* Enable interval timer interrupts		*/
-#define INTE_MIDITXENABLE	0x00000002	/* Enable MIDI transmit-buffer-empty interrupts	*/
-#define INTE_MIDIRXENABLE	0x00000001	/* Enable MIDI receive-buffer-empty interrupts	*/
-
-/* The next two interrupts are for the midi port on the Audigy (A_MPU2)	*/
-#define A_INTE_MIDITXENABLE1  	INTE_MIDITXENABLE
-#define A_INTE_MIDIRXENABLE1	INTE_MIDIRXENABLE
-
-#define WC			0x10		/* Wall Clock register				*/
-#define WC_SAMPLECOUNTER_MASK	0x03FFFFC0	/* Sample periods elapsed since reset		*/
-#define WC_SAMPLECOUNTER	0x14060010
-#define WC_CURRENTCHANNEL	0x0000003F	/* Channel [0..63] currently being serviced	*/
-						/* NOTE: Each channel takes 1/64th of a sample	*/
-						/* period to be serviced.			*/
-
-#define HCFG			0x14		/* Hardware config register			*/
-						/* NOTE: There is no reason to use the legacy	*/
-						/* SoundBlaster emulation stuff described below	*/
-						/* under Linux, and all kinds of weird hardware	*/
-						/* behavior can result if you try.  Don't.	*/
-#define HCFG_LEGACYFUNC_MASK	0xe0000000	/* Legacy function number 			*/
-#define HCFG_LEGACYFUNC_MPU	0x00000000	/* Legacy MPU	 				*/
-#define HCFG_LEGACYFUNC_SB	0x40000000	/* Legacy SB					*/
-#define HCFG_LEGACYFUNC_AD	0x60000000	/* Legacy AD					*/
-#define HCFG_LEGACYFUNC_MPIC	0x80000000	/* Legacy MPIC					*/
-#define HCFG_LEGACYFUNC_MDMA	0xa0000000	/* Legacy MDMA					*/
-#define HCFG_LEGACYFUNC_SPCI	0xc0000000	/* Legacy SPCI					*/
-#define HCFG_LEGACYFUNC_SDMA	0xe0000000	/* Legacy SDMA					*/
-#define HCFG_IOCAPTUREADDR	0x1f000000	/* The 4 LSBs of the captured I/O address.	*/
-#define HCFG_LEGACYWRITE	0x00800000	/* 1 = write, 0 = read 				*/
-#define HCFG_LEGACYWORD		0x00400000	/* 1 = word, 0 = byte 				*/
-#define HCFG_LEGACYINT		0x00200000	/* 1 = legacy event captured. Write 1 to clear.	*/
-						/* NOTE: The rest of the bits in this register	*/
-						/* _are_ relevant under Linux.			*/
-#define HCFG_CODECFORMAT_MASK	0x00070000	/* CODEC format					*/
-#define HCFG_CODECFORMAT_AC97	0x00000000	/* AC97 CODEC format -- Primary Output		*/
-#define HCFG_CODECFORMAT_I2S	0x00010000	/* I2S CODEC format -- Secondary (Rear) Output	*/
-#define HCFG_GPINPUT0		0x00004000	/* External pin112				*/
-#define HCFG_GPINPUT1		0x00002000	/* External pin110				*/
-
-#define HCFG_GPOUTPUT_MASK	0x00001c00	/* External pins which may be controlled	*/
-#define HCFG_GPOUT0		0x00001000	/* set to enable digital out on 5.1 cards	*/
-
-#define HCFG_JOYENABLE      	0x00000200	/* Internal joystick enable    			*/
-#define HCFG_PHASETRACKENABLE	0x00000100	/* Phase tracking enable			*/
-						/* 1 = Force all 3 async digital inputs to use	*/
-						/* the same async sample rate tracker (ZVIDEO)	*/
-#define HCFG_AC3ENABLE_MASK	0x0x0000e0	/* AC3 async input control - Not implemented	*/
-#define HCFG_AC3ENABLE_ZVIDEO	0x00000080	/* Channels 0 and 1 replace ZVIDEO		*/
-#define HCFG_AC3ENABLE_CDSPDIF	0x00000040	/* Channels 0 and 1 replace CDSPDIF		*/
-#define HCFG_AC3ENABLE_GPSPDIF  0x00000020      /* Channels 0 and 1 replace GPSPDIF             */
-#define HCFG_AUTOMUTE		0x00000010	/* When set, the async sample rate convertors	*/
-						/* will automatically mute their output when	*/
-						/* they are not rate-locked to the external	*/
-						/* async audio source  				*/
-#define HCFG_LOCKSOUNDCACHE	0x00000008	/* 1 = Cancel bustmaster accesses to soundcache */
-						/* NOTE: This should generally never be used.  	*/
-#define HCFG_LOCKTANKCACHE_MASK	0x00000004	/* 1 = Cancel bustmaster accesses to tankcache	*/
-						/* NOTE: This should generally never be used.  	*/
-#define HCFG_LOCKTANKCACHE	0x01020014
-#define HCFG_MUTEBUTTONENABLE	0x00000002	/* 1 = Master mute button sets AUDIOENABLE = 0.	*/
-						/* NOTE: This is a 'cheap' way to implement a	*/
-						/* master mute function on the mute button, and	*/
-						/* in general should not be used unless a more	*/
-						/* sophisticated master mute function has not	*/
-						/* been written.       				*/
-#define HCFG_AUDIOENABLE	0x00000001	/* 0 = CODECs transmit zero-valued samples	*/
-						/* Should be set to 1 when the EMU10K1 is	*/
-						/* completely initialized.			*/
-
-//For Audigy, MPU port move to 0x70-0x74 ptr register
-
-#define MUDATA			0x18		/* MPU401 data register (8 bits)       		*/
-
-#define MUCMD			0x19		/* MPU401 command register (8 bits)    		*/
-#define MUCMD_RESET		0xff		/* RESET command				*/
-#define MUCMD_ENTERUARTMODE	0x3f		/* Enter_UART_mode command			*/
-						/* NOTE: All other commands are ignored		*/
-
-#define MUSTAT			MUCMD		/* MPU401 status register (8 bits)     		*/
-#define MUSTAT_IRDYN		0x80		/* 0 = MIDI data or command ACK			*/
-#define MUSTAT_ORDYN		0x40		/* 0 = MUDATA can accept a command or data	*/
-
-#define A_IOCFG			0x18		/* GPIO on Audigy card (16bits)			*/
-#define A_GPINPUT_MASK		0xff00
-#define A_GPOUTPUT_MASK		0x00ff
-
-#define TIMER			0x1a		/* Timer terminal count register (16-bit)	*/
-						/* NOTE: After the rate is changed, a maximum	*/
-						/* of 1024 sample periods should be allowed	*/
-						/* before the new rate is guaranteed accurate.	*/
-#define TIMER_RATE_MASK		0x03ff		/* Timer interrupt rate in sample periods	*/
-						/* 0 == 1024 periods, [1..4] are not useful	*/
-
-#define AC97DATA		0x1c		/* AC97 register set data register (16 bit)	*/
-
-#define AC97ADDRESS		0x1e		/* AC97 register set address register (8 bit)	*/
-#define AC97ADDRESS_READY	0x80		/* Read-only bit, reflects CODEC READY signal	*/
-#define AC97ADDRESS_ADDRESS	0x7f		/* Address of indexed AC97 register		*/
-
-/********************************************************************************************************/
-/* Emu10k1 pointer-offset register set, accessed through the PTR and DATA registers			*/
-/********************************************************************************************************/
-
-#define CPF			0x00		/* Current pitch and fraction register			*/
-#define CPF_CURRENTPITCH_MASK	0xffff0000	/* Current pitch (linear, 0x4000 == unity pitch shift) 	*/
-#define CPF_CURRENTPITCH	0x10100000
-#define CPF_STEREO_MASK		0x00008000	/* 1 = Even channel interleave, odd channel locked	*/
-#define CPF_STOP_MASK		0x00004000	/* 1 = Current pitch forced to 0			*/
-#define CPF_FRACADDRESS_MASK	0x00003fff	/* Linear fractional address of the current channel	*/
-
-#define PTRX			0x01		/* Pitch target and send A/B amounts register		*/
-#define PTRX_PITCHTARGET_MASK	0xffff0000	/* Pitch target of specified channel			*/
-#define PTRX_PITCHTARGET	0x10100001
-#define PTRX_FXSENDAMOUNT_A_MASK 0x0000ff00	/* Linear level of channel output sent to FX send bus A	*/
-#define PTRX_FXSENDAMOUNT_A	0x08080001
-#define PTRX_FXSENDAMOUNT_B_MASK 0x000000ff	/* Linear level of channel output sent to FX send bus B	*/
-#define PTRX_FXSENDAMOUNT_B	0x08000001
-
-#define CVCF			0x02		/* Current volume and filter cutoff register		*/
-#define CVCF_CURRENTVOL_MASK	0xffff0000	/* Current linear volume of specified channel		*/
-#define CVCF_CURRENTVOL		0x10100002
-#define CVCF_CURRENTFILTER_MASK	0x0000ffff	/* Current filter cutoff frequency of specified channel	*/
-#define CVCF_CURRENTFILTER	0x10000002
-
-#define VTFT			0x03		/* Volume target and filter cutoff target register	*/
-#define VTFT_VOLUMETARGET_MASK	0xffff0000	/* Volume target of specified channel			*/
-#define VTFT_FILTERTARGET_MASK	0x0000ffff	/* Filter cutoff target of specified channel		*/
-
-#define Z1			0x05		/* Filter delay memory 1 register			*/
-
-#define Z2			0x04		/* Filter delay memory 2 register			*/
-
-#define PSST			0x06		/* Send C amount and loop start address register	*/
-#define PSST_FXSENDAMOUNT_C_MASK 0xff000000	/* Linear level of channel output sent to FX send bus C	*/
-
-#define PSST_FXSENDAMOUNT_C	0x08180006
-
-#define PSST_LOOPSTARTADDR_MASK	0x00ffffff	/* Loop start address of the specified channel		*/
-#define PSST_LOOPSTARTADDR	0x18000006
-
-#define DSL			0x07		/* Send D amount and loop start address register	*/
-#define DSL_FXSENDAMOUNT_D_MASK	0xff000000	/* Linear level of channel output sent to FX send bus D	*/
-
-#define DSL_FXSENDAMOUNT_D	0x08180007
-
-#define DSL_LOOPENDADDR_MASK	0x00ffffff	/* Loop end address of the specified channel		*/
-#define DSL_LOOPENDADDR		0x18000007
-
-#define CCCA			0x08		/* Filter Q, interp. ROM, byte size, cur. addr register */
-#define CCCA_RESONANCE		0xf0000000	/* Lowpass filter resonance (Q) height			*/
-#define CCCA_INTERPROMMASK	0x0e000000	/* Selects passband of interpolation ROM		*/
-						/* 1 == full band, 7 == lowpass				*/
-						/* ROM 0 is used when pitch shifting downward or less	*/
-						/* then 3 semitones upward.  Increasingly higher ROM	*/
-						/* numbers are used, typically in steps of 3 semitones,	*/
-						/* as upward pitch shifting is performed.		*/
-#define CCCA_INTERPROM_0	0x00000000	/* Select interpolation ROM 0				*/
-#define CCCA_INTERPROM_1	0x02000000	/* Select interpolation ROM 1				*/
-#define CCCA_INTERPROM_2	0x04000000	/* Select interpolation ROM 2				*/
-#define CCCA_INTERPROM_3	0x06000000	/* Select interpolation ROM 3				*/
-#define CCCA_INTERPROM_4	0x08000000	/* Select interpolation ROM 4				*/
-#define CCCA_INTERPROM_5	0x0a000000	/* Select interpolation ROM 5				*/
-#define CCCA_INTERPROM_6	0x0c000000	/* Select interpolation ROM 6				*/
-#define CCCA_INTERPROM_7	0x0e000000	/* Select interpolation ROM 7				*/
-#define CCCA_8BITSELECT		0x01000000	/* 1 = Sound memory for this channel uses 8-bit samples	*/
-#define CCCA_CURRADDR_MASK	0x00ffffff	/* Current address of the selected channel		*/
-#define CCCA_CURRADDR		0x18000008
-
-#define CCR			0x09		/* Cache control register				*/
-#define CCR_CACHEINVALIDSIZE	0x07190009
-#define CCR_CACHEINVALIDSIZE_MASK	0xfe000000	/* Number of invalid samples cache for this channel    	*/
-#define CCR_CACHELOOPFLAG	0x01000000	/* 1 = Cache has a loop service pending			*/
-#define CCR_INTERLEAVEDSAMPLES	0x00800000	/* 1 = A cache service will fetch interleaved samples	*/
-#define CCR_WORDSIZEDSAMPLES	0x00400000	/* 1 = A cache service will fetch word sized samples	*/
-#define CCR_READADDRESS		0x06100009
-#define CCR_READADDRESS_MASK	0x003f0000	/* Location of cache just beyond current cache service	*/
-#define CCR_LOOPINVALSIZE	0x0000fe00	/* Number of invalid samples in cache prior to loop	*/
-						/* NOTE: This is valid only if CACHELOOPFLAG is set	*/
-#define CCR_LOOPFLAG		0x00000100	/* Set for a single sample period when a loop occurs	*/
-#define CCR_CACHELOOPADDRHI	0x000000ff	/* DSL_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set	*/
-
-#define CLP			0x0a		/* Cache loop register (valid if CCR_CACHELOOPFLAG = 1) */
-						/* NOTE: This register is normally not used		*/
-#define CLP_CACHELOOPADDR	0x0000ffff	/* Cache loop address (DSL_LOOPSTARTADDR [0..15])	*/
-
-#define FXRT			0x0b		/* Effects send routing register			*/
-						/* NOTE: It is illegal to assign the same routing to	*/
-						/* two effects sends.					*/
-#define FXRT_CHANNELA		0x000f0000	/* Effects send bus number for channel's effects send A	*/
-#define FXRT_CHANNELB		0x00f00000	/* Effects send bus number for channel's effects send B	*/
-#define FXRT_CHANNELC		0x0f000000	/* Effects send bus number for channel's effects send C	*/
-#define FXRT_CHANNELD		0xf0000000	/* Effects send bus number for channel's effects send D	*/
-
-#define MAPA			0x0c		/* Cache map A						*/
-
-#define MAPB			0x0d		/* Cache map B						*/
-
-#define MAP_PTE_MASK		0xffffe000	/* The 19 MSBs of the PTE indexed by the PTI		*/
-#define MAP_PTI_MASK		0x00001fff	/* The 13 bit index to one of the 8192 PTE dwords      	*/
-
-#define ENVVOL			0x10		/* Volume envelope register				*/
-#define ENVVOL_MASK		0x0000ffff	/* Current value of volume envelope state variable	*/  
-						/* 0x8000-n == 666*n usec delay	       			*/
-
-#define ATKHLDV 		0x11		/* Volume envelope hold and attack register		*/
-#define ATKHLDV_PHASE0		0x00008000	/* 0 = Begin attack phase				*/
-#define ATKHLDV_HOLDTIME_MASK	0x00007f00	/* Envelope hold time (127-n == n*88.2msec)		*/
-#define ATKHLDV_ATTACKTIME_MASK	0x0000007f	/* Envelope attack time, log encoded			*/
-						/* 0 = infinite, 1 = 10.9msec, ... 0x7f = 5.5msec	*/
-
-#define DCYSUSV 		0x12		/* Volume envelope sustain and decay register		*/
-#define DCYSUSV_PHASE1_MASK	0x00008000	/* 0 = Begin attack phase, 1 = begin release phase	*/
-#define DCYSUSV_SUSTAINLEVEL_MASK 0x00007f00	/* 127 = full, 0 = off, 0.75dB increments		*/
-#define DCYSUSV_CHANNELENABLE_MASK 0x00000080	/* 1 = Inhibit envelope engine from writing values in	*/
-						/* this channel and from writing to pitch, filter and	*/
-						/* volume targets.					*/
-#define DCYSUSV_DECAYTIME_MASK	0x0000007f	/* Volume envelope decay time, log encoded     		*/
-						/* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec		*/
-
-#define LFOVAL1 		0x13		/* Modulation LFO value					*/
-#define LFOVAL_MASK		0x0000ffff	/* Current value of modulation LFO state variable	*/
-						/* 0x8000-n == 666*n usec delay				*/
-
-#define ENVVAL			0x14		/* Modulation envelope register				*/
-#define ENVVAL_MASK		0x0000ffff	/* Current value of modulation envelope state variable 	*/
-						/* 0x8000-n == 666*n usec delay				*/
-
-#define ATKHLDM			0x15		/* Modulation envelope hold and attack register		*/
-#define ATKHLDM_PHASE0		0x00008000	/* 0 = Begin attack phase				*/
-#define ATKHLDM_HOLDTIME	0x00007f00	/* Envelope hold time (127-n == n*42msec)		*/
-#define ATKHLDM_ATTACKTIME	0x0000007f	/* Envelope attack time, log encoded			*/
-						/* 0 = infinite, 1 = 11msec, ... 0x7f = 5.5msec		*/
-
-#define DCYSUSM			0x16		/* Modulation envelope decay and sustain register	*/
-#define DCYSUSM_PHASE1_MASK	0x00008000	/* 0 = Begin attack phase, 1 = begin release phase	*/
-#define DCYSUSM_SUSTAINLEVEL_MASK 0x00007f00	/* 127 = full, 0 = off, 0.75dB increments		*/
-#define DCYSUSM_DECAYTIME_MASK	0x0000007f	/* Envelope decay time, log encoded			*/
-						/* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec		*/
-
-#define LFOVAL2 		0x17		/* Vibrato LFO register					*/
-#define LFOVAL2_MASK		0x0000ffff	/* Current value of vibrato LFO state variable 		*/
-						/* 0x8000-n == 666*n usec delay				*/
-
-#define IP			0x18		/* Initial pitch register				*/
-#define IP_MASK			0x0000ffff	/* Exponential initial pitch shift			*/
-						/* 4 bits of octave, 12 bits of fractional octave	*/
-#define IP_UNITY		0x0000e000	/* Unity pitch shift					*/
-
-#define IFATN			0x19		/* Initial filter cutoff and attenuation register	*/
-#define IFATN_FILTERCUTOFF_MASK	0x0000ff00	/* Initial filter cutoff frequency in exponential units	*/
-						/* 6 most significant bits are semitones		*/
-						/* 2 least significant bits are fractions		*/
-#define IFATN_FILTERCUTOFF	0x08080019
-#define IFATN_ATTENUATION_MASK	0x000000ff	/* Initial attenuation in 0.375dB steps			*/
-#define IFATN_ATTENUATION	0x08000019
-
-
-#define PEFE			0x1a		/* Pitch envelope and filter envelope amount register	*/
-#define PEFE_PITCHAMOUNT_MASK	0x0000ff00	/* Pitch envlope amount					*/
-						/* Signed 2's complement, +/- one octave peak extremes	*/
-#define PEFE_PITCHAMOUNT	0x0808001a
-#define PEFE_FILTERAMOUNT_MASK	0x000000ff	/* Filter envlope amount				*/
-						/* Signed 2's complement, +/- six octaves peak extremes */
-#define PEFE_FILTERAMOUNT	0x0800001a
-#define FMMOD			0x1b		/* Vibrato/filter modulation from LFO register		*/
-#define FMMOD_MODVIBRATO	0x0000ff00	/* Vibrato LFO modulation depth				*/
-						/* Signed 2's complement, +/- one octave extremes	*/
-#define FMMOD_MOFILTER		0x000000ff	/* Filter LFO modulation depth				*/
-						/* Signed 2's complement, +/- three octave extremes	*/
-
-
-#define TREMFRQ 		0x1c		/* Tremolo amount and modulation LFO frequency register	*/
-#define TREMFRQ_DEPTH		0x0000ff00	/* Tremolo depth					*/
-						/* Signed 2's complement, with +/- 12dB extremes	*/
-#define TREMFRQ_FREQUENCY	0x000000ff	/* Tremolo LFO frequency				*/
-						/* ??Hz steps, maximum of ?? Hz.			*/
-
-#define FM2FRQ2 		0x1d		/* Vibrato amount and vibrato LFO frequency register	*/
-#define FM2FRQ2_DEPTH		0x0000ff00	/* Vibrato LFO vibrato depth				*/
-						/* Signed 2's complement, +/- one octave extremes	*/
-#define FM2FRQ2_FREQUENCY	0x000000ff	/* Vibrato LFO frequency				*/
-						/* 0.039Hz steps, maximum of 9.85 Hz.			*/
-
-#define TEMPENV 		0x1e		/* Tempory envelope register				*/
-#define TEMPENV_MASK		0x0000ffff	/* 16-bit value						*/
-						/* NOTE: All channels contain internal variables; do	*/
-						/* not write to these locations.			*/
-
-#define CD0			0x20		/* Cache data 0 register				*/
-#define CD1			0x21		/* Cache data 1 register				*/
-#define CD2			0x22		/* Cache data 2 register				*/
-#define CD3			0x23		/* Cache data 3 register				*/
-#define CD4			0x24		/* Cache data 4 register				*/
-#define CD5			0x25		/* Cache data 5 register				*/
-#define CD6			0x26		/* Cache data 6 register				*/
-#define CD7			0x27		/* Cache data 7 register				*/
-#define CD8			0x28		/* Cache data 8 register				*/
-#define CD9			0x29		/* Cache data 9 register				*/
-#define CDA			0x2a		/* Cache data A register				*/
-#define CDB			0x2b		/* Cache data B register				*/
-#define CDC			0x2c		/* Cache data C register				*/
-#define CDD			0x2d		/* Cache data D register				*/
-#define CDE			0x2e		/* Cache data E register				*/
-#define CDF			0x2f		/* Cache data F register				*/
-
-#define PTB			0x40		/* Page table base register				*/
-#define PTB_MASK		0xfffff000	/* Physical address of the page table in host memory	*/
-
-#define TCB			0x41		/* Tank cache base register    				*/
-#define TCB_MASK		0xfffff000	/* Physical address of the bottom of host based TRAM	*/
-
-#define ADCCR			0x42		/* ADC sample rate/stereo control register		*/
-#define ADCCR_RCHANENABLE	0x00000010	/* Enables right channel for writing to the host       	*/
-#define ADCCR_LCHANENABLE	0x00000008	/* Enables left channel for writing to the host		*/
-						/* NOTE: To guarantee phase coherency, both channels	*/
-						/* must be disabled prior to enabling both channels.	*/
-#define A_ADCCR_RCHANENABLE	0x00000020
-#define A_ADCCR_LCHANENABLE	0x00000010
-
-#define A_ADCCR_SAMPLERATE_MASK 0x0000000F      /* Audigy sample rate convertor output rate		*/
-#define ADCCR_SAMPLERATE_MASK	0x00000007	/* Sample rate convertor output rate			*/
-
-#define ADCCR_SAMPLERATE_48	0x00000000	/* 48kHz sample rate					*/
-#define ADCCR_SAMPLERATE_44	0x00000001	/* 44.1kHz sample rate					*/
-#define ADCCR_SAMPLERATE_32	0x00000002	/* 32kHz sample rate					*/
-#define ADCCR_SAMPLERATE_24	0x00000003	/* 24kHz sample rate					*/
-#define ADCCR_SAMPLERATE_22	0x00000004	/* 22.05kHz sample rate					*/
-#define ADCCR_SAMPLERATE_16	0x00000005	/* 16kHz sample rate					*/
-#define ADCCR_SAMPLERATE_11	0x00000006	/* 11.025kHz sample rate				*/
-#define ADCCR_SAMPLERATE_8	0x00000007	/* 8kHz sample rate					*/
-
-#define A_ADCCR_SAMPLERATE_12	0x00000006	/* 12kHz sample rate					*/
-#define A_ADCCR_SAMPLERATE_11	0x00000007	/* 11.025kHz sample rate				*/
-#define A_ADCCR_SAMPLERATE_8	0x00000008	/* 8kHz sample rate					*/
-
-#define FXWC			0x43		/* FX output write channels register			*/
-						/* When set, each bit enables the writing of the	*/
-						/* corresponding FX output channel (internal registers  */
-						/* 0x20-0x3f) into host memory. This mode of recording	*/
-						/* is 16bit, 48KHz only. All 32	channels can be enabled */
-						/* simultaneously.					*/
-#define TCBS			0x44		/* Tank cache buffer size register			*/
-#define TCBS_MASK		0x00000007	/* Tank cache buffer size field				*/
-#define TCBS_BUFFSIZE_16K	0x00000000
-#define TCBS_BUFFSIZE_32K	0x00000001
-#define TCBS_BUFFSIZE_64K	0x00000002
-#define TCBS_BUFFSIZE_128K	0x00000003
-#define TCBS_BUFFSIZE_256K	0x00000004
-#define TCBS_BUFFSIZE_512K	0x00000005
-#define TCBS_BUFFSIZE_1024K	0x00000006
-#define TCBS_BUFFSIZE_2048K	0x00000007
-
-#define MICBA			0x45		/* AC97 microphone buffer address register		*/
-#define MICBA_MASK		0xfffff000	/* 20 bit base address					*/
-
-#define ADCBA			0x46		/* ADC buffer address register				*/
-#define ADCBA_MASK		0xfffff000	/* 20 bit base address					*/
-
-#define FXBA			0x47		/* FX Buffer Address */
-#define FXBA_MASK		0xfffff000	/* 20 bit base address					*/
-
-#define MICBS			0x49		/* Microphone buffer size register			*/
-
-#define ADCBS			0x4a		/* ADC buffer size register				*/
-
-#define FXBS			0x4b		/* FX buffer size register				*/
-
-/* The following mask values define the size of the ADC, MIX and FX buffers in bytes */
-#define ADCBS_BUFSIZE_NONE	0x00000000
-#define ADCBS_BUFSIZE_384	0x00000001
-#define ADCBS_BUFSIZE_448	0x00000002
-#define ADCBS_BUFSIZE_512	0x00000003
-#define ADCBS_BUFSIZE_640	0x00000004
-#define ADCBS_BUFSIZE_768	0x00000005
-#define ADCBS_BUFSIZE_896	0x00000006
-#define ADCBS_BUFSIZE_1024	0x00000007
-#define ADCBS_BUFSIZE_1280	0x00000008
-#define ADCBS_BUFSIZE_1536	0x00000009
-#define ADCBS_BUFSIZE_1792	0x0000000a
-#define ADCBS_BUFSIZE_2048	0x0000000b
-#define ADCBS_BUFSIZE_2560	0x0000000c
-#define ADCBS_BUFSIZE_3072	0x0000000d
-#define ADCBS_BUFSIZE_3584	0x0000000e
-#define ADCBS_BUFSIZE_4096	0x0000000f
-#define ADCBS_BUFSIZE_5120	0x00000010
-#define ADCBS_BUFSIZE_6144	0x00000011
-#define ADCBS_BUFSIZE_7168	0x00000012
-#define ADCBS_BUFSIZE_8192	0x00000013
-#define ADCBS_BUFSIZE_10240	0x00000014
-#define ADCBS_BUFSIZE_12288	0x00000015
-#define ADCBS_BUFSIZE_14366	0x00000016
-#define ADCBS_BUFSIZE_16384	0x00000017
-#define ADCBS_BUFSIZE_20480	0x00000018
-#define ADCBS_BUFSIZE_24576	0x00000019
-#define ADCBS_BUFSIZE_28672	0x0000001a
-#define ADCBS_BUFSIZE_32768	0x0000001b
-#define ADCBS_BUFSIZE_40960	0x0000001c
-#define ADCBS_BUFSIZE_49152	0x0000001d
-#define ADCBS_BUFSIZE_57344	0x0000001e
-#define ADCBS_BUFSIZE_65536	0x0000001f
-
-
-#define CDCS			0x50		/* CD-ROM digital channel status register	*/
-
-#define GPSCS			0x51		/* General Purpose SPDIF channel status register*/
-
-#define DBG			0x52		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
-
-/* definitions for debug register - taken from the alsa drivers */
-#define DBG_ZC                  0x80000000      /* zero tram counter */
-#define DBG_SATURATION_OCCURED  0x02000000      /* saturation control */
-#define DBG_SATURATION_ADDR     0x01ff0000      /* saturation address */
-#define DBG_SINGLE_STEP         0x00008000      /* single step mode */
-#define DBG_STEP                0x00004000      /* start single step */
-#define DBG_CONDITION_CODE      0x00003e00      /* condition code */
-#define DBG_SINGLE_STEP_ADDR    0x000001ff      /* single step address */
-
-
-#define REG53			0x53		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
-
-#define A_DBG			 0x53
-#define A_DBG_SINGLE_STEP	 0x00020000	/* Set to zero to start dsp */
-#define A_DBG_ZC		 0x40000000	/* zero tram counter */
-#define A_DBG_STEP_ADDR		 0x000003ff
-#define A_DBG_SATURATION_OCCURED 0x20000000
-#define A_DBG_SATURATION_ADDR	 0x0ffc0000
-
-#define SPCS0			0x54		/* SPDIF output Channel Status 0 register	*/
-
-#define SPCS1			0x55		/* SPDIF output Channel Status 1 register	*/
-
-#define SPCS2			0x56		/* SPDIF output Channel Status 2 register	*/
-
-#define SPCS_CLKACCYMASK	0x30000000	/* Clock accuracy				*/
-#define SPCS_CLKACCY_1000PPM	0x00000000	/* 1000 parts per million			*/
-#define SPCS_CLKACCY_50PPM	0x10000000	/* 50 parts per million				*/
-#define SPCS_CLKACCY_VARIABLE	0x20000000	/* Variable accuracy				*/
-#define SPCS_SAMPLERATEMASK	0x0f000000	/* Sample rate					*/
-#define SPCS_SAMPLERATE_44	0x00000000	/* 44.1kHz sample rate				*/
-#define SPCS_SAMPLERATE_48	0x02000000	/* 48kHz sample rate				*/
-#define SPCS_SAMPLERATE_32	0x03000000	/* 32kHz sample rate				*/
-#define SPCS_CHANNELNUMMASK	0x00f00000	/* Channel number				*/
-#define SPCS_CHANNELNUM_UNSPEC	0x00000000	/* Unspecified channel number			*/
-#define SPCS_CHANNELNUM_LEFT	0x00100000	/* Left channel					*/
-#define SPCS_CHANNELNUM_RIGHT	0x00200000	/* Right channel				*/
-#define SPCS_SOURCENUMMASK	0x000f0000	/* Source number				*/
-#define SPCS_SOURCENUM_UNSPEC	0x00000000	/* Unspecified source number			*/
-#define SPCS_GENERATIONSTATUS	0x00008000	/* Originality flag (see IEC-958 spec)		*/
-#define SPCS_CATEGORYCODEMASK	0x00007f00	/* Category code (see IEC-958 spec)		*/
-#define SPCS_MODEMASK		0x000000c0	/* Mode (see IEC-958 spec)			*/
-#define SPCS_EMPHASISMASK	0x00000038	/* Emphasis					*/
-#define SPCS_EMPHASIS_NONE	0x00000000	/* No emphasis					*/
-#define SPCS_EMPHASIS_50_15	0x00000008	/* 50/15 usec 2 channel				*/
-#define SPCS_COPYRIGHT		0x00000004	/* Copyright asserted flag -- do not modify	*/
-#define SPCS_NOTAUDIODATA	0x00000002	/* 0 = Digital audio, 1 = not audio		*/
-#define SPCS_PROFESSIONAL	0x00000001	/* 0 = Consumer (IEC-958), 1 = pro (AES3-1992)	*/
-
-/* The 32-bit CLIx and SOLx registers all have one bit per channel control/status      		*/
-#define CLIEL			0x58		/* Channel loop interrupt enable low register	*/
-
-#define CLIEH			0x59		/* Channel loop interrupt enable high register	*/
-
-#define CLIPL			0x5a		/* Channel loop interrupt pending low register	*/
-
-#define CLIPH			0x5b		/* Channel loop interrupt pending high register	*/
-
-#define SOLEL			0x5c		/* Stop on loop enable low register		*/
-
-#define SOLEH			0x5d		/* Stop on loop enable high register		*/
-
-#define SPBYPASS		0x5e		/* SPDIF BYPASS mode register			*/
-#define SPBYPASS_ENABLE		0x00000001	/* Enable SPDIF bypass mode			*/
-
-#define AC97SLOT		0x5f		/* additional AC97 slots enable bits */
-#define AC97SLOT_CNTR		0x10		/* Center enable */
-#define AC97SLOT_LFE		0x20		/* LFE enable */
-
-#define CDSRCS			0x60		/* CD-ROM Sample Rate Converter status register	*/
-
-#define GPSRCS			0x61		/* General Purpose SPDIF sample rate cvt status */
-
-#define ZVSRCS			0x62		/* ZVideo sample rate converter status		*/
-						/* NOTE: This one has no SPDIFLOCKED field	*/
-						/* Assumes sample lock				*/
-
-/* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS.			*/
-#define SRCS_SPDIFLOCKED	0x02000000	/* SPDIF stream locked				*/
-#define SRCS_RATELOCKED		0x01000000	/* Sample rate locked				*/
-#define SRCS_ESTSAMPLERATE	0x0007ffff	/* Do not modify this field.			*/
-
-
-/* Note that these values can vary +/- by a small amount                                        */
-#define SRCS_SPDIFRATE_44	0x0003acd9
-#define SRCS_SPDIFRATE_48	0x00040000
-#define SRCS_SPDIFRATE_96	0x00080000
-
-#define MICIDX                  0x63            /* Microphone recording buffer index register   */
-#define MICIDX_MASK             0x0000ffff      /* 16-bit value                                 */
-#define MICIDX_IDX		0x10000063
-
-#define A_ADCIDX		0x63
-#define A_ADCIDX_IDX		0x10000063
-
-#define ADCIDX			0x64		/* ADC recording buffer index register		*/
-#define ADCIDX_MASK		0x0000ffff	/* 16 bit index field				*/
-#define ADCIDX_IDX		0x10000064
-
-#define FXIDX			0x65		/* FX recording buffer index register		*/
-#define FXIDX_MASK		0x0000ffff	/* 16-bit value					*/
-#define FXIDX_IDX		0x10000065
-
-/* This is the MPU port on the card (via the game port)						*/
-#define A_MUDATA1		0x70
-#define A_MUCMD1		0x71
-#define A_MUSTAT1		A_MUCMD1
-
-/* This is the MPU port on the Audigy Drive 							*/
-#define A_MUDATA2		0x72
-#define A_MUCMD2		0x73
-#define A_MUSTAT2		A_MUCMD2	
-
-/* The next two are the Audigy equivalent of FXWC						*/
-/* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously) 		*/
-/* Each bit selects a channel for recording */
-#define A_FXWC1			0x74            /* Selects 0x7f-0x60 for FX recording           */
-#define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording           */
-
-#define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
-#define A_SPDIF_48000		0x00000080
-#define A_SPDIF_44100		0x00000000
-#define A_SPDIF_96000		0x00000040
-
-#define A_FXRT2			0x7c
-#define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
-#define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
-#define A_FXRT_CHANNELG		0x003f0000	/* Effects send bus number for channel's effects send G	*/
-#define A_FXRT_CHANNELH		0x3f000000	/* Effects send bus number for channel's effects send H	*/
-
-#define A_SENDAMOUNTS		0x7d
-#define A_FXSENDAMOUNT_E_MASK	0xff000000
-#define A_FXSENDAMOUNT_F_MASK	0x00ff0000
-#define A_FXSENDAMOUNT_G_MASK	0x0000ff00
-#define A_FXSENDAMOUNT_H_MASK	0x000000ff
-
-/* The send amounts for this one are the same as used with the emu10k1 */
-#define A_FXRT1			0x7e
-#define A_FXRT_CHANNELA		0x0000003f
-#define A_FXRT_CHANNELB		0x00003f00
-#define A_FXRT_CHANNELC		0x003f0000
-#define A_FXRT_CHANNELD		0x3f000000
-
-
-/* Each FX general purpose register is 32 bits in length, all bits are used			*/
-#define FXGPREGBASE		0x100		/* FX general purpose registers base       	*/
-#define A_FXGPREGBASE		0x400		/* Audigy GPRs, 0x400 to 0x5ff			*/
-/* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is	*/
-/* decompressed back to 20 bits on a read.  There are a total of 160 locations, the last 32	*/
-/* locations are for external TRAM. 								*/
-#define TANKMEMDATAREGBASE	0x200		/* Tank memory data registers base     		*/
-#define TANKMEMDATAREG_MASK	0x000fffff	/* 20 bit tank audio data field			*/
-
-/* Combined address field and memory opcode or flag field.  160 locations, last 32 are external	*/
-#define TANKMEMADDRREGBASE	0x300		/* Tank memory address registers base		*/
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff	/* 20 bit tank address field			*/
-#define TANKMEMADDRREG_CLEAR	0x00800000	/* Clear tank memory				*/
-#define TANKMEMADDRREG_ALIGN	0x00400000	/* Align read or write relative to tank access	*/
-#define TANKMEMADDRREG_WRITE	0x00200000	/* Write to tank memory				*/
-#define TANKMEMADDRREG_READ	0x00100000	/* Read from tank memory			*/
-
-#define MICROCODEBASE		0x400		/* Microcode data base address			*/
-
-/* Each DSP microcode instruction is mapped into 2 doublewords 					*/
-/* NOTE: When writing, always write the LO doubleword first.  Reads can be in either order.	*/
-#define LOWORD_OPX_MASK		0x000ffc00	/* Instruction operand X			*/
-#define LOWORD_OPY_MASK		0x000003ff	/* Instruction operand Y			*/
-#define HIWORD_OPCODE_MASK	0x00f00000	/* Instruction opcode				*/
-#define HIWORD_RESULT_MASK	0x000ffc00	/* Instruction result				*/
-#define HIWORD_OPA_MASK		0x000003ff	/* Instruction operand A			*/
-
-
-/* Audigy Soundcard have a different instruction format */
-#define AUDIGY_CODEBASE		0x600
-#define A_LOWORD_OPY_MASK	0x000007ff		
-#define A_LOWORD_OPX_MASK	0x007ff000
-#define A_HIWORD_OPCODE_MASK	0x0f000000
-#define A_HIWORD_RESULT_MASK	0x007ff000
-#define A_HIWORD_OPA_MASK	0x000007ff
-
-
-#endif /* _8010_H */
diff --git a/sound/oss/emu10k1/Makefile b/sound/oss/emu10k1/Makefile
deleted file mode 100644
index b3af9cc..0000000
--- a/sound/oss/emu10k1/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Makefile for Creative Labs EMU10K1 
-#
-# 12 Apr 2000 Rui Sousa
-
-obj-$(CONFIG_SOUND_EMU10K1) += emu10k1.o
-
-emu10k1-objs := audio.o cardmi.o cardmo.o cardwi.o cardwo.o ecard.o \
-                efxmgr.o emuadxmg.o hwaccess.o irqmgr.o main.o midi.o \
-                mixer.o passthrough.o recmgr.o timer.o voicemgr.o
-
-ifdef DEBUG
-    EXTRA_CFLAGS += -DEMU10K1_DEBUG
-endif
-
-ifdef CONFIG_MIDI_EMU10K1
-    EXTRA_CFLAGS += -DEMU10K1_SEQUENCER
-endif
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
deleted file mode 100644
index e75ea21..0000000
--- a/sound/oss/emu10k1/audio.c
+++ /dev/null
@@ -1,1595 +0,0 @@
-/*
- **********************************************************************
- *     audio.c -- /dev/dsp interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999	    Alan Cox        cleaned up types/leaks
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-
-#include "hwaccess.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "recmgr.h"
-#include "irqmgr.h"
-#include "audio.h"
-#include "8010.h"
-
-static void calculate_ofrag(struct woinst *);
-static void calculate_ifrag(struct wiinst *);
-
-static void emu10k1_waveout_bh(unsigned long refdata);
-static void emu10k1_wavein_bh(unsigned long refdata);
-
-/* Audio file operations */
-static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	ssize_t ret = 0;
-	unsigned long flags;
-
-	DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count);
-
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-
-	spin_lock_irqsave(&wiinst->lock, flags);
-
-	if (wiinst->mmapped) {
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-		return -ENXIO;
-	}
-
-	if (wiinst->state == WAVE_STATE_CLOSED) {
-		calculate_ifrag(wiinst);
-
-		while (emu10k1_wavein_open(wave_dev) < 0) {
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-
-			if (file->f_flags & O_NONBLOCK)
-				return -EAGAIN;
-
-			interruptible_sleep_on(&wave_dev->card->open_wait);
-
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-		}
-	}
-
-	spin_unlock_irqrestore(&wiinst->lock, flags);
-
-	while (count > 0) {
-		u32 bytestocopy;
-
-		spin_lock_irqsave(&wiinst->lock, flags);
-
-		if (!(wiinst->state & WAVE_STATE_STARTED)
-		    && (wave_dev->enablebits & PCM_ENABLE_INPUT))
-			emu10k1_wavein_start(wave_dev);
-
-		emu10k1_wavein_update(wave_dev->card, wiinst);
-		emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-
-		DPD(3, "bytestocopy --> %d\n", bytestocopy);
-
-		if ((bytestocopy >= wiinst->buffer.fragment_size)
-		    || (bytestocopy >= count)) {
-			int rc;
-
-			bytestocopy = min_t(u32, bytestocopy, count);
-
-			rc = emu10k1_wavein_xferdata(wiinst,
-						     (u8 __user *)buffer,
-						     &bytestocopy);
-			if (rc)
-				return rc;
-
-			count -= bytestocopy;
-			buffer += bytestocopy;
-			ret += bytestocopy;
-		}
-
-		if (count > 0) {
-			if ((file->f_flags & O_NONBLOCK)
-			    || (!(wave_dev->enablebits & PCM_ENABLE_INPUT)))
-				return (ret ? ret : -EAGAIN);
-
-			interruptible_sleep_on(&wiinst->wait_queue);
-
-			if (signal_pending(current))
-				return (ret ? ret : -ERESTARTSYS);
-
-		}
-	}
-
-	DPD(3, "bytes copied -> %d\n", (u32) ret);
-
-	return ret;
-}
-
-static ssize_t emu10k1_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct woinst *woinst = wave_dev->woinst;
-	ssize_t ret;
-	unsigned long flags;
-
-	DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count);
-
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-
-	spin_lock_irqsave(&woinst->lock, flags);
-
-	if (woinst->mmapped) {
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		return -ENXIO;
-	}
-	// This is for emu10k1 revs less than 7, we need to go through tram
-	if (woinst->format.passthrough == 1) {
-		int r;
-		
-		woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2;
-		woinst->buffer.numfrags = PT_BLOCKCOUNT;
-		calculate_ofrag(woinst);
-		
-		r = emu10k1_pt_write(file, buffer, count);
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		return r;
-	}
-
-	if (woinst->state == WAVE_STATE_CLOSED) {
-		calculate_ofrag(woinst);
-
-		while (emu10k1_waveout_open(wave_dev) < 0) {
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			if (file->f_flags & O_NONBLOCK)
-				return -EAGAIN;
-
-			interruptible_sleep_on(&wave_dev->card->open_wait);
-
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-		}
-	}
-
-	spin_unlock_irqrestore(&woinst->lock, flags);
-
-	ret = 0;
-	if (count % woinst->format.bytespersample)
-                return -EINVAL;
-
-	count /= woinst->num_voices;
-
-	while (count > 0) {
-		u32 bytestocopy;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-		emu10k1_waveout_update(woinst);
-		emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-		spin_unlock_irqrestore(&woinst->lock, flags);
-
-		DPD(3, "bytestocopy --> %d\n", bytestocopy);
-
-		if ((bytestocopy >= woinst->buffer.fragment_size)
-		    || (bytestocopy >= count)) {
-
-			bytestocopy = min_t(u32, bytestocopy, count);
-
-			emu10k1_waveout_xferdata(woinst, (u8 __user *) buffer, &bytestocopy);
-
-			count -= bytestocopy;
-			buffer += bytestocopy * woinst->num_voices;
-			ret += bytestocopy * woinst->num_voices;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-			woinst->total_copied += bytestocopy;
-
-			if (!(woinst->state & WAVE_STATE_STARTED)
-			    && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
-			    && (woinst->total_copied >= woinst->buffer.fragment_size))
-				emu10k1_waveout_start(wave_dev);
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (count > 0) {
-			if ((file->f_flags & O_NONBLOCK)
-			    || (!(wave_dev->enablebits & PCM_ENABLE_OUTPUT)))
-				return (ret ? ret : -EAGAIN);
-
-			interruptible_sleep_on(&woinst->wait_queue);
-
-			if (signal_pending(current))
-				return (ret ? ret : -ERESTARTSYS);
-		}
-	}
-
-	DPD(3, "bytes copied -> %d\n", (u32) ret);
-
-	return ret;
-}
-
-static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct woinst *woinst = NULL;
-	struct wiinst *wiinst = NULL;
-	int val = 0;
-	u32 bytestocopy;
-	unsigned long flags;
-	int __user *p = (int __user *)arg;
-
-	DPF(4, "emu10k1_audio_ioctl()\n");
-
-	if (file->f_mode & FMODE_WRITE)
-		woinst = wave_dev->woinst;
-
-	if (file->f_mode & FMODE_READ)
-		wiinst = wave_dev->wiinst;
-
-	switch (cmd) {
-	case OSS_GETVERSION:
-		DPF(2, "OSS_GETVERSION:\n");
-		return put_user(SOUND_VERSION, p);
-
-	case SNDCTL_DSP_RESET:
-		DPF(2, "SNDCTL_DSP_RESET:\n");
-		wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;
-
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN) {
-				emu10k1_waveout_close(wave_dev);
-			}
-
-			woinst->mmapped = 0;
-			woinst->total_copied = 0;
-			woinst->total_played = 0;
-			woinst->blocks = 0;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_close(wave_dev);
-			}
-
-			wiinst->mmapped = 0;
-			wiinst->total_recorded = 0;
-			wiinst->blocks = 0;
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-
-		break;
-
-	case SNDCTL_DSP_SYNC:
-		DPF(2, "SNDCTL_DSP_SYNC:\n");
-
-		if (file->f_mode & FMODE_WRITE) {
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN) {
-
-				if (woinst->state & WAVE_STATE_STARTED)
-					while ((woinst->total_played < woinst->total_copied)
-					       && !signal_pending(current)) {
-						spin_unlock_irqrestore(&woinst->lock, flags);
-						interruptible_sleep_on(&woinst->wait_queue);
-						spin_lock_irqsave(&woinst->lock, flags);
-					}
-				emu10k1_waveout_close(wave_dev);
-			}
-
-			woinst->mmapped = 0;
-			woinst->total_copied = 0;
-			woinst->total_played = 0;
-			woinst->blocks = 0;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_close(wave_dev);
-			}
-
-			wiinst->mmapped = 0;
-			wiinst->total_recorded = 0;
-			wiinst->blocks = 0;
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-
-		break;
-
-	case SNDCTL_DSP_SETDUPLEX:
-		DPF(2, "SNDCTL_DSP_SETDUPLEX:\n");
-		break;
-
-	case SNDCTL_DSP_GETCAPS:
-		DPF(2, "SNDCTL_DSP_GETCAPS:\n");
-		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
-				DSP_CAP_TRIGGER | DSP_CAP_MMAP |
-				DSP_CAP_COPROC| DSP_CAP_MULTI, p);
-	case SNDCTL_DSP_SPEED:
-		DPF(2, "SNDCTL_DSP_SPEED:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, "val is %d\n", val);
-
-		if (val > 0) {
-			if (file->f_mode & FMODE_READ) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&wiinst->lock, flags);
-
-				format = wiinst->format;
-				format.samplingrate = val;
-
-				if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&wiinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = wiinst->format.samplingrate;
-
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-
-				DPD(2, "set recording sampling rate -> %d\n", val);
-			}
-
-			if (file->f_mode & FMODE_WRITE) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&woinst->lock, flags);
-
-				format = woinst->format;
-				format.samplingrate = val;
-
-				if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&woinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = woinst->format.samplingrate;
-
-				spin_unlock_irqrestore(&woinst->lock, flags);
-
-				DPD(2, "set playback sampling rate -> %d\n", val);
-			}
-
-			return put_user(val, p);
-		} else {
-			if (file->f_mode & FMODE_READ)
-				val = wiinst->format.samplingrate;
-			else if (file->f_mode & FMODE_WRITE)
-				val = woinst->format.samplingrate;
-
-			return put_user(val, p);
-		}
-		break;
-
-	case SNDCTL_DSP_STEREO:
-		DPF(2, "SNDCTL_DSP_STEREO:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, " val is %d\n", val);
-
-		if (file->f_mode & FMODE_READ) {
-			struct wave_format format;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			format = wiinst->format;
-			format.channels = val ? 2 : 1;
-
-			if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				return -EINVAL;
-			}
-
-			val = wiinst->format.channels - 1;
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-			DPD(2, "set recording stereo -> %d\n", val);
-		}
-
-		if (file->f_mode & FMODE_WRITE) {
-			struct wave_format format;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			format = woinst->format;
-			format.channels = val ? 2 : 1;
-
-			if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				return -EINVAL;
-			}
-
-			val = woinst->format.channels - 1;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			DPD(2, "set playback stereo -> %d\n", val);
-		}
-
-		return put_user(val, p);
-
-		break;
-
-	case SNDCTL_DSP_CHANNELS:
-		DPF(2, "SNDCTL_DSP_CHANNELS:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, " val is %d\n", val);
-
-		if (val > 0) {
-			if (file->f_mode & FMODE_READ) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&wiinst->lock, flags);
-
-				format = wiinst->format;
-				format.channels = val;
-
-				if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&wiinst->lock, flags);
-					return -EINVAL;
-				}
-				val = wiinst->format.channels;
-
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				DPD(2, "set recording number of channels -> %d\n", val);
-			}
-
-			if (file->f_mode & FMODE_WRITE) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&woinst->lock, flags);
-
-				format = woinst->format;
-				format.channels = val;
-
-				if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&woinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = woinst->format.channels;
-
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				DPD(2, "set playback number of channels -> %d\n", val);
-			}
-
-			return put_user(val, p);
-		} else {
-			if (file->f_mode & FMODE_READ)
-				val = wiinst->format.channels;
-			else if (file->f_mode & FMODE_WRITE)
-				val = woinst->format.channels;
-
-			return put_user(val, p);
-		}
-		break;
-
-	case SNDCTL_DSP_GETFMTS:
-		DPF(2, "SNDCTL_DSP_GETFMTS:\n");
-
-		if (file->f_mode & FMODE_READ)
-			val = AFMT_S16_LE;
-		else if (file->f_mode & FMODE_WRITE) {
-			val = AFMT_S16_LE | AFMT_U8;
-			if (emu10k1_find_control_gpr(&wave_dev->card->mgr,
-						     wave_dev->card->pt.patch_name, 
-						     wave_dev->card->pt.enable_gpr_name) >= 0)
-				val |= AFMT_AC3;
-		}
-		return put_user(val, p);
-
-	case SNDCTL_DSP_SETFMT:	/* Same as SNDCTL_DSP_SAMPLESIZE */
-		DPF(2, "SNDCTL_DSP_SETFMT:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, " val is %d\n", val);
-
-		if (val != AFMT_QUERY) {
-			if (file->f_mode & FMODE_READ) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&wiinst->lock, flags);
-
-				format = wiinst->format;
-				format.id = val;
-
-				if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&wiinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = wiinst->format.id;
-
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				DPD(2, "set recording format -> %d\n", val);
-			}
-
-			if (file->f_mode & FMODE_WRITE) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&woinst->lock, flags);
-
-				format = woinst->format;
-				format.id = val;
-
-				if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&woinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = woinst->format.id;
-
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				DPD(2, "set playback format -> %d\n", val);
-			}
-
-			return put_user(val, p);
-		} else {
-			if (file->f_mode & FMODE_READ)
-				val = wiinst->format.id;
-			else if (file->f_mode & FMODE_WRITE)
-				val = woinst->format.id;
-
-			return put_user(val, p);
-		}
-		break;
-
-	case SOUND_PCM_READ_BITS:
-
-		if (file->f_mode & FMODE_READ)
-			val = wiinst->format.bitsperchannel;
-		else if (file->f_mode & FMODE_WRITE)
-			val = woinst->format.bitsperchannel;
-
-		return put_user(val, p);
-
-	case SOUND_PCM_READ_RATE:
-
-		if (file->f_mode & FMODE_READ)
-			val = wiinst->format.samplingrate;
-		else if (file->f_mode & FMODE_WRITE)
-			val = woinst->format.samplingrate;
-
-		return put_user(val, p);
-
-	case SOUND_PCM_READ_CHANNELS:
-
-		if (file->f_mode & FMODE_READ)
-			val = wiinst->format.channels;
-		else if (file->f_mode & FMODE_WRITE)
-			val = woinst->format.channels;
-
-		return put_user(val, p);
-
-	case SOUND_PCM_WRITE_FILTER:
-		DPF(2, "SOUND_PCM_WRITE_FILTER: not implemented\n");
-		break;
-
-	case SOUND_PCM_READ_FILTER:
-		DPF(2, "SOUND_PCM_READ_FILTER: not implemented\n");
-		break;
-
-	case SNDCTL_DSP_SETSYNCRO:
-		DPF(2, "SNDCTL_DSP_SETSYNCRO: not implemented\n");
-		break;
-
-	case SNDCTL_DSP_GETTRIGGER:
-		DPF(2, "SNDCTL_DSP_GETTRIGGER:\n");
-
-		if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT))
-			val |= PCM_ENABLE_OUTPUT;
-
-		if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT))
-			val |= PCM_ENABLE_INPUT;
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_SETTRIGGER:
-		DPF(2, "SNDCTL_DSP_SETTRIGGER:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (val & PCM_ENABLE_OUTPUT) {
-				wave_dev->enablebits |= PCM_ENABLE_OUTPUT;
-				if (woinst->state & WAVE_STATE_OPEN)
-					emu10k1_waveout_start(wave_dev);
-			} else {
-				wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT;
-				if (woinst->state & WAVE_STATE_STARTED)
-					emu10k1_waveout_stop(wave_dev);
-			}
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (val & PCM_ENABLE_INPUT) {
-				wave_dev->enablebits |= PCM_ENABLE_INPUT;
-				if (wiinst->state & WAVE_STATE_OPEN)
-					emu10k1_wavein_start(wave_dev);
-			} else {
-				wave_dev->enablebits &= ~PCM_ENABLE_INPUT;
-				if (wiinst->state & WAVE_STATE_STARTED)
-					emu10k1_wavein_stop(wave_dev);
-			}
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-		break;
-
-	case SNDCTL_DSP_GETOSPACE:
-		{
-			audio_buf_info info;
-
-			DPF(4, "SNDCTL_DSP_GETOSPACE:\n");
-
-			if (!(file->f_mode & FMODE_WRITE))
-				return -EINVAL;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN) {
-				emu10k1_waveout_update(woinst);
-				emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-				info.bytes = bytestocopy;
-			} else {
-				calculate_ofrag(woinst);
-				info.bytes = woinst->buffer.size;
-			}
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			info.bytes *= woinst->num_voices;
-			info.fragsize = woinst->buffer.fragment_size * woinst->num_voices;
-			info.fragstotal = woinst->buffer.numfrags * woinst->num_voices;
-			info.fragments = info.bytes / info.fragsize;
-
-			if (copy_to_user(p, &info, sizeof(info)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_GETISPACE:
-		{
-			audio_buf_info info;
-
-			DPF(4, "SNDCTL_DSP_GETISPACE:\n");
-
-			if (!(file->f_mode & FMODE_READ))
-				return -EINVAL;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_update(wave_dev->card, wiinst);
-				emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-				info.bytes = bytestocopy;
-			} else {
-				calculate_ifrag(wiinst);
-				info.bytes = 0;
-			}
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-
-			info.fragstotal = wiinst->buffer.numfrags;
-			info.fragments = info.bytes / wiinst->buffer.fragment_size;
-			info.fragsize = wiinst->buffer.fragment_size;
-
-			if (copy_to_user(p, &info, sizeof(info)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_NONBLOCK:
-		DPF(2, "SNDCTL_DSP_NONBLOCK:\n");
-
-		file->f_flags |= O_NONBLOCK;
-		break;
-
-	case SNDCTL_DSP_GETODELAY:
-		DPF(4, "SNDCTL_DSP_GETODELAY:\n");
-
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-		if (woinst->state & WAVE_STATE_OPEN) {
-			emu10k1_waveout_update(woinst);
-			emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-			val = woinst->buffer.size - bytestocopy;
-		} else
-			val = 0;
-
-		val *= woinst->num_voices;
-		spin_unlock_irqrestore(&woinst->lock, flags);
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_GETIPTR:
-		{
-			count_info cinfo;
-
-			DPF(4, "SNDCTL_DSP_GETIPTR: \n");
-
-			if (!(file->f_mode & FMODE_READ))
-				return -EINVAL;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_update(wave_dev->card, wiinst);
-				cinfo.ptr = wiinst->buffer.hw_pos;
-				cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size;
-				cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks;
-				wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size;
-			} else {
-				cinfo.ptr = 0;
-				cinfo.bytes = 0;
-				cinfo.blocks = 0;
-			}
-
-			if (wiinst->mmapped)
-				wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size;
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-
-			if (copy_to_user(p, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_GETOPTR:
-		{
-			count_info cinfo;
-
-			DPF(4, "SNDCTL_DSP_GETOPTR:\n");
-
-			if (!(file->f_mode & FMODE_WRITE))
-				return -EINVAL;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN || 
-			    ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) {
-				int num_fragments;
-
-				if (woinst->format.passthrough == 1) {
-					emu10k1_pt_waveout_update(wave_dev);
-					cinfo.bytes = woinst->total_played;
-				} else {
-					emu10k1_waveout_update(woinst);
-					cinfo.bytes = woinst->total_played;
-				}
-
-				cinfo.ptr = woinst->buffer.hw_pos;
-				num_fragments = cinfo.bytes / woinst->buffer.fragment_size;
-				cinfo.blocks = num_fragments - woinst->blocks;
-				woinst->blocks = num_fragments;
-
-				cinfo.bytes *= woinst->num_voices;
-				cinfo.ptr *= woinst->num_voices;
-			} else {
-				cinfo.ptr = 0;
-				cinfo.bytes = 0;
-				cinfo.blocks = 0;
-			}
-
-			if (woinst->mmapped)
-				woinst->buffer.free_bytes %= woinst->buffer.fragment_size;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			if (copy_to_user(p, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_GETBLKSIZE:
-		DPF(2, "SNDCTL_DSP_GETBLKSIZE:\n");
-
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			calculate_ofrag(woinst);
-			val = woinst->buffer.fragment_size * woinst->num_voices;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			calculate_ifrag(wiinst);
-			val = wiinst->buffer.fragment_size;
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-
-		return put_user(val, p);
-
-		break;
-
-	case SNDCTL_DSP_POST:
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (!(woinst->state & WAVE_STATE_STARTED)
-			    && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
-			    && (woinst->total_copied > 0))
-				emu10k1_waveout_start(wave_dev);
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		break;
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		DPF(2, "SNDCTL_DSP_SUBDIVIDE: not implemented\n");
-		break;
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, "val is %#x\n", val);
-
-		if (val == 0)
-			return -EIO;
-
-		if (file->f_mode & FMODE_WRITE) {
-			/* digital pass-through fragment count and size are fixed values */
-			if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough == 1))
-				return -EINVAL;	/* too late to change */
-
-			woinst->buffer.ossfragshift = val & 0xffff;
-			woinst->buffer.numfrags = (val >> 16) & 0xffff;
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			if (wiinst->state & WAVE_STATE_OPEN)
-				return -EINVAL;	/* too late to change */
-
-			wiinst->buffer.ossfragshift = val & 0xffff;
-			wiinst->buffer.numfrags = (val >> 16) & 0xffff;
-		}
-
-		break;
-
-	case SNDCTL_COPR_LOAD:
-		{
-			copr_buffer *buf;
-			u32 i;
-
-			DPF(4, "SNDCTL_COPR_LOAD:\n");
-
-			buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL);
-			if (!buf)
-				return -ENOMEM;
-
-			if (copy_from_user(buf, p, sizeof(copr_buffer))) {
-				kfree (buf);
-				return -EFAULT;
-			}
-
-			if ((buf->command != CMD_READ) && (buf->command != CMD_WRITE)) {
-				kfree (buf);
-				return -EINVAL;
-			}
-
-			if (buf->command == CMD_WRITE) {
-				
-#ifdef DBGEMU
-				if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
-#else
-				if (((buf->offs < 0x100) || (buf->offs + buf->len > (wave_dev->card->is_audigy ? 0xe00 : 0x800)) || (buf->len > 1000)
-				) && !(
-					//any register allowed raw access to users goes here:
-					(buf->offs == DBG ||
-					  buf->offs == A_DBG)
-					&& (buf->len == 1))) {
-#endif		
-					kfree(buf);
-					return -EINVAL;
-				}
-			} else {
-				if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
-					kfree(buf);
-					return -EINVAL;
-				}
-			}			
-				
-			if (((unsigned)buf->flags) > 0x3f)
-				buf->flags = 0;
-
-			if (buf->command == CMD_READ) {
-				for (i = 0; i < buf->len; i++)
-					((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags);
-
-				if (copy_to_user(p, buf, sizeof(copr_buffer))) {
-					kfree(buf);
-					return -EFAULT;
-				}
-			} else {
-				for (i = 0; i < buf->len; i++)
-					sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]);
-			}
-
-			kfree (buf);
-			break;
-		}
-
-	default:		/* Default is unrecognized command */
-		DPD(2, "default: %#x\n", cmd);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type)
-{
-	struct emu10k1_wavedevice *wave_dev = vma->vm_private_data;
-	struct woinst *woinst = wave_dev->woinst;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	struct page *dmapage;
-	unsigned long pgoff;
-	int rd, wr;
-
-	DPF(3, "emu10k1_mm_nopage()\n");
-	DPD(3, "addr: %#lx\n", address);
-
-	if (address > vma->vm_end) {
-		DPF(1, "EXIT, returning NOPAGE_SIGBUS\n");
-		return NOPAGE_SIGBUS; /* Disallow mremap */
-	}
-
-	pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
-	if (woinst != NULL)
-		wr = woinst->mmapped;
-	else
-		wr = 0;
-
-	if (wiinst != NULL)
-		rd = wiinst->mmapped;
-	else
-		rd = 0;
-
-	/* if full-duplex (read+write) and we have two sets of bufs,
-	* then the playback buffers come first, sez soundcard.c */
-	if (wr) {
-		if (pgoff >= woinst->buffer.pages) {
-			pgoff -= woinst->buffer.pages;
-			dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
-		} else
-			dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]);
-	} else {
-		dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
-	}
-
-	get_page (dmapage);
-
-	DPD(3, "page: %#lx\n", (unsigned long) dmapage);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return dmapage;
-}
-
-static struct vm_operations_struct emu10k1_mm_ops = {
-	.nopage         = emu10k1_mm_nopage,
-};
-
-static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	unsigned long max_pages, n_pages, pgoffset;
-	struct woinst *woinst = NULL;
-	struct wiinst *wiinst = NULL;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_audio_mmap()\n");
-
-	max_pages = 0;
-	if (vma->vm_flags & VM_WRITE) {
-		woinst = wave_dev->woinst;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-
-		/* No m'mapping possible for multichannel */
-		if (woinst->num_voices > 1) {
-			spin_unlock_irqrestore(&woinst->lock, flags);
-                	return -EINVAL;
-		}
-
-		if (woinst->state == WAVE_STATE_CLOSED) {
-			calculate_ofrag(woinst);
-
-			if (emu10k1_waveout_open(wave_dev) < 0) {
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				ERROR();
-				return -EINVAL;
-			}
-		}
-
-		woinst->mmapped = 1;
-		max_pages += woinst->buffer.pages;
-		spin_unlock_irqrestore(&woinst->lock, flags);
-	}
-
-	if (vma->vm_flags & VM_READ) {
-		wiinst = wave_dev->wiinst;
-
-		spin_lock_irqsave(&wiinst->lock, flags);
-		if (wiinst->state == WAVE_STATE_CLOSED) {
-			calculate_ifrag(wiinst);
-
-			if (emu10k1_wavein_open(wave_dev) < 0) {
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				ERROR();
-				return -EINVAL;
-			}
-		}
-
-		wiinst->mmapped = 1;
-		max_pages += wiinst->buffer.pages;
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-	}
-
-	n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	pgoffset = vma->vm_pgoff;
-
-	DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset);
-	DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages);
-
-	if (pgoffset + n_pages > max_pages)
-		return -EINVAL;
-
-	vma->vm_flags |= VM_RESERVED;
-	vma->vm_ops = &emu10k1_mm_ops;
-	vma->vm_private_data = wave_dev;
-	return 0;
-}
-
-static int emu10k1_audio_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct emu10k1_card *card = NULL;
-	struct list_head *entry;
-	struct emu10k1_wavedevice *wave_dev;
-
-	DPF(2, "emu10k1_audio_open()\n");
-
-	/* Check for correct device to open */
-
-	list_for_each(entry, &emu10k1_devs) {
-		card = list_entry(entry, struct emu10k1_card, list);
-
-		if (!((card->audio_dev ^ minor) & ~0xf) || !((card->audio_dev1 ^ minor) & ~0xf))
-			goto match;
-	}
-
-	return -ENODEV;
-
-match:
-
-	wave_dev = kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
-
-	if (wave_dev == NULL) { 
-		ERROR();
-		return -ENOMEM;
-	}
-
-	wave_dev->card = card;
-	wave_dev->wiinst = NULL;
-	wave_dev->woinst = NULL;
-	wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;	/* Default */
-
-	if (file->f_mode & FMODE_READ) {
-		/* Recording */
-		struct wiinst *wiinst;
-
-		if ((wiinst = kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
-			ERROR();
-			kfree(wave_dev);
-			return -ENOMEM;
-		}
-
-		wiinst->recsrc = card->wavein.recsrc;
-                wiinst->fxwc = card->wavein.fxwc;
-
-		switch (wiinst->recsrc) {
-		case WAVERECORD_AC97:
-			wiinst->format.id = AFMT_S16_LE;
-			wiinst->format.samplingrate = 8000;
-			wiinst->format.bitsperchannel = 16;
-			wiinst->format.channels = 1;
-			break;
-		case WAVERECORD_MIC:
-			wiinst->format.id = AFMT_S16_LE;
-			wiinst->format.samplingrate = 8000;
-			wiinst->format.bitsperchannel = 16;
-			wiinst->format.channels = 1;
-			break;
-		case WAVERECORD_FX:
-			wiinst->format.id = AFMT_S16_LE;
-			wiinst->format.samplingrate = 48000;
-			wiinst->format.bitsperchannel = 16;
-			wiinst->format.channels = hweight32(wiinst->fxwc);
-			break;
-		default:
-			kfree(wave_dev);
-			kfree(wiinst);
-			BUG();
-			break;
-		}
-
-		wiinst->state = WAVE_STATE_CLOSED;
-
-		wiinst->buffer.ossfragshift = 0;
-		wiinst->buffer.fragment_size = 0;
-		wiinst->buffer.numfrags = 0;
-
-		init_waitqueue_head(&wiinst->wait_queue);
-
-		wiinst->mmapped = 0;
-		wiinst->total_recorded = 0;
-		wiinst->blocks = 0;
-		spin_lock_init(&wiinst->lock);
-		tasklet_init(&wiinst->timer.tasklet, emu10k1_wavein_bh, (unsigned long) wave_dev);
-		wave_dev->wiinst = wiinst;
-		emu10k1_wavein_setformat(wave_dev, &wiinst->format);
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		struct woinst *woinst;
-		int i;
-
-		if ((woinst = kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
-			ERROR();
-			kfree(wave_dev);
-			return -ENOMEM;
-		}
-
-		if (wave_dev->wiinst != NULL) {
-			woinst->format = wave_dev->wiinst->format;
-		} else {
-			woinst->format.id = AFMT_U8;
-			woinst->format.samplingrate = 8000;
-			woinst->format.bitsperchannel = 8;
-			woinst->format.channels = 1;
-		}
-
-		woinst->state = WAVE_STATE_CLOSED;
-
-		woinst->buffer.fragment_size = 0;
-		woinst->buffer.ossfragshift = 0;
-		woinst->buffer.numfrags = 0;
-		woinst->device = (card->audio_dev1 == minor);
-		woinst->timer.state = TIMER_STATE_UNINSTALLED;
-		woinst->num_voices = 1;
-		for (i = 0; i < WAVEOUT_MAXVOICES; i++) {
-			woinst->voice[i].usage = VOICE_USAGE_FREE;
-			woinst->voice[i].mem.emupageindex = -1;
-		}
-
-		init_waitqueue_head(&woinst->wait_queue);
-
-		woinst->mmapped = 0;
-		woinst->total_copied = 0;
-		woinst->total_played = 0;
-		woinst->blocks = 0;
-		spin_lock_init(&woinst->lock);
-		tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev);
-		wave_dev->woinst = woinst;
-		emu10k1_waveout_setformat(wave_dev, &woinst->format);
-	}
-
-	file->private_data = (void *) wave_dev;
-
-	return nonseekable_open(inode, file);
-}
-
-static int emu10k1_audio_release(struct inode *inode, struct file *file)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct emu10k1_card *card;
-	unsigned long flags;
-
-	card = wave_dev->card;
-
-	DPF(2, "emu10k1_audio_release()\n");
-
-	if (file->f_mode & FMODE_WRITE) {
-		struct woinst *woinst = wave_dev->woinst;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-		if(woinst->format.passthrough==2)
-			card->pt.state=PT_STATE_PLAYING;
-		if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){
-			spin_lock(&card->pt.lock);
-                        emu10k1_pt_stop(card);
-			spin_unlock(&card->pt.lock);
-		}
-		if (woinst->state & WAVE_STATE_OPEN) {
-			if (woinst->state & WAVE_STATE_STARTED) {
-				if (!(file->f_flags & O_NONBLOCK)) {
-					while (!signal_pending(current)
-					       && (woinst->total_played < woinst->total_copied)) {
-						DPF(4, "Buffer hasn't been totally played, sleep....\n");
-						spin_unlock_irqrestore(&woinst->lock, flags);
-						interruptible_sleep_on(&woinst->wait_queue);
-						spin_lock_irqsave(&woinst->lock, flags);
-					}
-				}
-			}
-			emu10k1_waveout_close(wave_dev);
-		}
-
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		/* remove the tasklet */
-		tasklet_kill(&woinst->timer.tasklet);
-		kfree(wave_dev->woinst);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		struct wiinst *wiinst = wave_dev->wiinst;
-
-		spin_lock_irqsave(&wiinst->lock, flags);
-
-		if (wiinst->state & WAVE_STATE_OPEN) {
-			emu10k1_wavein_close(wave_dev);
-		}
-
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-		tasklet_kill(&wiinst->timer.tasklet);
-		kfree(wave_dev->wiinst);
-	}
-
-	kfree(wave_dev);
-
-	if (waitqueue_active(&card->open_wait))
-		wake_up_interruptible(&card->open_wait);
-
-	return 0;
-}
-
-/* FIXME sort out poll() + mmap() */
-static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct woinst *woinst = wave_dev->woinst;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	unsigned int mask = 0;
-	u32 bytestocopy;
-	unsigned long flags;
-
-	DPF(4, "emu10k1_audio_poll()\n");
-
-	if (file->f_mode & FMODE_WRITE)
-		poll_wait(file, &woinst->wait_queue, wait);
-
-	if (file->f_mode & FMODE_READ)
-		poll_wait(file, &wiinst->wait_queue, wait);
-
-	if (file->f_mode & FMODE_WRITE) {
-		spin_lock_irqsave(&woinst->lock, flags);
-
-		if (woinst->state & WAVE_STATE_OPEN) {
-			emu10k1_waveout_update(woinst);
-			emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-
-			if (bytestocopy >= woinst->buffer.fragment_size)
-				mask |= POLLOUT | POLLWRNORM;
-		} else
-			mask |= POLLOUT | POLLWRNORM;
-
-		spin_unlock_irqrestore(&woinst->lock, flags);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		spin_lock_irqsave(&wiinst->lock, flags);
-
-		if (wiinst->state & WAVE_STATE_OPEN) {
-			emu10k1_wavein_update(wave_dev->card, wiinst);
-			emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-			if (bytestocopy >= wiinst->buffer.fragment_size)
-				mask |= POLLIN | POLLRDNORM;
-		}
-
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-	}
-
-	return mask;
-}
-
-static void calculate_ofrag(struct woinst *woinst)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	u32 fragsize;
-
-	if (buffer->fragment_size)
-		return;
-
-	if (!buffer->ossfragshift) {
-		fragsize = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1;
-
-		while (fragsize) {
-			fragsize >>= 1;
-			buffer->ossfragshift++;
-		}
-	}
-
-	if (buffer->ossfragshift < WAVEOUT_MINFRAGSHIFT)
-		buffer->ossfragshift = WAVEOUT_MINFRAGSHIFT;
-
-	buffer->fragment_size = 1 << buffer->ossfragshift;
-
-	while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE)
-		buffer->fragment_size >>= 1;
-
-	/* now we are sure that:
-	 (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS)
-	*/
-
-	if (!buffer->numfrags) {
-		u32 numfrags;
-
-		numfrags = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTBUFLEN) /
-			   (buffer->fragment_size * 1000) - 1;
-
-		buffer->numfrags = 1;
-
-		while (numfrags) {
-			numfrags >>= 1;
-			buffer->numfrags <<= 1;
-		}
-	}
-
-	if (buffer->numfrags < WAVEOUT_MINFRAGS)
-		buffer->numfrags = WAVEOUT_MINFRAGS;
-
-	if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE)
-		buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size;
-
-	if (buffer->numfrags < WAVEOUT_MINFRAGS)
-		BUG();
-
-	buffer->size = buffer->fragment_size * buffer->numfrags;
-	buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
-
-	DPD(2, " calculated playback fragment_size -> %d\n", buffer->fragment_size);
-	DPD(2, " calculated playback numfrags -> %d\n", buffer->numfrags);
-
-	return;
-}
-
-static void calculate_ifrag(struct wiinst *wiinst)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-	u32 fragsize, bufsize, size[4];
-	int i, j;
-
-	if (buffer->fragment_size)
-		return;
-
-	if (!buffer->ossfragshift) {
-		fragsize = (wiinst->format.bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1;
-
-		while (fragsize) {
-			fragsize >>= 1;
-			buffer->ossfragshift++;
-		}
-	}
-
-	if (buffer->ossfragshift < WAVEIN_MINFRAGSHIFT)
-		buffer->ossfragshift = WAVEIN_MINFRAGSHIFT;
-
-	buffer->fragment_size = 1 << buffer->ossfragshift;
-
-	while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE)
-		buffer->fragment_size >>= 1;
-
-	/* now we are sure that:
-	   (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS)
-        */
-
-
-	if (!buffer->numfrags)
-		buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
-
-	if (buffer->numfrags < WAVEIN_MINFRAGS)
-		buffer->numfrags = WAVEIN_MINFRAGS;
-
-	if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE)
-		buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size;
-
-	if (buffer->numfrags < WAVEIN_MINFRAGS)
-		BUG();
-
-	bufsize = buffer->fragment_size * buffer->numfrags;
-
-	/* the buffer size for recording is restricted to certain values, adjust it now */
-	if (bufsize >= 0x10000) {
-		buffer->size = 0x10000;
-		buffer->sizeregval = 0x1f;
-	} else {
-		buffer->size = 0;
-		size[0] = 384;
-		size[1] = 448;
-		size[2] = 512;
-		size[3] = 640;
-
-		for (i = 0; i < 8; i++)
-			for (j = 0; j < 4; j++)
-				if (bufsize >= size[j]) {
-					buffer->size = size[j];
-					size[j] *= 2;
-					buffer->sizeregval = i * 4 + j + 1;
-				} else
-					goto exitloop;
-	      exitloop:
-		if (buffer->size == 0) {
-			buffer->size = 384;
-			buffer->sizeregval = 0x01;
-		}
-	}
-
-	/* adjust the fragment size so that buffer size is an integer multiple */
-	while (buffer->size % buffer->fragment_size)
-		buffer->fragment_size >>= 1;
-
-	buffer->numfrags = buffer->size / buffer->fragment_size;
-	buffer->pages =  buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
-
-	DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size);
-	DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags);
-	DPD(2, " buffer size register -> %#04x\n", buffer->sizeregval);
-
-	return;
-}
-
-static void emu10k1_wavein_bh(unsigned long refdata)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	u32 bytestocopy;
-	unsigned long flags;
-
-	if (!wiinst)
-		return;
-
-	spin_lock_irqsave(&wiinst->lock, flags);
-
-	if (!(wiinst->state & WAVE_STATE_STARTED)) {
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-		return;
-	}
-
-	emu10k1_wavein_update(wave_dev->card, wiinst);
-	emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-	spin_unlock_irqrestore(&wiinst->lock, flags);
-
-	if (bytestocopy >= wiinst->buffer.fragment_size) {
-	 	if (waitqueue_active(&wiinst->wait_queue))
-			wake_up_interruptible(&wiinst->wait_queue);
-	} else
-		DPD(3, "Not enough transfer size, %d\n", bytestocopy);
-
-	return;
-}
-
-static void emu10k1_waveout_bh(unsigned long refdata)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
-	struct woinst *woinst = wave_dev->woinst;
-	u32 bytestocopy;
-	unsigned long flags;
-
-	if (!woinst)
-		return;
-
-	spin_lock_irqsave(&woinst->lock, flags);
-
-	if (!(woinst->state & WAVE_STATE_STARTED)) {
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		return;
-	}
-
-	emu10k1_waveout_update(woinst);
-	emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-
-	if (woinst->buffer.fill_silence) {
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		emu10k1_waveout_fillsilence(woinst);
-	} else
-		spin_unlock_irqrestore(&woinst->lock, flags);
-
-	if (bytestocopy >= woinst->buffer.fragment_size) {
-		if (waitqueue_active(&woinst->wait_queue))
-			wake_up_interruptible(&woinst->wait_queue);
-	} else
-		DPD(3, "Not enough transfer size -> %d\n", bytestocopy);
-
-	return;
-}
-
-const struct file_operations emu10k1_audio_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= emu10k1_audio_read,
-	.write		= emu10k1_audio_write,
-	.poll		= emu10k1_audio_poll,
-	.ioctl		= emu10k1_audio_ioctl,
-	.mmap		= emu10k1_audio_mmap,
-	.open		= emu10k1_audio_open,
-	.release	= emu10k1_audio_release,
-};
diff --git a/sound/oss/emu10k1/audio.h b/sound/oss/emu10k1/audio.h
deleted file mode 100644
index 26ee81b..0000000
--- a/sound/oss/emu10k1/audio.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- **********************************************************************
- *     audio.c -- /dev/dsp interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999	    Alan Cox        cleaned up types/leaks
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _AUDIO_H
-#define _AUDIO_H
-
-struct emu10k1_wavedevice
-{
-        struct emu10k1_card *card;
-        struct wiinst *wiinst;
-        struct woinst *woinst;
-        u16 enablebits;
-};
-
-#endif /* _AUDIO_H */
diff --git a/sound/oss/emu10k1/cardmi.c b/sound/oss/emu10k1/cardmi.c
deleted file mode 100644
index 57674f8..0000000
--- a/sound/oss/emu10k1/cardmi.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- **********************************************************************
- *     sblive_mi.c - MIDI UART input HAL for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        clean up
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmi.h"
-#include "irqmgr.h"
-
-
-static int emu10k1_mpuin_callback(struct emu10k1_mpuin *card_mpuin, u32 msg, unsigned long data, u32 bytesvalid);
-
-static int sblive_miStateInit(struct emu10k1_mpuin *);
-static int sblive_miStateEntry(struct emu10k1_mpuin *, u8);
-static int sblive_miStateParse(struct emu10k1_mpuin *, u8);
-static int sblive_miState3Byte(struct emu10k1_mpuin *, u8);
-static int sblive_miState3ByteKey(struct emu10k1_mpuin *, u8);
-static int sblive_miState3ByteVel(struct emu10k1_mpuin *, u8);
-static int sblive_miState2Byte(struct emu10k1_mpuin *, u8);
-static int sblive_miState2ByteKey(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon2(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3Key(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysExNorm(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysReal(struct emu10k1_mpuin *, u8);
-
-
-static struct {
-	int (*Fn) (struct emu10k1_mpuin *, u8);
-} midistatefn[] = {
-
-	{
-	sblive_miStateParse}, {
-	sblive_miState3Byte},	/* 0x8n, 0x9n, 0xAn, 0xBn, 0xEn */
-	{
-	sblive_miState3ByteKey},	/* Byte 1                       */
-	{
-	sblive_miState3ByteVel},	/* Byte 2                       */
-	{
-	sblive_miState2Byte},	/* 0xCn, 0xDn                   */
-	{
-	sblive_miState2ByteKey},	/* Byte 1                       */
-	{
-	sblive_miStateSysCommon2},	/* 0xF1 , 0xF3                  */
-	{
-	sblive_miStateSysCommon2Key},	/* 0xF1 , 0xF3, Byte 1          */
-	{
-	sblive_miStateSysCommon3},	/* 0xF2                         */
-	{
-	sblive_miStateSysCommon3Key},	/* 0xF2 , Byte 1                */
-	{
-	sblive_miStateSysCommon3Vel},	/* 0xF2 , Byte 2                */
-	{
-	sblive_miStateSysExNorm},	/* 0xF0, 0xF7, Normal mode      */
-	{
-	sblive_miStateSysReal}	/* 0xF4 - 0xF6 ,0xF8 - 0xFF     */
-};
-
-
-/* Installs the IRQ handler for the MPU in port                 */
-
-/* and initialize parameters                                    */
-
-int emu10k1_mpuin_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
-	DPF(2, "emu10k1_mpuin_open\n");
-
-	if (!(card_mpuin->status & FLAGS_AVAILABLE))
-		return -1;
-
-	/* Copy open info and mark channel as in use */
-	card_mpuin->openinfo = *openinfo;
-	card_mpuin->status &= ~FLAGS_AVAILABLE;	/* clear */
-	card_mpuin->status |= FLAGS_READY;	/* set */
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;	/* clear */
-	card_mpuin->firstmidiq = NULL;
-	card_mpuin->lastmidiq = NULL;
-	card_mpuin->qhead = 0;
-	card_mpuin->qtail = 0;
-
-	sblive_miStateInit(card_mpuin);
-
-	emu10k1_mpu_reset(card);
-	emu10k1_mpu_acquire(card);
-
-	return 0;
-}
-
-int emu10k1_mpuin_close(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
-	DPF(2, "emu10k1_mpuin_close()\n");
-
-	/* Check if there are pending input SysEx buffers */
-	if (card_mpuin->firstmidiq != NULL) {
-		ERROR();
-		return -1;
-	}
-
-	/* Disable RX interrupt */
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
-	emu10k1_mpu_release(card);
-
-	card_mpuin->status |= FLAGS_AVAILABLE;	/* set */
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;	/* clear */
-
-	return 0;
-}
-
-/* Adds MIDI buffer to local queue list                         */
-
-int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *card_mpuin, struct midi_hdr *midihdr)
-{
-	struct midi_queue *midiq;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuin_add_buffer()\n");
-
-	/* Update MIDI buffer flags */
-	midihdr->flags |= MIDIBUF_INQUEUE;	/* set */
-	midihdr->flags &= ~MIDIBUF_DONE;	/* clear */
-
-	if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
-		/* Message lost */
-		return -1;
-	}
-
-	midiq->next = NULL;
-	midiq->qtype = 1;
-	midiq->length = midihdr->bufferlength;
-	midiq->sizeLeft = midihdr->bufferlength;
-	midiq->midibyte = midihdr->data;
-	midiq->refdata = (unsigned long) midihdr;
-
-	spin_lock_irqsave(&card_mpuin->lock, flags);
-
-	if (card_mpuin->firstmidiq == NULL) {
-		card_mpuin->firstmidiq = midiq;
-		card_mpuin->lastmidiq = midiq;
-	} else {
-		(card_mpuin->lastmidiq)->next = midiq;
-		card_mpuin->lastmidiq = midiq;
-	}
-
-	spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-	return 0;
-}
-
-/* First set the Time Stamp if MIDI IN has not started.         */
-
-/* Then enable RX Irq.                                          */
-
-int emu10k1_mpuin_start(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-	u8 dummy;
-
-	DPF(2, "emu10k1_mpuin_start()\n");
-
-	/* Set timestamp if not set */
-	if (card_mpuin->status & FLAGS_MIDM_STARTED) {
-		DPF(2, "Time Stamp not changed\n");
-	} else {
-		while (!emu10k1_mpu_read_data(card, &dummy));
-
-		card_mpuin->status |= FLAGS_MIDM_STARTED;	/* set */
-
-		/* Set new time stamp */
-		card_mpuin->timestart = (jiffies * 1000) / HZ;
-		DPD(2, "New Time Stamp = %d\n", card_mpuin->timestart);
-
-		card_mpuin->qhead = 0;
-		card_mpuin->qtail = 0;
-
-		emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-	}
-
-	return 0;
-}
-
-/* Disable the RX Irq.  If a partial recorded buffer            */
-
-/* exist, send it up to IMIDI level.                            */
-
-int emu10k1_mpuin_stop(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-	struct midi_queue *midiq;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuin_stop()\n");
-
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;	/* clear */
-
-	if (card_mpuin->firstmidiq) {
-		spin_lock_irqsave(&card_mpuin->lock, flags);
-
-		midiq = card_mpuin->firstmidiq;
-		if (midiq != NULL) {
-			if (midiq->sizeLeft == midiq->length)
-				midiq = NULL;
-			else {
-				card_mpuin->firstmidiq = midiq->next;
-				if (card_mpuin->firstmidiq == NULL)
-					card_mpuin->lastmidiq = NULL;
-			}
-		}
-
-		spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-		if (midiq) {
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-			kfree(midiq);
-		}
-	}
-
-	return 0;
-}
-
-/* Disable the RX Irq.  If any buffer                           */
-
-/* exist, send it up to IMIDI level.                            */
-int emu10k1_mpuin_reset(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-	struct midi_queue *midiq;
-
-	DPF(2, "emu10k1_mpuin_reset()\n");
-
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
-	while (card_mpuin->firstmidiq) {
-		midiq = card_mpuin->firstmidiq;
-		card_mpuin->firstmidiq = midiq->next;
-
-		if (midiq->sizeLeft == midiq->length)
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-		else
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-
-		kfree(midiq);
-	}
-
-	card_mpuin->lastmidiq = NULL;
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;
-
-	return 0;
-}
-
-/* Passes the message with the data back to the client          */
-
-/* via IRQ & DPC callbacks to Ring 3                            */
-static int emu10k1_mpuin_callback(struct emu10k1_mpuin *card_mpuin, u32 msg, unsigned long data, u32 bytesvalid)
-{
-	unsigned long timein;
-	struct midi_queue *midiq;
-	unsigned long callback_msg[3];
-	struct midi_hdr *midihdr;
-
-	/* Called during ISR. The data & code touched are:
-	 * 1. card_mpuin
-	 * 2. The function to be called
-	 */
-
-	timein = card_mpuin->timein;
-	if (card_mpuin->timestart <= timein)
-		callback_msg[0] = timein - card_mpuin->timestart;
-	else
-		callback_msg[0] = (~0x0L - card_mpuin->timestart) + timein;
-
-	if (msg == ICARDMIDI_INDATA || msg == ICARDMIDI_INDATAERROR) {
-		callback_msg[1] = data;
-		callback_msg[2] = bytesvalid;
-		DPD(2, "emu10k1_mpuin_callback: midimsg = %#lx\n", data);
-	} else {
-		midiq = (struct midi_queue *) data;
-		midihdr = (struct midi_hdr *) midiq->refdata;
-
-		callback_msg[1] = midiq->length - midiq->sizeLeft;
-		callback_msg[2] = midiq->refdata;
-		midihdr->flags &= ~MIDIBUF_INQUEUE;
-		midihdr->flags |= MIDIBUF_DONE;
-
-		midihdr->bytesrecorded = midiq->length - midiq->sizeLeft;
-	}
-
-	/* Notify client that Sysex buffer has been sent */
-	emu10k1_midi_callback(msg, card_mpuin->openinfo.refdata, callback_msg);
-
-	return 0;
-}
-
-void emu10k1_mpuin_bh(unsigned long refdata)
-{
-	u8 data;
-	unsigned idx;
-	struct emu10k1_mpuin *card_mpuin = (struct emu10k1_mpuin *) refdata;
-	unsigned long flags;
-
-	while (card_mpuin->qhead != card_mpuin->qtail) {
-		spin_lock_irqsave(&card_mpuin->lock, flags);
-		idx = card_mpuin->qhead;
-		data = card_mpuin->midiq[idx].data;
-		card_mpuin->timein = card_mpuin->midiq[idx].timein;
-		idx = (idx + 1) % MIDIIN_MAX_BUFFER_SIZE;
-		card_mpuin->qhead = idx;
-		spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-		sblive_miStateEntry(card_mpuin, data);
-	}
-
-	return;
-}
-
-/* IRQ callback handler routine for the MPU in port */
-
-int emu10k1_mpuin_irqhandler(struct emu10k1_card *card)
-{
-	unsigned idx;
-	unsigned count;
-	u8 MPUIvalue;
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
-	/* IRQ service routine. The data and code touched are:
-	 * 1. card_mpuin
-	 */
-
-	count = 0;
-	idx = card_mpuin->qtail;
-
-	while (1) {
-		if (emu10k1_mpu_read_data(card, &MPUIvalue) < 0) {
-			break;
-		} else {
-			++count;
-			card_mpuin->midiq[idx].data = MPUIvalue;
-			card_mpuin->midiq[idx].timein = (jiffies * 1000) / HZ;
-			idx = (idx + 1) % MIDIIN_MAX_BUFFER_SIZE;
-		}
-	}
-
-	if (count) {
-		card_mpuin->qtail = idx;
-
-		tasklet_hi_schedule(&card_mpuin->tasklet);
-	}
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*   Supporting functions for Midi-In Interpretation State Machine           */
-
-/*****************************************************************************/
-
-/* FIXME: This should be a macro */
-static int sblive_miStateInit(struct emu10k1_mpuin *card_mpuin)
-{
-	card_mpuin->status = 0;	/* For MIDI running status */
-	card_mpuin->fstatus = 0;	/* For 0xFn status only */
-	card_mpuin->curstate = STIN_PARSE;
-	card_mpuin->laststate = STIN_PARSE;
-	card_mpuin->data = 0;
-	card_mpuin->timestart = 0;
-	card_mpuin->timein = 0;
-
-	return 0;
-}
-
-/* FIXME: This should be a macro */
-static int sblive_miStateEntry(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	return midistatefn[card_mpuin->curstate].Fn(card_mpuin, data);
-}
-
-static int sblive_miStateParse(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	switch (data & 0xf0) {
-	case 0x80:
-	case 0x90:
-	case 0xA0:
-	case 0xB0:
-	case 0xE0:
-		card_mpuin->curstate = STIN_3BYTE;
-		break;
-
-	case 0xC0:
-	case 0xD0:
-		card_mpuin->curstate = STIN_2BYTE;
-		break;
-
-	case 0xF0:
-		/* System messages do not affect the previous running status! */
-		switch (data & 0x0f) {
-		case 0x0:
-			card_mpuin->laststate = card_mpuin->curstate;
-			card_mpuin->curstate = STIN_SYS_EX_NORM;
-
-			if (card_mpuin->firstmidiq) {
-				struct midi_queue *midiq;
-
-				midiq = card_mpuin->firstmidiq;
-				*midiq->midibyte = data;
-				--midiq->sizeLeft;
-				++midiq->midibyte;
-			}
-
-			return CTSTATUS_NEXT_BYTE;
-
-		case 0x7:
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, 0xf7, 0);
-			return -1;
-
-		case 0x2:
-			card_mpuin->laststate = card_mpuin->curstate;
-			card_mpuin->curstate = STIN_SYS_COMMON_3;
-			break;
-
-		case 0x1:
-		case 0x3:
-			card_mpuin->laststate = card_mpuin->curstate;
-			card_mpuin->curstate = STIN_SYS_COMMON_2;
-			break;
-
-		default:
-			/* includes 0xF4 - 0xF6, 0xF8 - 0xFF */
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-		}
-
-		break;
-
-	default:
-		DPF(2, "BUG: default case hit\n");
-		return -1;
-	}
-
-	return midistatefn[card_mpuin->curstate].Fn(card_mpuin, data);
-}
-
-static int sblive_miState3Byte(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	u8 temp = data & 0xf0;
-
-	if (temp < 0x80) {
-		return midistatefn[STIN_3BYTE_KEY].Fn(card_mpuin, data);
-	} else if (temp <= 0xe0 && temp != 0xc0 && temp != 0xd0) {
-		card_mpuin->status = data;
-		card_mpuin->curstate = STIN_3BYTE_KEY;
-
-		return CTSTATUS_NEXT_BYTE;
-	}
-
-	return midistatefn[STIN_PARSE].Fn(card_mpuin, data);
-}
-
-static int sblive_miState3ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = STIN_PARSE;
-		tmp = ((unsigned long) data) << 8;
-		tmp |= (unsigned long) card_mpuin->status;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->data = data;
-	card_mpuin->curstate = STIN_3BYTE_VEL;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miState3ByteVel(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 2 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = STIN_PARSE;
-		tmp = ((unsigned long) data) << 8;
-		tmp |= card_mpuin->data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->status;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = STIN_3BYTE;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->status;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
-
-	return 0;
-}
-
-static int sblive_miState2Byte(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	u8 temp = data & 0xf0;
-
-	if ((temp == 0xc0) || (temp == 0xd0)) {
-		card_mpuin->status = data;
-		card_mpuin->curstate = STIN_2BYTE_KEY;
-
-		return CTSTATUS_NEXT_BYTE;
-	}
-
-	if (temp < 0x80)
-		return midistatefn[STIN_2BYTE_KEY].Fn(card_mpuin, data);
-
-	return midistatefn[STIN_PARSE].Fn(card_mpuin, data);
-}
-
-static int sblive_miState2ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = STIN_PARSE;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->status;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = STIN_2BYTE;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->status;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
-
-	return 0;
-}
-
-static int sblive_miStateSysCommon2(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	card_mpuin->fstatus = data;
-	card_mpuin->curstate = STIN_SYS_COMMON_2_KEY;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->fstatus;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = card_mpuin->laststate;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->fstatus;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
-
-	return 0;
-}
-
-static int sblive_miStateSysCommon3(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	card_mpuin->fstatus = data;
-	card_mpuin->curstate = STIN_SYS_COMMON_3_KEY;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon3Key(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->fstatus;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->data = data;
-	card_mpuin->curstate = STIN_SYS_COMMON_3_VEL;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 2 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->fstatus;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = card_mpuin->laststate;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->fstatus;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
-
-	return 0;
-}
-
-static int sblive_miStateSysExNorm(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	unsigned long flags;
-
-	if ((data > 0x7f) && (data != 0xf7)) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid Data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-
-		if (card_mpuin->firstmidiq) {
-			struct midi_queue *midiq;
-
-			midiq = card_mpuin->firstmidiq;
-			*midiq->midibyte = data;
-			--midiq->sizeLeft;
-			++midiq->midibyte;
-
-			spin_lock_irqsave(&card_mpuin->lock, flags);
-
-			card_mpuin->firstmidiq = midiq->next;
-			if (card_mpuin->firstmidiq == NULL)
-				card_mpuin->lastmidiq = NULL;
-
-			spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-
-			kfree(midiq);
-		}
-
-		return -1;
-	}
-
-	if (card_mpuin->firstmidiq) {
-		struct midi_queue *midiq;
-
-		midiq = card_mpuin->firstmidiq;
-		*midiq->midibyte = data;
-		--midiq->sizeLeft;
-		++midiq->midibyte;
-	}
-
-	if (data == 0xf7) {
-		/* End of Sysex buffer */
-		/* Send down the buffer */
-
-		card_mpuin->curstate = card_mpuin->laststate;
-
-		if (card_mpuin->firstmidiq) {
-			struct midi_queue *midiq;
-
-			midiq = card_mpuin->firstmidiq;
-
-			spin_lock_irqsave(&card_mpuin->lock, flags);
-
-			card_mpuin->firstmidiq = midiq->next;
-			if (card_mpuin->firstmidiq == NULL)
-				card_mpuin->lastmidiq = NULL;
-
-			spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-
-			kfree(midiq);
-		}
-
-		return 0;
-	}
-
-	if (card_mpuin->firstmidiq) {
-		struct midi_queue *midiq;
-
-		midiq = card_mpuin->firstmidiq;
-
-		if (midiq->sizeLeft == 0) {
-			/* Special case */
-
-			spin_lock_irqsave(&card_mpuin->lock, flags);
-
-			card_mpuin->firstmidiq = midiq->next;
-			if (card_mpuin->firstmidiq == NULL)
-				card_mpuin->lastmidiq = NULL;
-
-			spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-
-			kfree(midiq);
-
-			return CTSTATUS_NEXT_BYTE;
-		}
-	}
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysReal(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, data, 1);
-
-	return CTSTATUS_NEXT_BYTE;
-}
diff --git a/sound/oss/emu10k1/cardmi.h b/sound/oss/emu10k1/cardmi.h
deleted file mode 100644
index d12c241..0000000
--- a/sound/oss/emu10k1/cardmi.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- **********************************************************************
- *     sblive_mi.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        cleaned up
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _CARDMI_H
-#define _CARDMI_H
-
-#include "icardmid.h"
-#include <linux/interrupt.h>
-
-typedef enum
-{
-	STIN_PARSE = 0,
-	STIN_3BYTE,                     /* 0x80, 0x90, 0xA0, 0xB0, 0xE0 */
-	STIN_3BYTE_KEY,                 /* Byte 1 */
-	STIN_3BYTE_VEL,                 /* Byte 1 */
-	STIN_2BYTE,                     /* 0xC0, 0xD0 */
-	STIN_2BYTE_KEY,                 /* Byte 1 */
-	STIN_SYS_COMMON_2,              /* 0xF1, 0xF3  */
-	STIN_SYS_COMMON_2_KEY,
-	STIN_SYS_COMMON_3,              /* 0xF2 */
-	STIN_SYS_COMMON_3_KEY,
-	STIN_SYS_COMMON_3_VEL,
-	STIN_SYS_EX_NORM,               /* 0xF0, Normal mode */
-	STIN_SYS_REAL
-} midi_in_state;
-
-
-/* flags for card MIDI in object */
-#define FLAGS_MIDM_STARTED          0x00001000      // Data has started to come in after Midm Start
-#define MIDIIN_MAX_BUFFER_SIZE      200             // Definition for struct emu10k1_mpuin
-
-struct midi_data
-{
-	u8 data;
-	u32 timein;
-};
-
-struct emu10k1_mpuin
-{
-	spinlock_t        lock;
-	struct midi_queue *firstmidiq;
-	struct midi_queue *lastmidiq;
-	unsigned          qhead, qtail;
-	struct midi_data  midiq[MIDIIN_MAX_BUFFER_SIZE];
-	struct tasklet_struct tasklet;
-	struct midi_openinfo    openinfo;
-
-	/* For MIDI state machine */
-	u8              status;        /* For MIDI running status */
-	u8              fstatus;       /* For 0xFn status only */
-	midi_in_state   curstate;
-	midi_in_state   laststate;
-	u32             timestart;
-	u32             timein;
-	u8              data;
-};
-
-int emu10k1_mpuin_open(struct emu10k1_card *, struct midi_openinfo *);
-int emu10k1_mpuin_close(struct emu10k1_card *);
-int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *, struct midi_hdr *);
-int emu10k1_mpuin_start(struct emu10k1_card *);
-int emu10k1_mpuin_stop(struct emu10k1_card *);
-int emu10k1_mpuin_reset(struct emu10k1_card *);
-
-int emu10k1_mpuin_irqhandler(struct emu10k1_card *);
-void emu10k1_mpuin_bh(unsigned long);
-
-#endif  /* _CARDMI_H */
diff --git a/sound/oss/emu10k1/cardmo.c b/sound/oss/emu10k1/cardmo.c
deleted file mode 100644
index a8cc75d..0000000
--- a/sound/oss/emu10k1/cardmo.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*     
- **********************************************************************
- *     cardmo.c - MIDI UART output HAL for emu10k1 driver 
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- *     November 2, 1999     Alan Cox        cleaned up
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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. 
- * 
- ********************************************************************** 
- */
-
-#include <linux/slab.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmo.h"
-#include "irqmgr.h"
-
-/* Installs the IRQ handler for the MPU out port               *
- * and initialize parameters                                    */
-
-int emu10k1_mpuout_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-
-	DPF(2, "emu10k1_mpuout_open()\n");
-
-	if (!(card_mpuout->status & FLAGS_AVAILABLE))
-		return -1;
-
-	/* Copy open info and mark channel as in use */
-	card_mpuout->intr = 0;
-	card_mpuout->openinfo = *openinfo;
-	card_mpuout->status &= ~FLAGS_AVAILABLE;
-	card_mpuout->laststatus = 0x80;
-	card_mpuout->firstmidiq = NULL;
-	card_mpuout->lastmidiq = NULL;
-
-	emu10k1_mpu_reset(card);
-	emu10k1_mpu_acquire(card);
-
-	return 0;
-}
-
-int emu10k1_mpuout_close(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-	struct midi_queue *midiq;
-	struct midi_hdr *midihdr;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuout_close()\n");
-
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
-	spin_lock_irqsave(&card_mpuout->lock, flags);
-
-	while (card_mpuout->firstmidiq != NULL) {
-		midiq = card_mpuout->firstmidiq;
-		midihdr = (struct midi_hdr *) midiq->refdata;
-
-		card_mpuout->firstmidiq = midiq->next;
-
-		kfree(midihdr->data);
-		kfree(midihdr);
-		kfree(midiq);
-	}
-
-	card_mpuout->lastmidiq = NULL;
-
-	emu10k1_mpu_release(card);
-
-	card_mpuout->status |= FLAGS_AVAILABLE;
-
-	spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
-	return 0;
-}
-
-/* If there isn't enough buffer space, reject Midi Buffer.     *
-* Otherwise, disable TX, create object to hold Midi            *
-*  uffer, update buffer flags and other parameters             *
-* before enabling TX again.                                    */
-
-int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihdr)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-	struct midi_queue *midiq;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuout_add_buffer()\n");
-
-	if (card_mpuout->state == CARDMIDIOUT_STATE_SUSPEND)
-		return 0;
-
-	midihdr->flags |= MIDIBUF_INQUEUE;
-	midihdr->flags &= ~MIDIBUF_DONE;
-
-	if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
-		/* Message lost */
-		return -1;
-	}
-
-	midiq->next = NULL;
-	midiq->qtype = 1;
-	midiq->length = midihdr->bufferlength;
-	midiq->sizeLeft = midihdr->bufferlength;
-	midiq->midibyte = midihdr->data;
-
-	midiq->refdata = (unsigned long) midihdr;
-
-	spin_lock_irqsave(&card_mpuout->lock, flags);
-
-	if (card_mpuout->firstmidiq == NULL) {
-		card_mpuout->firstmidiq = midiq;
-		card_mpuout->lastmidiq = midiq;
-	} else {
-		(card_mpuout->lastmidiq)->next = midiq;
-		card_mpuout->lastmidiq = midiq;
-	}
-
-	card_mpuout->intr = 0;
-
-	emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
-	spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
-	return 0;
-}
-
-void emu10k1_mpuout_bh(unsigned long refdata)
-{
-	struct emu10k1_card *card = (struct emu10k1_card *) refdata;
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-	int cByteSent = 0;
-	struct midi_queue *midiq;
-	struct midi_queue *doneq = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card_mpuout->lock, flags);
-
-	while (card_mpuout->firstmidiq != NULL) {
-		midiq = card_mpuout->firstmidiq;
-
-		while (cByteSent < 4 && midiq->sizeLeft) {
-			if (emu10k1_mpu_write_data(card, *midiq->midibyte) < 0) {
-				DPF(2, "emu10k1_mpuoutDpcCallback error!!\n");
-			} else {
-				++cByteSent;
-				--midiq->sizeLeft;
-				++midiq->midibyte;
-			}
-		}
-
-		if (midiq->sizeLeft == 0) {
-			if (doneq == NULL)
-				doneq = midiq;
-			card_mpuout->firstmidiq = midiq->next;
-		} else
-			break;
-	}
-
-	if (card_mpuout->firstmidiq == NULL)
-		card_mpuout->lastmidiq = NULL;
-
-	if (doneq != NULL) {
-		while (doneq != card_mpuout->firstmidiq) {
-			unsigned long callback_msg[3];
-
-			midiq = doneq;
-			doneq = midiq->next;
-
-			if (midiq->qtype) {
-				callback_msg[0] = 0;
-				callback_msg[1] = midiq->length;
-				callback_msg[2] = midiq->refdata;
-
-				emu10k1_midi_callback(ICARDMIDI_OUTLONGDATA, card_mpuout->openinfo.refdata, callback_msg);
-			} else if (((u8) midiq->refdata) < 0xF0 && ((u8) midiq->refdata) > 0x7F)
-				card_mpuout->laststatus = (u8) midiq->refdata;
-
-			kfree(midiq);
-		}
-	}
-
-	if ((card_mpuout->firstmidiq != NULL) || cByteSent) {
-		card_mpuout->intr = 0;
-		emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-	}
-
-	spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
-	return;
-}
-
-int emu10k1_mpuout_irqhandler(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-
-	DPF(4, "emu10k1_mpuout_irqhandler\n");
-
-	card_mpuout->intr = 1;
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
-	tasklet_hi_schedule(&card_mpuout->tasklet);
-
-	return 0;
-}
diff --git a/sound/oss/emu10k1/cardmo.h b/sound/oss/emu10k1/cardmo.h
deleted file mode 100644
index 7026eb3..0000000
--- a/sound/oss/emu10k1/cardmo.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- **********************************************************************
- *     cardmo.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox	    cleaned up
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _CARDMO_H
-#define _CARDMO_H
-
-#include "icardmid.h"
-#include <linux/interrupt.h>
-
-#define CARDMIDIOUT_STATE_DEFAULT    0x00000000
-#define CARDMIDIOUT_STATE_SUSPEND    0x00000001
-
-struct emu10k1_mpuout
-{
-	u32			status;
-	u32			state;
-	volatile int		intr;
-	struct midi_queue	*firstmidiq;
-	struct midi_queue	*lastmidiq;
-	u8			laststatus;
-	struct tasklet_struct 	tasklet;
-	spinlock_t		lock;
-	struct midi_openinfo	openinfo;
-};
-
-int emu10k1_mpuout_open(struct emu10k1_card *, struct midi_openinfo *);
-int emu10k1_mpuout_close(struct emu10k1_card *);
-int emu10k1_mpuout_add_buffer(struct emu10k1_card *, struct midi_hdr *);
-
-int emu10k1_mpuout_irqhandler(struct emu10k1_card *);
-void emu10k1_mpuout_bh(unsigned long);
-
-#endif  /* _CARDMO_H */
diff --git a/sound/oss/emu10k1/cardwi.c b/sound/oss/emu10k1/cardwi.c
deleted file mode 100644
index 060d1be..0000000
--- a/sound/oss/emu10k1/cardwi.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- **********************************************************************
- *     cardwi.c - PCM input HAL for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <linux/poll.h>
-#include "hwaccess.h"
-#include "timer.h"
-#include "recmgr.h"
-#include "audio.h"
-#include "cardwi.h"
-
-/**
- * query_format - returns a valid sound format
- *
- * This function will return a valid sound format as close
- * to the requested one as possible. 
- */
-static void query_format(int recsrc, struct wave_format *wave_fmt)
-{
-
-	switch (recsrc) {
-	case WAVERECORD_AC97:
-
-		if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
-			wave_fmt->channels = 2;
-
-		if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
-			wave_fmt->samplingrate = 0xBB80;
-		else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)
-			wave_fmt->samplingrate = 0xAC44;
-		else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)
-			wave_fmt->samplingrate = 0x7D00;
-		else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)
-			wave_fmt->samplingrate = 0x5DC0;
-		else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)
-			wave_fmt->samplingrate = 0x5622;
-		else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)
-			wave_fmt->samplingrate = 0x3E80;
-		else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)
-			wave_fmt->samplingrate = 0x2B11;
-		else
-			wave_fmt->samplingrate = 0x1F40;
-
-		switch (wave_fmt->id) {
-		case AFMT_S16_LE:
-			wave_fmt->bitsperchannel = 16;
-			break;
-		case AFMT_U8:
-			wave_fmt->bitsperchannel = 8;
-			break;
-		default:
-			wave_fmt->id = AFMT_S16_LE;
-			wave_fmt->bitsperchannel = 16;
-			break;
-		}
-
-		break;
-
-	/* these can't be changed from the original values */
-	case WAVERECORD_MIC:
-	case WAVERECORD_FX:
-		break;
-
-	default:
-		BUG();
-		break;
-	}
-
-	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
-	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-	wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
-}
-
-static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov,
-					    &buffer->dma_handle);
-	if (buffer->addr == NULL)
-		return -1;
-
-	return 0;
-}
-
-static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	if (buffer->addr != NULL)
-		pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,
-				    buffer->addr, buffer->dma_handle);
-}
-
-int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	struct wiinst **wiinst_tmp = NULL;
-	u16 delay;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_wavein_open()\n");
-
-	switch (wiinst->recsrc) {
-	case WAVERECORD_AC97:
-		wiinst_tmp = &card->wavein.ac97;
-		break;
-	case WAVERECORD_MIC:
-		wiinst_tmp = &card->wavein.mic;
-		break;
-	case WAVERECORD_FX:
-		wiinst_tmp = &card->wavein.fx;
-		break;
-	default:
-		BUG();
-		break;
-	}
-
-	spin_lock_irqsave(&card->lock, flags);
-	if (*wiinst_tmp != NULL) {
-		spin_unlock_irqrestore(&card->lock, flags);
-		return -1;
-	}
-
-	*wiinst_tmp = wiinst;
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	/* handle 8 bit recording */
-	if (wiinst->format.bytesperchannel == 1) {
-		if (wiinst->buffer.size > 0x8000) {
-			wiinst->buffer.size = 0x8000;
-			wiinst->buffer.sizeregval = 0x1f;
-		} else
-			wiinst->buffer.sizeregval += 4;
-
-		wiinst->buffer.cov = 2;
-	} else
-		wiinst->buffer.cov = 1;
-
-	if (alloc_buffer(card, &wiinst->buffer) < 0) {
-		ERROR();
-		return -1;
-	}
-
-	emu10k1_set_record_src(card, wiinst);
-
-	emu10k1_reset_record(card, &wiinst->buffer);
-
-	wiinst->buffer.hw_pos = 0;
-	wiinst->buffer.pos = 0;
-	wiinst->buffer.bytestocopy = 0;
-
-	delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
-
-	emu10k1_timer_install(card, &wiinst->timer, delay / 2);
-
-	wiinst->state = WAVE_STATE_OPEN;
-
-	return 0;
-}
-
-void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_wavein_close()\n");
-
-	emu10k1_wavein_stop(wave_dev);
-
-	emu10k1_timer_uninstall(card, &wiinst->timer);
-
-	free_buffer(card, &wiinst->buffer);
-
-	spin_lock_irqsave(&card->lock, flags);
-	switch (wave_dev->wiinst->recsrc) {
-	case WAVERECORD_AC97:
-		card->wavein.ac97 = NULL;
-		break;
-	case WAVERECORD_MIC:
-		card->wavein.mic = NULL;
-		break;
-	case WAVERECORD_FX:
-		card->wavein.fx = NULL;
-		break;
-	default:
-		BUG();
-		break;
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	wiinst->state = WAVE_STATE_CLOSED;
-}
-
-void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-
-	DPF(2, "emu10k1_wavein_start()\n");
-
-	emu10k1_start_record(card, &wiinst->buffer);
-	emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
-
-	wiinst->state |= WAVE_STATE_STARTED;
-}
-
-void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-
-	DPF(2, "emu10k1_wavein_stop()\n");
-
-	if (!(wiinst->state & WAVE_STATE_STARTED))
-		return;
-
-	emu10k1_timer_disable(card, &wiinst->timer);
-	emu10k1_stop_record(card, &wiinst->buffer);
-
-	wiinst->state &= ~WAVE_STATE_STARTED;
-}
-
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	u16 delay;
-
-	DPF(2, "emu10k1_wavein_setformat()\n");
-
-	if (wiinst->state & WAVE_STATE_STARTED)
-		return -1;
-
-	query_format(wiinst->recsrc, format);
-
-	if ((wiinst->format.samplingrate != format->samplingrate)
-	    || (wiinst->format.bitsperchannel != format->bitsperchannel)
-	    || (wiinst->format.channels != format->channels)) {
-
-		wiinst->format = *format;
-
-		if (wiinst->state == WAVE_STATE_CLOSED)
-			return 0;
-
-		wiinst->buffer.size *= wiinst->buffer.cov;
-
-		if (wiinst->format.bytesperchannel == 1) {
-			wiinst->buffer.cov = 2;
-			wiinst->buffer.size /= wiinst->buffer.cov;
-		} else
-			wiinst->buffer.cov = 1;
-
-		emu10k1_timer_uninstall(card, &wiinst->timer);
-
-		delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
-
-		emu10k1_timer_install(card, &wiinst->timer, delay / 2);
-	}
-
-	return 0;
-}
-
-void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-
-	*size = buffer->bytestocopy;
-
-	if (wiinst->mmapped)
-		return;
-
-	if (*size > buffer->size) {
-		*size = buffer->size;
-		buffer->pos = buffer->hw_pos;
-		buffer->bytestocopy = buffer->size;
-		DPF(1, "buffer overrun\n");
-	}
-}
-
-static int copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
-{
-	if (cov == 1) {
-		if (__copy_to_user(dst, src + str, len))
-			return -EFAULT;
-	} else {
-		u8 byte;
-		u32 i;
-
-		src += 1 + 2 * str;
-
-		for (i = 0; i < len; i++) {
-			byte = src[2 * i] ^ 0x80;
-			if (__copy_to_user(dst + i, &byte, 1))
-				return -EFAULT;
-		}
-	}
-
-	return 0;
-}
-
-int emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-	u32 sizetocopy, sizetocopy_now, start;
-	unsigned long flags;
-	int ret;
-
-	sizetocopy = min_t(u32, buffer->size, *size);
-	*size = sizetocopy;
-
-	if (!sizetocopy)
-		return 0;
-
-	spin_lock_irqsave(&wiinst->lock, flags);
-	start = buffer->pos;
-	buffer->pos += sizetocopy;
-	buffer->pos %= buffer->size;
-	buffer->bytestocopy -= sizetocopy;
-	sizetocopy_now = buffer->size - start;
-
-	spin_unlock_irqrestore(&wiinst->lock, flags);
-
-	if (sizetocopy > sizetocopy_now) {
-		sizetocopy -= sizetocopy_now;
-
-		ret = copy_block(data, buffer->addr, start, sizetocopy_now,
-				 buffer->cov);
-		if (ret == 0)
-			ret = copy_block(data + sizetocopy_now, buffer->addr, 0,
-					 sizetocopy, buffer->cov);
-	} else {
-		ret = copy_block(data, buffer->addr, start, sizetocopy,
-				 buffer->cov);
-	}
-
-	return ret;
-}
-
-void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
-{
-	u32 hw_pos;
-	u32 diff;
-
-	/* There is no actual start yet */
-	if (!(wiinst->state & WAVE_STATE_STARTED)) {
-		hw_pos = wiinst->buffer.hw_pos;
-	} else {
-		/* hw_pos in byte units */
-		hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;
-	}
-
-	diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
-	wiinst->total_recorded += diff;
-	wiinst->buffer.bytestocopy += diff;
-
-	wiinst->buffer.hw_pos = hw_pos;
-}
diff --git a/sound/oss/emu10k1/cardwi.h b/sound/oss/emu10k1/cardwi.h
deleted file mode 100644
index e82029b..0000000
--- a/sound/oss/emu10k1/cardwi.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- **********************************************************************
- *     cardwi.h -- header file for card wave input functions
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _CARDWI_H
-#define _CARDWI_H
-
-#include "icardwav.h"
-#include "audio.h"
-#include "timer.h"
-
-struct wavein_buffer {
-	u16 ossfragshift;
-        u32 fragment_size;
-        u32 numfrags;
-	u32 hw_pos;		/* hardware cursor position */
-	u32 pos;		/* software cursor position */
-	u32 bytestocopy;	/* bytes of recorded data available */
-	u32 size;
-	u32 pages;
-	u32 sizereg;
-	u32 sizeregval;
-        u32 addrreg;
-        u32 idxreg;
-        u32 adcctl;
-	void *addr;
-	u8 cov;
-	dma_addr_t dma_handle;	
-};
-
-struct wiinst
-{
-	u8 state;
-	struct emu_timer timer;
-	struct wave_format format;
-	struct wavein_buffer buffer;
-	wait_queue_head_t wait_queue;
-	u8 mmapped;
-	u32 total_recorded;	/* total bytes read() from device */
-	u32 blocks;
-	spinlock_t lock;
-	u8 recsrc;
-	u16 fxwc;
-};
-
-#define WAVEIN_MAXBUFSIZE	65536
-#define WAVEIN_MINBUFSIZE	368
-
-#define WAVEIN_DEFAULTFRAGLEN	100 
-#define WAVEIN_DEFAULTBUFLEN	1000
-
-#define WAVEIN_MINFRAGSHIFT	8 
-#define WAVEIN_MINFRAGS		2
-
-int emu10k1_wavein_open(struct emu10k1_wavedevice *);
-void emu10k1_wavein_close(struct emu10k1_wavedevice *);
-void emu10k1_wavein_start(struct emu10k1_wavedevice *);
-void emu10k1_wavein_stop(struct emu10k1_wavedevice *);
-void emu10k1_wavein_getxfersize(struct wiinst *, u32 *);
-int emu10k1_wavein_xferdata(struct wiinst *, u8 __user *, u32 *);
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *, struct wave_format *);
-void emu10k1_wavein_update(struct emu10k1_card *, struct wiinst *);
-
-
-#endif /* _CARDWI_H */
diff --git a/sound/oss/emu10k1/cardwo.c b/sound/oss/emu10k1/cardwo.c
deleted file mode 100644
index 54daca4..0000000
--- a/sound/oss/emu10k1/cardwo.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- **********************************************************************
- *     cardwo.c - PCM output HAL for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <linux/poll.h>
-#include "hwaccess.h"
-#include "8010.h"
-#include "voicemgr.h"
-#include "cardwo.h"
-#include "audio.h"
-
-static u32 samplerate_to_linearpitch(u32 samplingrate)
-{
-	samplingrate = (samplingrate << 8) / 375;
-	return (samplingrate >> 1) + (samplingrate & 1);
-}
-
-static void query_format(struct emu10k1_wavedevice *wave_dev, struct wave_format *wave_fmt)
-{
-	int i, j, do_passthrough = 0, is_ac3 = 0;
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-
-	if ((wave_fmt->channels > 2) && (wave_fmt->id != AFMT_S16_LE) && (wave_fmt->id != AFMT_U8))
-		wave_fmt->channels = 2;
-
-	if ((wave_fmt->channels < 1) || (wave_fmt->channels > WAVEOUT_MAXVOICES))
-		wave_fmt->channels = 2;
-
-	if (wave_fmt->channels == 2)
-		woinst->num_voices = 1;
-	else
-		woinst->num_voices = wave_fmt->channels;
-
-	if (wave_fmt->samplingrate >= 0x2ee00)
-		wave_fmt->samplingrate = 0x2ee00;
-
-	wave_fmt->passthrough = 0;
-	do_passthrough = is_ac3 = 0;
-
-	if (card->pt.selected)
-		do_passthrough = 1;
-
-	switch (wave_fmt->id) {
-	case AFMT_S16_LE:
-		wave_fmt->bitsperchannel = 16;
-		break;
-	case AFMT_U8:
-		wave_fmt->bitsperchannel = 8;
-		break;
-	case AFMT_AC3:
-		do_passthrough = 1;
-		is_ac3 = 1;
-		break;
-	default:
-		wave_fmt->id = AFMT_S16_LE;
-		wave_fmt->bitsperchannel = 16;
-		break;
-	}	
-	if (do_passthrough) {
-		/* currently only one waveout instance may use pass-through */
-		if (woinst->state != WAVE_STATE_CLOSED || 
-		    card->pt.state != PT_STATE_INACTIVE ||
-		    (wave_fmt->samplingrate != 48000 && !is_ac3)) {
-			DPF(2, "unable to set pass-through mode\n");
-		} else if (USE_PT_METHOD1) {
-			i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name);
-			j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name);
-			if (i < 0 || j < 0)
-				DPF(2, "unable to set pass-through mode\n");
-			else {
-				wave_fmt->samplingrate = 48000;
-				wave_fmt->channels = 2;
-				card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
-									    card->pt.pos_gpr_name);
-				wave_fmt->passthrough = 1;
-				card->pt.intr_gpr = i;
-				card->pt.enable_gpr = j;
-				card->pt.state = PT_STATE_INACTIVE;
-			
-				DPD(2, "is_ac3 is %d\n", is_ac3);
-				card->pt.ac3data = is_ac3;
-				wave_fmt->bitsperchannel = 16;
-			}
-		}else{
-			DPF(2, "Using Passthrough Method 2\n");
-			card->pt.enable_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
-								       card->pt.enable_gpr_name);
-			wave_fmt->passthrough = 2;
-			wave_fmt->bitsperchannel = 16;
-		}
-	}
-
-	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
-	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-
-	if (wave_fmt->channels == 2)
-		wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	else
-		wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;
-}
-
-static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum)
-{
-	struct emu_voice *voice = &woinst->voice[voicenum];
-
-	/* Allocate voices here, if no voices available, return error. */
-
-	voice->usage = VOICE_USAGE_PLAYBACK;
-
-	voice->flags = 0;
-
-	if (woinst->format.channels == 2)
-		voice->flags |= VOICE_FLAGS_STEREO;
-
-	if (woinst->format.bitsperchannel == 16)
-		voice->flags |= VOICE_FLAGS_16BIT;
-
-	if (emu10k1_voice_alloc(card, voice) < 0) {
-		voice->usage = VOICE_USAGE_FREE;
-		return -1;
-	}
-
-	/* Calculate pitch */
-	voice->initial_pitch = (u16) (srToPitch(woinst->format.samplingrate) >> 8);
-	voice->pitch_target = samplerate_to_linearpitch(woinst->format.samplingrate);
-
-	DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch);
-
-	voice->startloop = (voice->mem.emupageindex << 12) /
-	 woinst->format.bytespervoicesample;
-	voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;
-	voice->start = voice->startloop;
-
-	
-	voice->params[0].volume_target = 0xffff;
-	voice->params[0].initial_fc = 0xff;
-	voice->params[0].initial_attn = 0x00;
-	voice->params[0].byampl_env_sustain = 0x7f;
-	voice->params[0].byampl_env_decay = 0x7f;
-
-	
-	if (voice->flags & VOICE_FLAGS_STEREO) {
-		if (woinst->format.passthrough == 2) {
-			voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PT];
-			voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PT];
-			voice->params[0].send_dcba = 0xff;
-			voice->params[1].send_dcba = 0xff00;
-			voice->params[0].send_hgfe = voice->params[1].send_hgfe=0;
-		} else {
-			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_LEFT];
-			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_LEFT];
-			voice->params[1].send_dcba = card->waveout.send_dcba[SEND_RIGHT];
-			voice->params[1].send_hgfe = card->waveout.send_hgfe[SEND_RIGHT];
-
-			if (woinst->device) {
-				// /dev/dps1
-				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM1];
-				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
-			} else {
-				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM];
-				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
-			}
-		}
-		
-		voice->params[1].volume_target = 0xffff;
-		voice->params[1].initial_fc = 0xff;
-		voice->params[1].initial_attn = 0x00;
-		voice->params[1].byampl_env_sustain = 0x7f;
-		voice->params[1].byampl_env_decay = 0x7f;
-	} else {
-		if (woinst->num_voices > 1) {
-			// Multichannel pcm
-			voice->params[0].send_dcba=0xff;
-			voice->params[0].send_hgfe=0;
-			if (card->is_audigy) {
-				voice->params[0].send_routing = 0x3f3f3f00 + card->mchannel_fx + voicenum;
-				voice->params[0].send_routing2 = 0x3f3f3f3f;
-			} else {
-				voice->params[0].send_routing = 0xfff0 + card->mchannel_fx + voicenum;
-			}
-			
-		} else {
-			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_MONO];
-			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_MONO];
-
-			if (woinst->device) {
-				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM1];
-				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
-			} else {
-				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM];
-				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
-			}
-		}
-	}
-
-	DPD(2, "voice: startloop=%#x, endloop=%#x\n", voice->startloop, voice->endloop);
-
-	emu10k1_voice_playback_setup(voice);
-
-	return 0;
-}
-
-int emu10k1_waveout_open(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	struct waveout_buffer *buffer = &woinst->buffer;
-	unsigned int voicenum;
-	u16 delay;
-
-	DPF(2, "emu10k1_waveout_open()\n");
-
-	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-		if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 0) {
-			ERROR();
-			emu10k1_waveout_close(wave_dev);
-			return -1;
-		}
-
-		if (get_voice(card, woinst, voicenum) < 0) {
-			ERROR();
-			emu10k1_waveout_close(wave_dev);
-			return -1;
-		}
-	}
-
-	buffer->fill_silence = 0;
-	buffer->silence_bytes = 0;
-	buffer->silence_pos = 0;
-	buffer->hw_pos = 0;
-	buffer->free_bytes = woinst->buffer.size;
-
-	delay = (48000 * woinst->buffer.fragment_size) /
-		 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
-
-	emu10k1_timer_install(card, &woinst->timer, delay);
-
-	woinst->state = WAVE_STATE_OPEN;
-
-	return 0;
-}
-
-void emu10k1_waveout_close(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	unsigned int voicenum;
-
-	DPF(2, "emu10k1_waveout_close()\n");
-
-	emu10k1_waveout_stop(wave_dev);
-
-	emu10k1_timer_uninstall(card, &woinst->timer);
-
-	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-		emu10k1_voice_free(&woinst->voice[voicenum]);
-		emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem);
-	}
-
-	woinst->state = WAVE_STATE_CLOSED;
-}
-
-void emu10k1_waveout_start(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	struct pt_data *pt = &card->pt;
-
-	DPF(2, "emu10k1_waveout_start()\n");
-
-	if (woinst->format.passthrough == 2) {
-		emu10k1_pt_setup(wave_dev);
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 1);
-		pt->state = PT_STATE_PLAYING;
-	}
-
-	/* Actual start */
-	emu10k1_voices_start(woinst->voice, woinst->num_voices, woinst->total_played);
-
-	emu10k1_timer_enable(card, &woinst->timer);
-
-	woinst->state |= WAVE_STATE_STARTED;
-}
-
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	unsigned int voicenum;
-	u16 delay;
-
-	DPF(2, "emu10k1_waveout_setformat()\n");
-
-	if (woinst->state & WAVE_STATE_STARTED)
-		return -1;
-
-	query_format(wave_dev, format);
-
-	if (woinst->format.samplingrate != format->samplingrate ||
-	    woinst->format.channels != format->channels ||
-	    woinst->format.bitsperchannel != format->bitsperchannel) {
-
-		woinst->format = *format;
-
-		if (woinst->state == WAVE_STATE_CLOSED)
-			return 0;
-
-		emu10k1_timer_uninstall(card, &woinst->timer);
-
-		for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-			emu10k1_voice_free(&woinst->voice[voicenum]);
-
-			if (get_voice(card, woinst, voicenum) < 0) {
-				ERROR();
-				emu10k1_waveout_close(wave_dev);
-				return -1;
-			}
-		}
-
-		delay = (48000 * woinst->buffer.fragment_size) /
-			 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
-
-		emu10k1_timer_install(card, &woinst->timer, delay);
-	}
-
-	return 0;
-}
-
-void emu10k1_waveout_stop(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-
-	DPF(2, "emu10k1_waveout_stop()\n");
-
-	if (!(woinst->state & WAVE_STATE_STARTED))
-		return;
-
-	emu10k1_timer_disable(card, &woinst->timer);
-
-	/* Stop actual voices */
-	emu10k1_voices_stop(woinst->voice, woinst->num_voices);
-
-	emu10k1_waveout_update(woinst);
-
-	woinst->state &= ~WAVE_STATE_STARTED;
-}
-
-/**
- * emu10k1_waveout_getxfersize -
- *
- * gives the total free bytes on the voice buffer, including silence bytes
- * (basically: total_free_bytes = free_bytes + silence_bytes).
- *
- */
-void emu10k1_waveout_getxfersize(struct woinst *woinst, u32 *total_free_bytes)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	int pending_bytes;
-
-	if (woinst->mmapped) {
-		*total_free_bytes = buffer->free_bytes;
-		return;
-	}
-
-	pending_bytes = buffer->size - buffer->free_bytes;
-
-	buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size * 2) ? 1 : 0;
-
-	if (pending_bytes > (signed) buffer->silence_bytes) {
-		*total_free_bytes = (buffer->free_bytes + buffer->silence_bytes);
-	} else {
-		*total_free_bytes = buffer->size;
-		buffer->silence_bytes = pending_bytes;
-		if (pending_bytes < 0) {
-			buffer->silence_pos = buffer->hw_pos;
-			buffer->silence_bytes = 0;
-			buffer->free_bytes = buffer->size;
-			DPF(1, "buffer underrun\n");
-		}
-	}
-}
-
-/**
- * copy_block -
- *
- * copies a block of pcm data to a voice buffer.
- * Notice that the voice buffer is actually a set of disjointed memory pages.
- *
- */
-static void copy_block(void **dst, u32 str, u8 __user *src, u32 len)
-{
-	unsigned int pg;
-	unsigned int pgoff;
-	unsigned int k;
-
-	pg = str / PAGE_SIZE;
-	pgoff = str % PAGE_SIZE;
-
-	if (len > PAGE_SIZE - pgoff) {
-		k = PAGE_SIZE - pgoff;
-		if (__copy_from_user((u8 *)dst[pg] + pgoff, src, k))
-			return;
-		len -= k;
-		while (len > PAGE_SIZE) {
-			if (__copy_from_user(dst[++pg], src + k, PAGE_SIZE))
-				return;
-			k += PAGE_SIZE;
-			len -= PAGE_SIZE;
-		}
-		if (__copy_from_user(dst[++pg], src + k, len))
-			return;
-
-	} else
-		__copy_from_user((u8 *)dst[pg] + pgoff, src, len);
-}
-
-/**
- * copy_ilv_block -
- *
- * copies a block of pcm data containing n interleaved channels to n mono voice buffers.
- * Notice that the voice buffer is actually a set of disjointed memory pages.
- *
- */
-static void copy_ilv_block(struct woinst *woinst, u32 str, u8 __user *src, u32 len) 
-{
-        unsigned int pg;
-	unsigned int pgoff;
-	unsigned int voice_num;
-	struct emu_voice *voice = woinst->voice;
-
-	pg = str / PAGE_SIZE;
-	pgoff = str % PAGE_SIZE;
-
-	while (len) { 
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) {
-			if (__copy_from_user((u8 *)(voice[voice_num].mem.addr[pg]) + pgoff, src, woinst->format.bytespervoicesample))
-				return;
-			src += woinst->format.bytespervoicesample;
-		}
-
-		len -= woinst->format.bytespervoicesample;
-
-		pgoff += woinst->format.bytespervoicesample;
-		if (pgoff >= PAGE_SIZE) {
-			pgoff = 0;
-			pg++;
-		}
-	}
-}
-
-/**
- * fill_block -
- *
- * fills a set voice buffers with a block of a given sample.
- *
- */
-static void fill_block(struct woinst *woinst, u32 str, u8 data, u32 len)
-{
-	unsigned int pg;
-	unsigned int pgoff;
-	unsigned int voice_num;
-        struct emu_voice *voice = woinst->voice;
-	unsigned int  k;
-
-	pg = str / PAGE_SIZE;
-	pgoff = str % PAGE_SIZE;
-
-	if (len > PAGE_SIZE - pgoff) {
-		k = PAGE_SIZE - pgoff;
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, k);
-		len -= k;
-		while (len > PAGE_SIZE) {
-			pg++;
-			for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-				memset(voice[voice_num].mem.addr[pg], data, PAGE_SIZE);
-
-			len -= PAGE_SIZE;
-		}
-		pg++;
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset(voice[voice_num].mem.addr[pg], data, len);
-
-	} else {
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, len);
-	}
-}
-
-/**
- * emu10k1_waveout_xferdata -
- *
- * copies pcm data to the voice buffer. Silence samples
- * previously added to the buffer are overwritten.
- *
- */
-void emu10k1_waveout_xferdata(struct woinst *woinst, u8 __user *data, u32 *size)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	struct voice_mem *mem = &woinst->voice[0].mem;
-	u32 sizetocopy, sizetocopy_now, start;
-	unsigned long flags;
-
-	sizetocopy = min_t(u32, buffer->size, *size);
-	*size = sizetocopy;
-
-	if (!sizetocopy)
-		return;
-	
-	spin_lock_irqsave(&woinst->lock, flags);
-	start = (buffer->size + buffer->silence_pos - buffer->silence_bytes) % buffer->size;
-
-	if (sizetocopy > buffer->silence_bytes) {
-		buffer->silence_pos += sizetocopy - buffer->silence_bytes;
-		buffer->free_bytes -= sizetocopy - buffer->silence_bytes;
-		buffer->silence_bytes = 0;
-	} else
-		buffer->silence_bytes -= sizetocopy;
-
-	spin_unlock_irqrestore(&woinst->lock, flags);
-
-	sizetocopy_now = buffer->size - start;
-	if (sizetocopy > sizetocopy_now) {
-		sizetocopy -= sizetocopy_now;
-		if (woinst->num_voices > 1) {
-			copy_ilv_block(woinst, start, data, sizetocopy_now);
-			copy_ilv_block(woinst, 0, data + sizetocopy_now * woinst->num_voices, sizetocopy);
-		} else {
-			copy_block(mem->addr, start, data, sizetocopy_now);
-			copy_block(mem->addr, 0, data + sizetocopy_now, sizetocopy);
-		}
-	} else {
-		if (woinst->num_voices > 1)
-			copy_ilv_block(woinst, start, data, sizetocopy);
-		else
-			copy_block(mem->addr, start, data, sizetocopy);
-	}
-}
-
-/**
- * emu10k1_waveout_fillsilence -
- *
- * adds samples of silence to the voice buffer so that we
- * don't loop over stale pcm data.
- *
- */
-void emu10k1_waveout_fillsilence(struct woinst *woinst)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	u32 sizetocopy, sizetocopy_now, start;
-	u8 filldata;
-	unsigned long flags;
-
-	sizetocopy = buffer->fragment_size;
-
-	if (woinst->format.bitsperchannel == 16)
-		filldata = 0x00;
-	else
-		filldata = 0x80;
-
-	spin_lock_irqsave(&woinst->lock, flags);
-	buffer->silence_bytes += sizetocopy;
-	buffer->free_bytes -= sizetocopy;
-	buffer->silence_pos %= buffer->size;
-	start = buffer->silence_pos;
-	buffer->silence_pos += sizetocopy;
-	spin_unlock_irqrestore(&woinst->lock, flags);
-
-	sizetocopy_now = buffer->size - start;
-
-	if (sizetocopy > sizetocopy_now) {
-		sizetocopy -= sizetocopy_now;
-		fill_block(woinst, start, filldata, sizetocopy_now);
-		fill_block(woinst, 0, filldata, sizetocopy);
-	} else {
-		fill_block(woinst, start, filldata, sizetocopy);
-	}
-}
-
-/**
- * emu10k1_waveout_update -
- *
- * updates the position of the voice buffer hardware pointer (hw_pos)
- * and the number of free bytes on the buffer (free_bytes).
- * The free bytes _don't_ include silence bytes that may have been
- * added to the buffer.
- *
- */
-void emu10k1_waveout_update(struct woinst *woinst)
-{
-	u32 hw_pos;
-	u32 diff;
-
-	/* There is no actual start yet */
-	if (!(woinst->state & WAVE_STATE_STARTED)) {
-		hw_pos = woinst->buffer.hw_pos;
-	} else {
-		/* hw_pos in sample units */
-		hw_pos = sblive_readptr(woinst->voice[0].card, CCCA_CURRADDR, woinst->voice[0].num);
-
-		if(hw_pos < woinst->voice[0].start)
-			hw_pos += woinst->buffer.size / woinst->format.bytespervoicesample - woinst->voice[0].start;
-		else
-			hw_pos -= woinst->voice[0].start;
-
-		hw_pos *= woinst->format.bytespervoicesample;
-	}
-
-	diff = (woinst->buffer.size + hw_pos - woinst->buffer.hw_pos) % woinst->buffer.size;
-	woinst->total_played += diff;
-	woinst->buffer.free_bytes += diff;
-	woinst->buffer.hw_pos = hw_pos;
-}
diff --git a/sound/oss/emu10k1/cardwo.h b/sound/oss/emu10k1/cardwo.h
deleted file mode 100644
index 1dece88..0000000
--- a/sound/oss/emu10k1/cardwo.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*     
- **********************************************************************
- *     cardwo.h -- header file for card wave out functions
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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 _CARDWO_H
-#define _CARDWO_H
-
-#include "icardwav.h"
-#include "audio.h"
-#include "voicemgr.h"
-#include "timer.h"
-
-/* setting this to other than a power of two may break some applications */
-#define WAVEOUT_MAXBUFSIZE	MAXBUFSIZE
-
-#define WAVEOUT_DEFAULTFRAGLEN	20 /* Time to play a fragment in ms (latency) */
-#define WAVEOUT_DEFAULTBUFLEN	500 /* Time to play the entire buffer in ms */
-
-#define WAVEOUT_MINFRAGSHIFT	6 /* Minimum fragment size in bytes is 2^6 */
-#define WAVEOUT_MINFRAGS	3 /* _don't_ go bellow 3, it would break silence filling */
-#define WAVEOUT_MAXVOICES	6
-
-struct waveout_buffer {
-	u16 ossfragshift;
-	u32 numfrags;
-	u32 fragment_size;	/* in bytes units */
-	u32 size;		/* in bytes units */
-	u32 pages;		/* buffer size in page units*/
-	u32 silence_pos;	/* software cursor position (including silence bytes) */
-	u32 hw_pos;		/* hardware cursor position */
-	u32 free_bytes;		/* free bytes available on the buffer (not including silence bytes) */
-	u8 fill_silence;
-	u32 silence_bytes;      /* silence bytes on the buffer */
-};
-
-struct woinst 
-{
-	u8 state;
-	u8 num_voices;
-	struct emu_voice voice[WAVEOUT_MAXVOICES];
-	struct emu_timer timer;
-	struct wave_format format;
-	struct waveout_buffer buffer;
-	wait_queue_head_t wait_queue;
-	u8 mmapped;
-	u32 total_copied;	/* total number of bytes written() to the buffer (excluding silence) */
-	u32 total_played;	/* total number of bytes played including silence */
-	u32 blocks;
-	u8 device;
-	spinlock_t lock;
-};
-
-int emu10k1_waveout_open(struct emu10k1_wavedevice *);
-void emu10k1_waveout_close(struct emu10k1_wavedevice *);
-void emu10k1_waveout_start(struct emu10k1_wavedevice *);
-void emu10k1_waveout_stop(struct emu10k1_wavedevice *);
-void emu10k1_waveout_getxfersize(struct woinst*, u32 *);
-void emu10k1_waveout_xferdata(struct woinst*, u8 __user *, u32 *);
-void emu10k1_waveout_fillsilence(struct woinst*);
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice*, struct wave_format*);
-void emu10k1_waveout_update(struct woinst*);
-
-#endif /* _CARDWO_H */
diff --git a/sound/oss/emu10k1/ecard.c b/sound/oss/emu10k1/ecard.c
deleted file mode 100644
index 4ae635f..0000000
--- a/sound/oss/emu10k1/ecard.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*     
- **********************************************************************
- *     ecard.c - E-card initialization code
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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. 
- * 
- ********************************************************************** 
- */ 
-
-#include "ecard.h"
-#include "hwaccess.h"
-
-/* Private routines */
-static void ecard_setadcgain(struct emu10k1_card *, struct ecard_state *, u16);
-static void ecard_write(struct emu10k1_card *, u32);
-
-/**************************************************************************
- * @func Set the gain of the ECARD's CS3310 Trim/gain controller.  The
- * trim value consists of a 16bit value which is composed of two
- * 8 bit gain/trim values, one for the left channel and one for the
- * right channel.  The following table maps from the Gain/Attenuation
- * value in decibels into the corresponding bit pattern for a single
- * channel.
- */
-
-static void ecard_setadcgain(struct emu10k1_card *card, struct ecard_state *ecard, u16 gain)
-{
-	u32 currbit;
-	ecard->adc_gain = gain;
-
-	/* Enable writing to the TRIM registers */
-	ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
-
-	/* Do it again to insure that we meet hold time requirements */
-	ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
-
-	for (currbit = (1L << 15); currbit; currbit >>= 1) {
-
-		u32 value = ecard->control_bits & ~(EC_TRIM_CSN|EC_TRIM_SDATA);
-
-		if (gain & currbit)
-		      value |= EC_TRIM_SDATA;
-
-		/* Clock the bit */
-		ecard_write(card, value);
-		ecard_write(card, value | EC_TRIM_SCLK);
-		ecard_write(card, value);
-	}
-
-	ecard_write(card, ecard->control_bits);
-}
-
-/**************************************************************************
- * @func Clock bits into the Ecard's control latch.  The Ecard uses a
- *  control latch will is loaded bit-serially by toggling the Modem control
- *  lines from function 2 on the E8010.  This function hides these details
- *  and presents the illusion that we are actually writing to a distinct
- *  register.
- */
-static void ecard_write(struct emu10k1_card *card, u32 value)
-{
-	u16 count;
-	u32 data, hcvalue;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	hcvalue = inl(card->iobase + HCFG) & ~(HOOKN_BIT|HANDN_BIT|PULSEN_BIT);
-
-	outl(card->iobase + HCFG, hcvalue);
-
-	for (count = 0 ; count < EC_NUM_CONTROL_BITS; count++) {
-	
-		/* Set up the value */
-		data = ((value & 0x1) ? PULSEN_BIT : 0);
-		value >>= 1;
-
-		outl(card->iobase + HCFG, hcvalue | data);
-
-		/* Clock the shift register */
-		outl(card->iobase + HCFG, hcvalue | data | HANDN_BIT);
-		outl(card->iobase + HCFG, hcvalue | data);
-	}
-
-	/* Latch the bits */
-	outl(card->iobase + HCFG, hcvalue | HOOKN_BIT);
-	outl(card->iobase + HCFG, hcvalue);
-
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-void __devinit emu10k1_ecard_init(struct emu10k1_card *card)
-{
-	u32 hcvalue;
-	struct ecard_state ecard;
-
-	/* Set up the initial settings */
-	ecard.mux0_setting = EC_DEFAULT_SPDIF0_SEL;
-	ecard.mux1_setting = EC_DEFAULT_SPDIF1_SEL;
-	ecard.mux2_setting = 0;
-	ecard.adc_gain = EC_DEFAULT_ADC_GAIN;
-	ecard.control_bits = EC_RAW_RUN_MODE | 
-                             EC_SPDIF0_SELECT(ecard.mux0_setting) |
-			     EC_SPDIF1_SELECT(ecard.mux1_setting);
-
-
-	/* Step 0: Set the codec type in the hardware control register 
-	 * and enable audio output */
-	hcvalue = emu10k1_readfn0(card, HCFG);
-	emu10k1_writefn0(card, HCFG, hcvalue | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S);
-
-	/* Step 1: Turn off the led and deassert TRIM_CS */
-	ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
-
-	/* Step 2: Calibrate the ADC and DAC */
-	ecard_write(card, EC_DACCAL | EC_LEDN | EC_TRIM_CSN);
-
-	/* Step 3: Wait for awhile; FIXME: Is this correct? */
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ);
-
-	/* Step 4: Switch off the DAC and ADC calibration.  Note
-	 * That ADC_CAL is actually an inverted signal, so we assert
-	 * it here to stop calibration.  */
-	ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
-
-	/* Step 4: Switch into run mode */
-	ecard_write(card, ecard.control_bits);
-
-	/* Step 5: Set the analog input gain */
-	ecard_setadcgain(card, &ecard, ecard.adc_gain);
-}
-
-
diff --git a/sound/oss/emu10k1/ecard.h b/sound/oss/emu10k1/ecard.h
deleted file mode 100644
index 67aead1..0000000
--- a/sound/oss/emu10k1/ecard.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*     
- **********************************************************************
- *     ecard.h
- *     Copyright 1999, 2000 Creative Labs, 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 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 _ECARD_H
-#define _ECARD_H
-
-#include "8010.h"
-#include "hwaccess.h"
-#include <linux/init.h>
-
-/* In A1 Silicon, these bits are in the HC register */
-#define HOOKN_BIT   (1L << 12)
-#define HANDN_BIT   (1L << 11)
-#define PULSEN_BIT  (1L << 10)
-
-#define EC_GDI1 (1 << 13)
-#define EC_GDI0 (1 << 14)
-
-#define EC_NUM_CONTROL_BITS 20
-
-#define EC_AC3_DATA_SELN  0x0001L
-#define EC_EE_DATA_SEL    0x0002L
-#define EC_EE_CNTRL_SELN  0x0004L
-#define EC_EECLK          0x0008L
-#define EC_EECS           0x0010L
-#define EC_EESDO          0x0020L
-#define EC_TRIM_CSN	  0x0040L
-#define EC_TRIM_SCLK	  0x0080L
-#define EC_TRIM_SDATA	  0x0100L
-#define EC_TRIM_MUTEN	  0x0200L
-#define EC_ADCCAL	  0x0400L
-#define EC_ADCRSTN	  0x0800L
-#define EC_DACCAL	  0x1000L
-#define EC_DACMUTEN	  0x2000L
-#define EC_LEDN		  0x4000L
-
-#define EC_SPDIF0_SEL_SHIFT	15
-#define EC_SPDIF1_SEL_SHIFT	17	
-#define EC_SPDIF0_SEL_MASK	(0x3L << EC_SPDIF0_SEL_SHIFT)
-#define EC_SPDIF1_SEL_MASK	(0x7L << EC_SPDIF1_SEL_SHIFT)
-#define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK)
-#define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK)
-#define EC_CURRENT_PROM_VERSION 0x01 /* Self-explanatory.  This should
-                                      * be incremented any time the EEPROM's
-                                      * format is changed.  */
-
-#define EC_EEPROM_SIZE	        0x40 /* ECARD EEPROM has 64 16-bit words */
-
-/* Addresses for special values stored in to EEPROM */
-#define EC_PROM_VERSION_ADDR	0x20	/* Address of the current prom version */
-#define EC_BOARDREV0_ADDR	0x21	/* LSW of board rev */
-#define EC_BOARDREV1_ADDR 	0x22	/* MSW of board rev */ 
-
-#define EC_LAST_PROMFILE_ADDR	0x2f
-
-#define EC_SERIALNUM_ADD	0x30	/* First word of serial number.  The number
-                                         * can be up to 30 characters in length
-                                         * and is stored as a NULL-terminated
-                                         * ASCII string.  Any unused bytes must be
-                                         * filled with zeros */
-#define EC_CHECKSUM_ADDR	0x3f    /* Location at which checksum is stored */
-
-
-
-/* Most of this stuff is pretty self-evident.  According to the hardware 
- * dudes, we need to leave the ADCCAL bit low in order to avoid a DC 
- * offset problem.  Weird.
- */
-#define EC_RAW_RUN_MODE	(EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | EC_TRIM_CSN)
-
-
-#define EC_DEFAULT_ADC_GAIN   0xC4C4
-#define EC_DEFAULT_SPDIF0_SEL 0x0
-#define EC_DEFAULT_SPDIF1_SEL 0x4
-
-#define HC_EA 0x01L
-
-/* ECARD state structure.  This structure maintains the state
- * for various portions of the ECARD's onboard hardware.
- */
-struct ecard_state {
-	u32 control_bits;
-	u16 adc_gain;
-	u16 mux0_setting;
-	u16 mux1_setting;
-	u16 mux2_setting;
-};
-
-void emu10k1_ecard_init(struct emu10k1_card *) __devinit;
-
-#endif /* _ECARD_H */
diff --git a/sound/oss/emu10k1/efxmgr.c b/sound/oss/emu10k1/efxmgr.c
deleted file mode 100644
index 7d5865d..0000000
--- a/sound/oss/emu10k1/efxmgr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- **********************************************************************
- *     efxmgr.c
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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. 
- * 
- ********************************************************************** 
- */
-
-#include <linux/bitops.h>
-#include "hwaccess.h"
-#include "efxmgr.h"
-
-int emu10k1_find_control_gpr(struct patch_manager *mgr, const char *patch_name, const char *gpr_name)
-{
-        struct dsp_patch *patch;
-	struct dsp_rpatch *rpatch;
-	char s[PATCH_NAME_SIZE + 4];
-	unsigned long *gpr_used;
-	int i;
-
-	DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name, gpr_name);
-
-	rpatch = &mgr->rpatch;
-	if (!strcmp(rpatch->name, patch_name)) {
-		gpr_used = rpatch->gpr_used;
-		goto match;
-	}
-
-	for (i = 0; i < mgr->current_pages * PATCHES_PER_PAGE; i++) {
-		patch = PATCH(mgr, i);
-			sprintf(s,"%s", patch->name);
-
-		if (!strcmp(s, patch_name)) {
-			gpr_used = patch->gpr_used;
-			goto match;
-		}
-	}
-
-	return -1;
-
-  match:
-	for (i = 0; i < NUM_GPRS; i++)
-		if (mgr->gpr[i].type == GPR_TYPE_CONTROL &&
-		    test_bit(i, gpr_used) &&
-		    !strcmp(mgr->gpr[i].name, gpr_name))
-			return i;
-
-	return -1;
-}
-
-void emu10k1_set_control_gpr(struct emu10k1_card *card, int addr, s32 val, int flag)
-{
-	struct patch_manager *mgr = &card->mgr;
-
-	DPD(2, "emu10k1_set_control_gpr(): %d %x\n", addr, val);
-
-	if (addr < 0 || addr >= NUM_GPRS)
-		return;
-
-	//fixme: once patch manager is up, remember to fix this for the audigy
-	if (card->is_audigy) {
-		sblive_writeptr(card, A_GPR_BASE + addr, 0, val);
-	} else {
-		if (flag)
-			val += sblive_readptr(card, GPR_BASE + addr, 0);
-		if (val > mgr->gpr[addr].max)
-			val = mgr->gpr[addr].max;
-		else if (val < mgr->gpr[addr].min)
-			val = mgr->gpr[addr].min;
-		sblive_writeptr(card, GPR_BASE + addr, 0, val);
-	}
-	
-	
-}
-
-//TODO: make this configurable:
-#define VOLCTRL_CHANNEL SOUND_MIXER_VOLUME
-#define VOLCTRL_STEP_SIZE        5
-
-//An internal function for setting OSS mixer controls.
-static void emu10k1_set_oss_vol(struct emu10k1_card *card, int oss_mixer,
-				unsigned int left, unsigned int right)
-{
-	extern char volume_params[SOUND_MIXER_NRDEVICES];
-
-	card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
-
-	if (!card->is_aps)
-		card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
-	
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left,
-			       volume_params[oss_mixer]);
-
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right,
-			       volume_params[oss_mixer]);
-}
-
-//FIXME: mute should unmute when pressed a second time
-void emu10k1_mute_irqhandler(struct emu10k1_card *card)
-{
-	int oss_channel = VOLCTRL_CHANNEL;
-	int left, right;
-	static int val;
-
-	if (val) {
-		left = val & 0xff;
-		right = (val >> 8) & 0xff;
-		val = 0;
-	} else {
-		val = card->ac97->mixer_state[oss_channel];
-		left = 0;
-		right = 0;
-	}
-
-	emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_volincr_irqhandler(struct emu10k1_card *card)
-{
-	int oss_channel = VOLCTRL_CHANNEL;
-	int left, right;
-
-	left = card->ac97->mixer_state[oss_channel] & 0xff;
-	right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
-
-	if ((left += VOLCTRL_STEP_SIZE) > 100)
-		left = 100;
-
-	if ((right += VOLCTRL_STEP_SIZE) > 100)
-		right = 100;
-
-	emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_voldecr_irqhandler(struct emu10k1_card *card)
-{
-	int oss_channel = VOLCTRL_CHANNEL;
-	int left, right;
-
-	left = card->ac97->mixer_state[oss_channel] & 0xff;
-	right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
-
-	if ((left -= VOLCTRL_STEP_SIZE) < 0)
-		left = 0;
-
-	if ((right -= VOLCTRL_STEP_SIZE) < 0)
-		right = 0;
-
-	emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int scale)
-{
-	struct patch_manager *mgr = &card->mgr;
-	unsigned long flags;
-
-	static const s32 log2lin[4] ={           //  attenuation (dB)
-		0x7fffffff,                      //       0.0         
-		0x7fffffff * 0.840896415253715 , //       1.5          
-		0x7fffffff * 0.707106781186548,  //       3.0
-		0x7fffffff * 0.594603557501361 , //       4.5
-	};
-
-	if (addr < 0)
-		return;
-
-	vol = (100 - vol ) * scale / 100;
-
-	// Thanks to the comp.dsp newsgroup for this neat trick:
-	vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
-
-	spin_lock_irqsave(&mgr->lock, flags);
-	emu10k1_set_control_gpr(card, addr, vol, 0);
-	spin_unlock_irqrestore(&mgr->lock, flags);
-}
-
-void emu10k1_dsp_irqhandler(struct emu10k1_card *card)
-{
-	unsigned long flags;
-
-	if (card->pt.state != PT_STATE_INACTIVE) {
-		u32 bc;
-		bc = sblive_readptr(card, GPR_BASE + card->pt.intr_gpr, 0);
-		if (bc != 0) {
-			DPD(3, "pt interrupt, bc = %d\n", bc);
-			spin_lock_irqsave(&card->pt.lock, flags);
-			card->pt.blocks_played = bc;
-			if (card->pt.blocks_played >= card->pt.blocks_copied) {
-				DPF(1, "buffer underrun in passthrough playback\n");
-				emu10k1_pt_stop(card);
-			}
-			wake_up_interruptible(&card->pt.wait);
-			spin_unlock_irqrestore(&card->pt.lock, flags);
-		}
-	}
-}
-
diff --git a/sound/oss/emu10k1/efxmgr.h b/sound/oss/emu10k1/efxmgr.h
deleted file mode 100644
index ef48e5c..0000000
--- a/sound/oss/emu10k1/efxmgr.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*     
- **********************************************************************
- *     sblive_fx.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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 _EFXMGR_H
-#define _EFXMGR_H
-
-struct emu_efx_info_t{
-	int opcode_shift;
-	int high_operand_shift;
-	int instruction_start;
-	int gpr_base;
-	int output_base;
-};
-
-
-#define WRITE_EFX(a, b, c) sblive_writeptr((a), emu_efx_info[card->is_audigy].instruction_start + (b), 0, (c))
-
-#define OP(op, z, w, x, y) \
-	do { WRITE_EFX(card, (pc) * 2, ((x) << emu_efx_info[card->is_audigy].high_operand_shift) | (y)); \
-	WRITE_EFX(card, (pc) * 2 + 1, ((op) << emu_efx_info[card->is_audigy].opcode_shift ) | ((z) << emu_efx_info[card->is_audigy].high_operand_shift) | (w)); \
-	++pc; } while (0)
-
-#define NUM_INPUTS 0x20
-#define NUM_OUTPUTS 0x20
-#define NUM_GPRS 0x100
-
-#define A_NUM_INPUTS 0x60
-#define A_NUM_OUTPUTS 0x60  //fixme: this may or may not be true
-#define A_NUM_GPRS 0x200
-
-#define GPR_NAME_SIZE   32
-#define PATCH_NAME_SIZE 32
-
-struct dsp_rpatch {
-	char name[PATCH_NAME_SIZE];
-	u16 code_start;
-	u16 code_size;
-
-	unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
-	unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
-	unsigned long route[NUM_OUTPUTS];
-	unsigned long route_v[NUM_OUTPUTS];
-};
-
-struct dsp_patch {
-	char name[PATCH_NAME_SIZE];
-	u8 id;
-	unsigned long input;	/* bitmap of the lines used as inputs */
-	unsigned long output;	/* bitmap of the lines used as outputs */
-	u16 code_start;
-	u16 code_size;
-
-	unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];	/* bitmap of used gprs */
-	unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
-	u8 traml_istart;	/* starting address of the internal tram lines used */
-	u8 traml_isize;		/* number of internal tram lines used */
-
-	u8 traml_estart;
-	u8 traml_esize;
-
-	u16 tramb_istart;        /* starting address of the internal tram memory used */
-	u16 tramb_isize;         /* amount of internal memory used */
-	u32 tramb_estart;
-	u32 tramb_esize;
-};
-
-struct dsp_gpr {
-	u8 type;			/* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */
-	char name[GPR_NAME_SIZE];	/* gpr value, only valid for control gprs */
-	s32 min, max;			/* value range for this gpr, only valid for control gprs */
-	u8 line;			/* which input/output line is the gpr attached, only valid for input/output gprs */
-	u8 usage;
-};
-
-enum {
-	GPR_TYPE_NULL = 0,
-	GPR_TYPE_IO,
-	GPR_TYPE_STATIC,
-	GPR_TYPE_DYNAMIC,
-	GPR_TYPE_CONTROL,
-	GPR_TYPE_CONSTANT
-};
-
-#define GPR_BASE 0x100
-#define OUTPUT_BASE 0x20
-
-#define A_GPR_BASE 0x400
-#define A_OUTPUT_BASE 0x60
-
-#define MAX_PATCHES_PAGES 32
-
-struct patch_manager {
-	void *patch[MAX_PATCHES_PAGES];
-	int current_pages;
-	struct dsp_rpatch rpatch;
-	struct dsp_gpr gpr[NUM_GPRS];   /* gpr usage table */
-	spinlock_t lock;
-	s16 ctrl_gpr[SOUND_MIXER_NRDEVICES][2];
-};
-
-#define PATCHES_PER_PAGE (PAGE_SIZE / sizeof(struct dsp_patch))
-
-#define PATCH(mgr, i) ((struct dsp_patch *) (mgr)->patch[(i) / PATCHES_PER_PAGE] + (i) % PATCHES_PER_PAGE)
-
-/* PCM volume control */
-#define TMP_PCM_L     0x100 //temp PCM L (after the vol control)       
-#define TMP_PCM_R     0x101
-#define VOL_PCM_L     0x102 //vol PCM
-#define VOL_PCM_R     0x103
-
-/* Routing patch */
-#define TMP_AC_L      0x104 //tmp ac97 out
-#define TMP_AC_R      0x105
-#define TMP_REAR_L    0x106 //output - Temp Rear
-#define TMP_REAR_R    0x107
-#define TMP_DIGI_L    0x108 //output - Temp digital
-#define TMP_DIGI_R    0x109
-#define DSP_VOL_L     0x10a // main dsp volume
-#define DSP_VOL_R     0x10b
-
-/* hw inputs */
-#define PCM_IN_L 	0x00
-#define PCM_IN_R 	0x01
-
-#define PCM1_IN_L        0x04
-#define PCM1_IN_R        0x05
-//mutilchannel playback stream appear here:
-
-#define MULTI_FRONT_L	0x08
-#define MULTI_FRONT_R	0x09
-#define MULTI_REAR_L	0x0a
-#define MULTI_REAR_R	0x0b
-#define MULTI_CENTER	0x0c
-#define MULTI_LFE	0x0d
-
-#define AC97_IN_L	0x10
-#define AC97_IN_R	0x11
-#define SPDIF_CD_L	0x12
-#define SPDIF_CD_R	0x13
-
-/* hw outputs */
-#define AC97_FRONT_L	0x20
-#define AC97_FRONT_R	0x21
-#define DIGITAL_OUT_L	0x22
-#define DIGITAL_OUT_R	0x23
-#define DIGITAL_CENTER	0x24
-#define DIGITAL_LFE	0x25
-
-#define ANALOG_REAR_L	0x28
-#define ANALOG_REAR_R	0x29
-#define ADC_REC_L	0x2a
-#define ADC_REC_R	0x2b
-
-#define ANALOG_CENTER	0x31
-#define ANALOG_LFE	0x32
-
-
-#define INPUT_PATCH_START(patch, nm, ln, i)		\
-do {							\
-	patch = PATCH(mgr, patch_n);			\
-	strcpy(patch->name, nm);			\
-	patch->code_start = pc * 2;			\
-	patch->input = (1<<(0x1f&ln));			\
-	patch->output= (1<<(0x1f&ln));			\
-	patch->id = i;					\
-} while(0)
-
-#define INPUT_PATCH_END(patch)				\
-do {							\
-	patch->code_size = pc * 2 - patch->code_start;	\
-	patch_n++;					\
-} while(0)
-
-
-#define ROUTING_PATCH_START(patch, nm)	\
-do {					\
-	patch = &mgr->rpatch;		\
-	strcpy(patch->name, nm);	\
-	patch->code_start = pc * 2;	\
-} while(0)
-
-#define ROUTING_PATCH_END(patch)			\
-do {                                                    \
-	patch->code_size = pc * 2 - patch->code_start;      \
-} while(0)
-
-#define CONNECT(input, output) set_bit(input, &rpatch->route[(output) - OUTPUT_BASE]);
-
-#define CONNECT_V(input, output) set_bit(input, &rpatch->route_v[(output) - OUTPUT_BASE]);
-
-#define OUTPUT_PATCH_START(patch, nm, ln, i)		\
-do {							\
-	patch = PATCH(mgr, patch_n);			\
-	strcpy(patch->name, nm);			\
-	patch->code_start = pc * 2;			\
-	patch->input = (1<<(0x1f&ln));			\
-	patch->output= (1<<(0x1f&ln));			\
-	patch->id = i;					\
-} while(0)
-
-#define OUTPUT_PATCH_END(patch)				\
-do {							\
-	patch->code_size = pc * 2 - patch->code_start;	\
-	patch_n++;					\
-} while(0)
-
-#define GET_OUTPUT_GPR(patch, g, ln)			\
-do {							\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_IO;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;		\
-	mgr->gpr[(g) - GPR_BASE].line = ln;		\
-	set_bit((g) - GPR_BASE, patch->gpr_used);	\
-} while(0)
-
-#define GET_INPUT_GPR(patch, g, ln)			\
-do {							\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_IO;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;		\
-	mgr->gpr[(g) - GPR_BASE].line = ln;		\
-	set_bit((g) - GPR_BASE, patch->gpr_used);	\
-	set_bit((g) - GPR_BASE, patch->gpr_input);	\
-} while(0)
-
-#define GET_DYNAMIC_GPR(patch, g)				\
-do {								\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_DYNAMIC;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;			\
-	set_bit((g) - GPR_BASE, patch->gpr_used);          	\
-} while(0)
-
-#define GET_CONTROL_GPR(patch, g, nm, a, b)			\
-do {								\
-	strcpy(mgr->gpr[(g) - GPR_BASE].name, nm);		\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_CONTROL;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;			\
-	mgr->gpr[(g) - GPR_BASE].min = a;			\
-	mgr->gpr[(g) - GPR_BASE].max = b;			\
-	sblive_writeptr(card, g, 0, b);				\
-	set_bit((g) - GPR_BASE, patch->gpr_used);		\
-} while(0)
-
-#endif /* _EFXMGR_H */
diff --git a/sound/oss/emu10k1/emuadxmg.c b/sound/oss/emu10k1/emuadxmg.c
deleted file mode 100644
index d7d2d4c..0000000
--- a/sound/oss/emu10k1/emuadxmg.c
+++ /dev/null
@@ -1,104 +0,0 @@
-
-/*     
- **********************************************************************
- *     emuadxmg.c - Address space manager for emu10k1 driver 
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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. 
- * 
- ********************************************************************** 
- */
-
-#include "hwaccess.h"
-
-/* Allocates emu address space */
-
-int emu10k1_addxmgr_alloc(u32 size, struct emu10k1_card *card)
-{
-	u16 *pagetable = card->emupagetable;
-	u16 index = 0;
-	u16 numpages;
-	unsigned long flags;
-
-	/* Convert bytes to pages */
-	numpages = (size / EMUPAGESIZE) + ((size % EMUPAGESIZE) ? 1 : 0);
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	while (index < (MAXPAGES - 1)) {
-		if (pagetable[index] & 0x8000) {
-			/* This block of pages is in use, jump to the start of the next block. */
-			index += (pagetable[index] & 0x7fff);
-		} else {
-			/* Found free block */
-			if (pagetable[index] >= numpages) {
-
-				/* Block is large enough */
-
-				/* If free block is larger than the block requested
-				 * then adjust the size of the block remaining */
-				if (pagetable[index] > numpages)
-					pagetable[index + numpages] = pagetable[index] - numpages;
-
-				pagetable[index] = (numpages | 0x8000);	/* Mark block as used */
-
-				spin_unlock_irqrestore(&card->lock, flags);
-
-				return index;
-			} else {
-				/* Block too small, jump to the start of the next block */
-				index += pagetable[index];
-			}
-		}
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return -1;
-}
-
-/* Frees a previously allocated emu address space. */
-
-void emu10k1_addxmgr_free(struct emu10k1_card *card, int index)
-{
-	u16 *pagetable = card->emupagetable;
-	u16 origsize = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (pagetable[index] & 0x8000) {
-		/* Block is allocated - mark block as free */
-		origsize = pagetable[index] & 0x7fff;
-		pagetable[index] = origsize;
-
-		/* If next block is free, we concat both blocks */
-		if (!(pagetable[index + origsize] & 0x8000))
-			pagetable[index] += pagetable[index + origsize] & 0x7fff;
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return;
-}
diff --git a/sound/oss/emu10k1/hwaccess.c b/sound/oss/emu10k1/hwaccess.c
deleted file mode 100644
index 2dc16a8..0000000
--- a/sound/oss/emu10k1/hwaccess.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- **********************************************************************
- *     hwaccess.c -- Hardware access layer
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     December 9, 1999     Jon Taylor      rewrote the I/O subsystem
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <asm/io.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "icardmid.h"
-
-/*************************************************************************
-* Function : srToPitch                                                   *
-* Input    : sampleRate - sampling rate                                  *
-* Return   : pitch value                                                 *
-* About    : convert sampling rate to pitch                              *
-* Note     : for 8010, sampling rate is at 48kHz, this function should   *
-*            be changed.                                                 *
-*************************************************************************/
-u32 srToPitch(u32 sampleRate)
-{
-	int i;
-
-	/* FIXME: These tables should be defined in a headerfile */
-	static u32 logMagTable[128] = {
-		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
-		0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
-		0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
-		0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
-		0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
-		0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
-		0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
-		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
-		0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
-		0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
-		0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
-		0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
-		0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
-		0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
-		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
-		0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
-	};
-
-	static char logSlopeTable[128] = {
-		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
-		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
-		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
-		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
-		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
-		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
-		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
-		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
-		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
-		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
-		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
-		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
-		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
-		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
-		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
-		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
-	};
-
-	if (sampleRate == 0)
-		return 0;	/* Bail out if no leading "1" */
-
-	sampleRate *= 11185;	/* Scale 48000 to 0x20002380 */
-
-	for (i = 31; i > 0; i--) {
-		if (sampleRate & 0x80000000) {	/* Detect leading "1" */
-			return (u32) (((s32) (i - 15) << 20) +
-				      logMagTable[0x7f & (sampleRate >> 24)] +
-				      (0x7f & (sampleRate >> 17)) * logSlopeTable[0x7f & (sampleRate >> 24)]);
-		}
-		sampleRate = sampleRate << 1;
-	}
-
-	DPF(2, "srToPitch: BUG!\n");
-	return 0;		/* Should never reach this point */
-}
-
-/*******************************************
-* write/read PCI function 0 registers      *
-********************************************/
-void emu10k1_writefn0(struct emu10k1_card *card, u32 reg, u32 data)
-{
-	unsigned long flags;
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-		data = (data << offset) & mask;
-		reg &= 0x7f;
-
-		spin_lock_irqsave(&card->lock, flags);
-		data |= inl(card->iobase + reg) & ~mask;
-		outl(data, card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-		outl(data, card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-
-	return;
-}
-
-#ifdef DBGEMU
-void emu10k1_writefn0_2(struct emu10k1_card *card, u32 reg, u32 data, int size)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (size == 32)
-		outl(data, card->iobase + (reg & 0x1F));
-	else if (size == 16)
-		outw(data, card->iobase + (reg & 0x1F));
-	else
-		outb(data, card->iobase + (reg & 0x1F));
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return;
-}
-#endif  /*  DBGEMU  */
-
-u32 emu10k1_readfn0(struct emu10k1_card * card, u32 reg)
-{
-	u32 val;
-	unsigned long flags;
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-		reg &= 0x7f;
-
-		spin_lock_irqsave(&card->lock, flags);
-		val = inl(card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		return (val & mask) >> offset;
-        } else {
-		spin_lock_irqsave(&card->lock, flags);
-		val = inl(card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-		return val;
-	}
-}
-
-void emu10k1_timer_set(struct emu10k1_card * card, u16 data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	outw(data & TIMER_RATE_MASK, card->iobase + TIMER);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/************************************************************************
-* write/read Emu10k1 pointer-offset register set, accessed through      *
-*  the PTR and DATA registers                                           *
-*************************************************************************/
-#define A_PTR_ADDRESS_MASK 0x0fff0000
-void sblive_writeptr(struct emu10k1_card *card, u32 reg, u32 channel, u32 data)
-{
-	u32 regptr;
-	unsigned long flags;
-
-	regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-		data = (data << offset) & mask;
-
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		data |= inl(card->iobase + DATA) & ~mask;
-		outl(data, card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		outl(data, card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-}
-
-/* ... :  data, reg, ... , TAGLIST_END */
-void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...)
-{
-	va_list args;
-
-	unsigned long flags;
-        u32 reg;
-
-	va_start(args, channel);
-
-	spin_lock_irqsave(&card->lock, flags);
-	while ((reg = va_arg(args, u32)) != TAGLIST_END) {
-		u32 data = va_arg(args, u32);
-		u32 regptr = (((reg << 16) & A_PTR_ADDRESS_MASK)
-			      | (channel & PTR_CHANNELNUM_MASK));
-		outl(regptr, card->iobase + PTR);
-		if (reg & 0xff000000) {
-			int size = (reg >> 24) & 0x3f;
-                        int offset = (reg >> 16) & 0x1f;
-			u32 mask = ((1 << size) - 1) << offset;
-			data = (data << offset) & mask;
-
-			data |= inl(card->iobase + DATA) & ~mask;
-		}
-		outl(data, card->iobase + DATA);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	va_end(args);
-
-	return;
-}
-
-u32 sblive_readptr(struct emu10k1_card * card, u32 reg, u32 channel)
-{
-	u32 regptr, val;
-	unsigned long flags;
-
-	regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		val = inl(card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		return (val & mask) >> offset;
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		val = inl(card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		return val;
-	}
-}
-
-void emu10k1_irq_enable(struct emu10k1_card *card, u32 irq_mask)
-{
-	u32 val;
-	unsigned long flags;
-
-	DPF(2,"emu10k1_irq_enable()\n");
-
-	spin_lock_irqsave(&card->lock, flags);
-        val = inl(card->iobase + INTE) | irq_mask;
-        outl(val, card->iobase + INTE);
-	spin_unlock_irqrestore(&card->lock, flags);
-	return;
-}
-
-void emu10k1_irq_disable(struct emu10k1_card *card, u32 irq_mask)
-{
-        u32 val;
-        unsigned long flags;
-
-        DPF(2,"emu10k1_irq_disable()\n");
-
-        spin_lock_irqsave(&card->lock, flags);
-        val = inl(card->iobase + INTE) & ~irq_mask;
-        outl(val, card->iobase + INTE);
-        spin_unlock_irqrestore(&card->lock, flags);
-        return;
-}
-
-void emu10k1_clear_stop_on_loop(struct emu10k1_card *card, u32 voicenum)
-{
-	/* Voice interrupt */
-	if (voicenum >= 32)
-		sblive_writeptr(card, SOLEH | ((0x0100 | (voicenum - 32)) << 16), 0, 0);
-	else
-		sblive_writeptr(card, SOLEL | ((0x0100 | voicenum) << 16), 0, 0);
-
-	return;
-}
-
-static void sblive_wcwait(struct emu10k1_card *card, u32 wait)
-{
-	volatile unsigned uCount;
-	u32 newtime = 0, curtime;
-
-	curtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
-	while (wait--) {
-		uCount = 0;
-		while (uCount++ < TIMEOUT) {
-			newtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
-			if (newtime != curtime)
-				break;
-		}
-
-		if (uCount >= TIMEOUT)
-			break;
-
-		curtime = newtime;
-	}
-}
-
-u16 emu10k1_ac97_read(struct ac97_codec *codec, u8 reg)
-{
-	struct emu10k1_card *card = codec->private_data;
-	u16 data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	outb(reg, card->iobase + AC97ADDRESS);
-	data = inw(card->iobase + AC97DATA);
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return data;
-}
-
-void emu10k1_ac97_write(struct ac97_codec *codec, u8 reg, u16 value)
-{
-	struct emu10k1_card *card = codec->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	outb(reg, card->iobase + AC97ADDRESS);
-	outw(value, card->iobase + AC97DATA);
-	outb( AC97_EXTENDED_ID, card->iobase + AC97ADDRESS); 
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/*********************************************************
-*            MPU access functions                        *
-**********************************************************/
-
-int emu10k1_mpu_write_data(struct emu10k1_card *card, u8 data)
-{
-	unsigned long flags;
-	int ret;
-
-	if (card->is_audigy) {
-		if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_ORDYN) == 0) {
-			sblive_writeptr(card, A_MUDATA, 0, data);
-			ret = 0;
-		} else
-			ret = -1;
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-
-		if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) {
-			outb(data, card->iobase + MUDATA);
-			ret = 0;
-		} else
-			ret = -1;
-
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-
-	return ret;
-}
-
-int emu10k1_mpu_read_data(struct emu10k1_card *card, u8 * data)
-{
-	unsigned long flags;
-	int ret;
-
-	if (card->is_audigy) {
-		if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_IRDYN) == 0) {
-			*data = sblive_readptr(card, A_MUDATA,0);
-			ret = 0;
-		} else
-			ret = -1;
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-
-		if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) {
-			*data = inb(card->iobase + MUDATA);
-			ret = 0;
-		} else
-			ret = -1;
-
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-
-	return ret;
-}
-
-int emu10k1_mpu_reset(struct emu10k1_card *card)
-{
-	u8 status;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpu_reset()\n");
-	if (card->is_audigy) {
-		if (card->mpuacqcount == 0) {
-			sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
-			sblive_wcwait(card, 8);
-			sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
-			sblive_wcwait(card, 8);
-			sblive_writeptr(card, A_MUCMD, 0, MUCMD_ENTERUARTMODE);
-			sblive_wcwait(card, 8);
-			status = sblive_readptr(card, A_MUDATA, 0);
-			if (status == 0xfe)
-				return 0;
-			else
-				return -1;
-		}
-
-		return 0;
-	} else {
-		if (card->mpuacqcount == 0) {
-			spin_lock_irqsave(&card->lock, flags);
-			outb(MUCMD_RESET, card->iobase + MUCMD);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			sblive_wcwait(card, 8);
-
-			spin_lock_irqsave(&card->lock, flags);
-			outb(MUCMD_RESET, card->iobase + MUCMD);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			sblive_wcwait(card, 8);
-
-			spin_lock_irqsave(&card->lock, flags);
-			outb(MUCMD_ENTERUARTMODE, card->iobase + MUCMD);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			sblive_wcwait(card, 8);
-
-			spin_lock_irqsave(&card->lock, flags);
-			status = inb(card->iobase + MUDATA);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			if (status == 0xfe)
-				return 0;
-			else
-				return -1;
-		}
-
-		return 0;
-	}
-}
-
-int emu10k1_mpu_acquire(struct emu10k1_card *card)
-{
-	/* FIXME: This should be a macro */
-	++card->mpuacqcount;
-
-	return 0;
-}
-
-int emu10k1_mpu_release(struct emu10k1_card *card)
-{
-	/* FIXME: this should be a macro */
-	--card->mpuacqcount;
-
-	return 0;
-}
diff --git a/sound/oss/emu10k1/hwaccess.h b/sound/oss/emu10k1/hwaccess.h
deleted file mode 100644
index 85e27bd..0000000
--- a/sound/oss/emu10k1/hwaccess.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- **********************************************************************
- *     hwaccess.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date		    Author	    Summary of changes
- *     ----		    ------	    ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _HWACCESS_H
-#define _HWACCESS_H
-
-#include <linux/fs.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <asm/io.h>
-
-#include "efxmgr.h"
-#include "passthrough.h"
-#include "midi.h"
-
-#define EMUPAGESIZE     4096            /* don't change */
-#define NUM_G           64              /* use all channels */
-#define NUM_FXSENDS     4               /* don't change */
-/* setting this to other than a power of two may break some applications */
-#define MAXBUFSIZE	65536
-#define MAXPAGES	8192 
-#define BUFMAXPAGES     (MAXBUFSIZE / PAGE_SIZE)
-
-#define FLAGS_AVAILABLE     0x0001
-#define FLAGS_READY         0x0002
-
-struct memhandle
-{
-	dma_addr_t dma_handle;
-	void *addr;
-	u32 size;
-};
-
-#define DEBUG_LEVEL 2
-
-#ifdef EMU10K1_DEBUG
-# define DPD(level,x,y...) do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ , y );} while(0)
-# define DPF(level,x)   do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ );} while(0)
-#else
-# define DPD(level,x,y...) do { } while (0) /* not debugging: nothing */
-# define DPF(level,x) do { } while (0)
-#endif /* EMU10K1_DEBUG */
-
-#define ERROR() DPF(1,"error\n")
-
-/* DATA STRUCTURES */
-
-struct emu10k1_waveout
-{
-	u32 send_routing[3];
-	// audigy only:
-	u32 send_routing2[3];
-
-	u32 send_dcba[3];
-	// audigy only:
-	u32 send_hgfe[3];
-};
-#define ROUTE_PCM 0
-#define ROUTE_PT 1
-#define ROUTE_PCM1 2
-
-#define SEND_MONO 0
-#define SEND_LEFT 1
-#define SEND_RIGHT 2
-
-struct emu10k1_wavein
-{
-        struct wiinst *ac97;
-        struct wiinst *mic;
-        struct wiinst *fx;
-
-        u8 recsrc;
-        u32 fxwc;
-};
-
-#define CMD_READ 1
-#define CMD_WRITE 2
-
-struct mixer_private_ioctl {
-        u32 cmd;
-        u32 val[90];
-};
-
-/* bogus ioctls numbers to escape from OSS mixer limitations */
-#define CMD_WRITEFN0            _IOW('D', 0, struct mixer_private_ioctl)
-#define CMD_READFN0		_IOR('D', 1, struct mixer_private_ioctl) 
-#define CMD_WRITEPTR		_IOW('D', 2, struct mixer_private_ioctl) 
-#define CMD_READPTR		_IOR('D', 3, struct mixer_private_ioctl) 
-#define CMD_SETRECSRC		_IOW('D', 4, struct mixer_private_ioctl) 
-#define CMD_GETRECSRC		_IOR('D', 5, struct mixer_private_ioctl) 
-#define CMD_GETVOICEPARAM	_IOR('D', 6, struct mixer_private_ioctl) 
-#define CMD_SETVOICEPARAM	_IOW('D', 7, struct mixer_private_ioctl) 
-#define CMD_GETPATCH		_IOR('D', 8, struct mixer_private_ioctl) 
-#define CMD_GETGPR		_IOR('D', 9, struct mixer_private_ioctl) 
-#define CMD_GETCTLGPR           _IOR('D', 10, struct mixer_private_ioctl)
-#define CMD_SETPATCH		_IOW('D', 11, struct mixer_private_ioctl) 
-#define CMD_SETGPR		_IOW('D', 12, struct mixer_private_ioctl) 
-#define CMD_SETCTLGPR		_IOW('D', 13, struct mixer_private_ioctl)
-#define CMD_SETGPOUT		_IOW('D', 14, struct mixer_private_ioctl)
-#define CMD_GETGPR2OSS		_IOR('D', 15, struct mixer_private_ioctl)
-#define CMD_SETGPR2OSS		_IOW('D', 16, struct mixer_private_ioctl)
-#define CMD_SETMCH_FX		_IOW('D', 17, struct mixer_private_ioctl)
-#define CMD_SETPASSTHROUGH	_IOW('D', 18, struct mixer_private_ioctl)
-#define CMD_PRIVATE3_VERSION	_IOW('D', 19, struct mixer_private_ioctl)
-#define CMD_AC97_BOOST		_IOW('D', 20, struct mixer_private_ioctl)
-
-//up this number when breaking compatibility
-#define PRIVATE3_VERSION 2
-
-struct emu10k1_card 
-{
-	struct list_head list;
-
-	struct memhandle	virtualpagetable;
-	struct memhandle	tankmem;
-	struct memhandle	silentpage;
-
-	spinlock_t		lock;
-
-	u8			voicetable[NUM_G];
-	u16			emupagetable[MAXPAGES];
-
-	struct list_head	timers;
-	u16			timer_delay;
-	spinlock_t		timer_lock;
-
-	struct pci_dev		*pci_dev;
-	unsigned long           iobase;
-	unsigned long		length;
-	unsigned short		model;
-	unsigned int irq; 
-
-	int	audio_dev;
-	int	audio_dev1;
-	int	midi_dev;
-#ifdef EMU10K1_SEQUENCER
-	int seq_dev;
-	struct emu10k1_mididevice *seq_mididev;
-#endif
-
-	struct ac97_codec *ac97;
-	int ac97_supported_mixers;
-	int ac97_stereo_mixers;
-
-	/* Number of first fx voice for multichannel output */
-	u8 mchannel_fx;
-	struct emu10k1_waveout	waveout;
-	struct emu10k1_wavein	wavein;
-	struct emu10k1_mpuout	*mpuout;
-	struct emu10k1_mpuin	*mpuin;
-
-	struct mutex		open_sem;
-	mode_t			open_mode;
-	wait_queue_head_t	open_wait;
-
-	u32	    mpuacqcount;	  // Mpu acquire count
-	u32	    has_toslink;	       // TOSLink detection
-
-	u8 chiprev;                    /* Chip revision                */
-	u8 is_audigy;
-	u8 is_aps;
-
-	struct patch_manager mgr;
-	struct pt_data pt;
-};
-
-int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *);
-void emu10k1_addxmgr_free(struct emu10k1_card *, int);
-
-int emu10k1_find_control_gpr(struct patch_manager *, const char *, const char *);
-void emu10k1_set_control_gpr(struct emu10k1_card *, int , s32, int );
-
-void emu10k1_set_volume_gpr(struct emu10k1_card *, int, s32, int);
-
-
-#define VOL_6BIT 0x40
-#define VOL_5BIT 0x20
-#define VOL_4BIT 0x10
-
-#define TIMEOUT 		    16384
-
-u32 srToPitch(u32);
-
-extern struct list_head emu10k1_devs;
-
-/* Hardware Abstraction Layer access functions */
-
-void emu10k1_writefn0(struct emu10k1_card *, u32, u32);
-void emu10k1_writefn0_2(struct emu10k1_card *, u32, u32, int);
-u32 emu10k1_readfn0(struct emu10k1_card *, u32);
-
-void emu10k1_timer_set(struct emu10k1_card *, u16);
-
-void sblive_writeptr(struct emu10k1_card *, u32, u32, u32);
-void sblive_writeptr_tag(struct emu10k1_card *, u32, ...);
-#define TAGLIST_END	0
-
-u32 sblive_readptr(struct emu10k1_card *, u32 , u32 );
-
-void emu10k1_irq_enable(struct emu10k1_card *, u32);
-void emu10k1_irq_disable(struct emu10k1_card *, u32);
-void emu10k1_clear_stop_on_loop(struct emu10k1_card *, u32);
-
-/* AC97 Codec register access function */
-u16 emu10k1_ac97_read(struct ac97_codec *, u8);
-void emu10k1_ac97_write(struct ac97_codec *, u8, u16);
-
-/* MPU access function*/
-int emu10k1_mpu_write_data(struct emu10k1_card *, u8);
-int emu10k1_mpu_read_data(struct emu10k1_card *, u8 *);
-int emu10k1_mpu_reset(struct emu10k1_card *);
-int emu10k1_mpu_acquire(struct emu10k1_card *);
-int emu10k1_mpu_release(struct emu10k1_card *);
-
-#endif  /* _HWACCESS_H */
diff --git a/sound/oss/emu10k1/icardmid.h b/sound/oss/emu10k1/icardmid.h
deleted file mode 100644
index 6a6ef41..0000000
--- a/sound/oss/emu10k1/icardmid.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- **********************************************************************
- *     isblive_mid.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _ICARDMIDI_H
-#define _ICARDMIDI_H
-
-/* MIDI defines */
-#define MIDI_DATA_FIRST                 0x00
-#define MIDI_DATA_LAST                  0x7F
-#define MIDI_STATUS_FIRST               0x80
-#define MIDI_STATUS_LAST                0xFF
-
-/* Channel status bytes */
-#define MIDI_STATUS_CHANNEL_FIRST       0x80
-#define MIDI_STATUS_CHANNEL_LAST        0xE0
-#define MIDI_STATUS_CHANNEL_MASK        0xF0
-
-/* Channel voice messages */
-#define MIDI_VOICE_NOTE_OFF             0x80
-#define MIDI_VOICE_NOTE_ON              0x90
-#define MIDI_VOICE_POLY_PRESSURE        0xA0
-#define MIDI_VOICE_CONTROL_CHANGE       0xB0
-#define MIDI_VOICE_PROGRAM_CHANGE       0xC0
-#define MIDI_VOICE_CHANNEL_PRESSURE     0xD0
-#define MIDI_VOICE_PITCH_BEND           0xE0
-
-/* Channel mode messages */
-#define MIDI_MODE_CHANNEL               MIDI_VOICE_CONTROL_CHANGE
-
-/* System status bytes */
-#define MIDI_STATUS_SYSTEM_FIRST        0xF0
-#define MIDI_STATUS_SYSTEM_LAST         0xFF
-
-/* System exclusive messages */
-#define MIDI_SYSEX_BEGIN                0xF0
-#define MIDI_SYSEX_EOX                  0xF7
-
-/* System common messages */
-#define MIDI_COMMON_TCQF                0xF1	/* Time code quarter frame  */
-#define MIDI_COMMON_SONG_POSITION       0xF2
-#define MIDI_COMMON_SONG_SELECT         0xF3
-#define MIDI_COMMON_UNDEFINED_F4        0xF4
-#define MIDI_COMMON_UNDEFINED_F5        0xF5
-#define MIDI_COMMON_TUNE_REQUEST        0xF6
-
-/* System real-time messages */
-#define MIDI_RTIME_TIMING_CLOCK         0xF8
-#define MIDI_RTIME_UNDEFINED_F9         0xF9
-#define MIDI_RTIME_START                0xFA
-#define MIDI_RTIME_CONTINUE             0xFB
-#define MIDI_RTIME_STOP                 0xFC
-#define MIDI_RTIME_UNDEFINED_FD         0xFD
-#define MIDI_RTIME_ACTIVE_SENSING       0xFE
-#define MIDI_RTIME_SYSTEM_RESET         0xFF
-
-/* Flags for flags parm of midiOutCachePatches(), midiOutCacheDrumPatches() */
-#define MIDI_CACHE_ALL                  1
-#define MIDI_CACHE_BESTFIT              2
-#define MIDI_CACHE_QUERY                3
-#define MIDI_UNCACHE                    4
-
-/* Event declarations for MPU IRQ Callbacks */
-#define ICARDMIDI_INLONGDATA            0x00000001 /* MIM_LONGDATA */
-#define ICARDMIDI_INLONGERROR           0x00000002 /* MIM_LONGERROR */
-#define ICARDMIDI_OUTLONGDATA           0x00000004 /* MOM_DONE for MPU OUT buffer */
-#define ICARDMIDI_INDATA                0x00000010 /* MIM_DATA */
-#define ICARDMIDI_INDATAERROR           0x00000020 /* MIM_ERROR */
-
-/* Declaration for flags in CARDMIDIBUFFERHDR */
-/* Make it the same as MHDR_DONE, MHDR_INQUEUE in mmsystem.h */
-#define MIDIBUF_DONE                    0x00000001
-#define MIDIBUF_INQUEUE                 0x00000004
-
-/* Declaration for msg parameter in midiCallbackFn */
-#define ICARDMIDI_OUTBUFFEROK           0x00000001
-#define ICARDMIDI_INMIDIOK              0x00000002
-
-/* Declaration for technology in struct midi_caps */
-#define MT_MIDIPORT                     0x00000001	/* In original MIDIOUTCAPS structure */
-#define MT_FMSYNTH                      0x00000004	/* In original MIDIOUTCAPS structure */
-#define MT_AWESYNTH                     0x00001000
-#define MT_PCISYNTH                     0x00002000
-#define MT_PCISYNTH64                   0x00004000
-#define CARDMIDI_AWEMASK                0x0000F000
-
-enum LocalErrorCode
-{
-        CTSTATUS_NOTENABLED = 0x7000,
-        CTSTATUS_READY,
-        CTSTATUS_BUSY,
-        CTSTATUS_DATAAVAIL,
-        CTSTATUS_NODATA,
-        CTSTATUS_NEXT_BYTE
-};
-
-/* MIDI data block header */
-struct midi_hdr
-{
-	u8 *reserved;		/* Pointer to original locked data block */
-	u32 bufferlength;	/* Length of data in data block */
-	u32 bytesrecorded;	/* Used for input only */
-	u32 user;		/* For client's use */
-	u32 flags;		/* Assorted flags (see defines) */
-	struct list_head list;	/* Reserved for driver */
-	u8 *data;		/* Second copy of first pointer */
-};
-
-/* Enumeration for SetControl */
-enum
-{
-	MIDIOBJVOLUME = 0x1,
-	MIDIQUERYACTIVEINST
-};
-
-struct midi_queue
-{
-	struct midi_queue  *next;
-	u32 qtype;            /* 0 = short message, 1 = long data */
-	u32 length;
-	u32 sizeLeft;
-	u8 *midibyte;
-	unsigned long refdata;
-};
-
-struct midi_openinfo
-{
-	u32     cbsize;
-	u32     flags;
-	unsigned long  refdata;
-	u32     streamid;
-};
-
-int emu10k1_midi_callback(unsigned long , unsigned long, unsigned long *);
-
-#endif /* _ICARDMIDI_H */
diff --git a/sound/oss/emu10k1/icardwav.h b/sound/oss/emu10k1/icardwav.h
deleted file mode 100644
index 25be409..0000000
--- a/sound/oss/emu10k1/icardwav.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*     
- **********************************************************************
- *     icardwav.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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 _ICARDWAV_H
-#define _ICARDWAV_H
-
-struct wave_format 
-{
-	int id;
-	int samplingrate;
-	u8 bitsperchannel;
-	u8 channels;		/* 1 = Mono, 2 = Stereo, 3, ... = Multichannel */
-	u8 bytesperchannel;
-	u8 bytespervoicesample;
-	u8 bytespersample;
-	int bytespersec;
-	u8 passthrough;
-};
-
-/* emu10k1_wave states */
-#define WAVE_STATE_OPEN		0x01	
-#define WAVE_STATE_STARTED	0x02
-#define WAVE_STATE_CLOSED	0x04
-
-#endif /* _ICARDWAV_H */
diff --git a/sound/oss/emu10k1/irqmgr.c b/sound/oss/emu10k1/irqmgr.c
deleted file mode 100644
index fb2ce63..0000000
--- a/sound/oss/emu10k1/irqmgr.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- **********************************************************************
- *     irqmgr.c - IRQ manager for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmi.h"
-#include "cardmo.h"
-#include "irqmgr.h"
-
-/* Interrupt handler */
-
-irqreturn_t emu10k1_interrupt(int irq, void *dev_id)
-{
-	struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
-	u32 irqstatus, irqstatus_tmp;
-	int handled = 0;
-
-	DPD(4, "emu10k1_interrupt called, irq =  %u\n", irq);
-
-	/*
-	 ** NOTE :
-	 ** We do a 'while loop' here cos on certain machines, with both
-	 ** playback and recording going on at the same time, IRQs will
-	 ** stop coming in after a while. Checking IPND indeed shows that
-	 ** there are interrupts pending but the PIC says no IRQs pending.
-	 ** I suspect that some boards need edge-triggered IRQs but are not
-	 ** getting that condition if we don't completely clear the IPND
-	 ** (make sure no more interrupts are pending).
-	 ** - Eric
-	 */
-
-	while ((irqstatus = inl(card->iobase + IPR))) {
-		DPD(4, "irq status %#x\n", irqstatus);
-
-		irqstatus_tmp = irqstatus;
-
-		if (irqstatus & IRQTYPE_TIMER) {
-			emu10k1_timer_irqhandler(card);
-			irqstatus &= ~IRQTYPE_TIMER;
-		}
-
-		if (irqstatus & IRQTYPE_DSP) {
-			emu10k1_dsp_irqhandler(card);
-			irqstatus &= ~IRQTYPE_DSP;
-		}
-
-		if (irqstatus & IRQTYPE_MPUIN) {
-			emu10k1_mpuin_irqhandler(card);
-			irqstatus &= ~IRQTYPE_MPUIN;
-		}
-
-		if (irqstatus & IRQTYPE_MPUOUT) {
-			emu10k1_mpuout_irqhandler(card);
-			irqstatus &= ~IRQTYPE_MPUOUT;
-		}
-
-		if (irqstatus & IPR_MUTE) {
-			emu10k1_mute_irqhandler(card);
-			irqstatus &=~IPR_MUTE;
-		}
-
-		if (irqstatus & IPR_VOLINCR) {
-			emu10k1_volincr_irqhandler(card);
-			irqstatus &=~IPR_VOLINCR;
-		}
-
-		if (irqstatus & IPR_VOLDECR) {
-			emu10k1_voldecr_irqhandler(card);
-			irqstatus &=~IPR_VOLDECR;
-		}
-
-		if (irqstatus){
-			printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus);
-			//make sure any interrupts we don't handle are disabled:
-			emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB |
-						INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE |
-						INTE_FXDSPENABLE));
-		}
-
-		/* acknowledge interrupt */
-		outl(irqstatus_tmp, card->iobase + IPR);
-		handled = 1;
-	}
-	return IRQ_RETVAL(handled);
-}
diff --git a/sound/oss/emu10k1/irqmgr.h b/sound/oss/emu10k1/irqmgr.h
deleted file mode 100644
index 7e7c9ca..0000000
--- a/sound/oss/emu10k1/irqmgr.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- **********************************************************************
- *     irq.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _IRQ_H
-#define _IRQ_H
-
-/* EMU Irq Types */
-#define IRQTYPE_PCIBUSERROR	IPR_PCIERROR
-#define IRQTYPE_MIXERBUTTON	(IPR_VOLINCR | IPR_VOLDECR | IPR_MUTE)
-#define IRQTYPE_VOICE		(IPR_CHANNELLOOP | IPR_CHANNELNUMBERMASK)
-#define IRQTYPE_RECORD		(IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL | IPR_MICBUFFULL | IPR_MICBUFHALFFULL | IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)
-#define IRQTYPE_MPUOUT		(IPR_MIDITRANSBUFEMPTY | A_IPR_MIDITRANSBUFEMPTY2) 
-#define IRQTYPE_MPUIN		(IPR_MIDIRECVBUFEMPTY | A_IPR_MIDIRECVBUFEMPTY2)
-#define IRQTYPE_TIMER		IPR_INTERVALTIMER
-#define IRQTYPE_SPDIF		(IPR_GPSPDIFSTATUSCHANGE | IPR_CDROMSTATUSCHANGE)
-#define IRQTYPE_DSP		IPR_FXDSP
-
-void emu10k1_timer_irqhandler(struct emu10k1_card *);
-void emu10k1_dsp_irqhandler(struct emu10k1_card *);
-void emu10k1_mute_irqhandler(struct emu10k1_card *);
-void emu10k1_volincr_irqhandler(struct emu10k1_card *);
-void emu10k1_voldecr_irqhandler(struct emu10k1_card *);
-
-#endif /* _IRQ_H */
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
deleted file mode 100644
index 5058411..0000000
--- a/sound/oss/emu10k1/main.c
+++ /dev/null
@@ -1,1471 +0,0 @@
- /*
- **********************************************************************
- *     main.c - Creative EMU10K1 audio driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        cleaned up stuff
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- *
- *      Supported devices:
- *      /dev/dsp:        Standard /dev/dsp device, OSS-compatible
- *      /dev/dsp1:       Routes to rear speakers only	 
- *      /dev/mixer:      Standard /dev/mixer device, OSS-compatible
- *      /dev/midi:       Raw MIDI UART device, mostly OSS-compatible
- *	/dev/sequencer:  Sequencer Interface (requires sound.o)
- *
- *      Revision history:
- *      0.1 beta Initial release
- *      0.2 Lowered initial mixer vol. Improved on stuttering wave playback. Added MIDI UART support.
- *      0.3 Fixed mixer routing bug, added APS, joystick support.
- *      0.4 Added rear-channel, SPDIF support.
- *	0.5 Source cleanup, SMP fixes, multiopen support, 64 bit arch fixes,
- *	    moved bh's to tasklets, moved to the new PCI driver initialization style.
- *	0.6 Make use of pci_alloc_consistent, improve compatibility layer for 2.2 kernels,
- *	    code reorganization and cleanup.
- *	0.7 Support for the Emu-APS. Bug fixes for voice cache setup, mmaped sound + poll().
- *          Support for setting external TRAM size.
- *      0.8 Make use of the kernel ac97 interface. Support for a dsp patch manager.
- *      0.9 Re-enables rear speakers volume controls
- *     0.10 Initializes rear speaker volume.
- *	    Dynamic patch storage allocation.
- *	    New private ioctls to change control gpr values.
- *	    Enable volume control interrupts.
- *	    By default enable dsp routes to digital out. 
- *     0.11 Fixed fx / 4 problem.
- *     0.12 Implemented mmaped for recording.
- *	    Fixed bug: not unreserving mmaped buffer pages.
- *	    IRQ handler cleanup.
- *     0.13 Fixed problem with dsp1
- *          Simplified dsp patch writing (inside the driver)
- *	    Fixed several bugs found by the Stanford tools
- *     0.14 New control gpr to oss mixer mapping feature (Chris Purnell)
- *          Added AC3 Passthrough Support (Juha Yrjola)
- *          Added Support for 5.1 cards (digital out and the third analog out)
- *     0.15 Added Sequencer Support (Daniel Mack)
- *          Support for multichannel pcm playback (Eduard Hasenleithner)
- *     0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand)
- *          Small code format cleanup.
- *          Deadlock bug fix for emu10k1_volxxx_irqhandler().
- *     0.17 Fix for mixer SOUND_MIXER_INFO ioctl.
- *	    Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master) 
- *	    midi poll initial implementation.
- *	    Small mixer fixes/cleanups.
- *	    Improved support for 5.1 cards.
- *     0.18 Fix for possible leak in pci_alloc_consistent()
- *          Cleaned up poll() functions (audio and midi). Don't start input.
- *	    Restrict DMA pages used to 512Mib range.
- *	    New AC97_BOOST mixer ioctl.
- *    0.19a Added Support for Audigy Cards
- *	    Real fix for kernel with highmem support (cast dma_handle to u32).
- *	    Fix recording buffering parameters calculation.
- *	    Use unsigned long for variables in bit ops.
- *    0.20a Fixed recording startup
- *	    Fixed timer rate setting (it's a 16-bit register)
- *	0.21 Converted code to use pci_name() instead of accessing slot_name
- *	    directly (Eugene Teo)
- *********************************************************************/
-
-/* These are only included once per module */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/dma-mapping.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "efxmgr.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "cardmo.h"
-#include "cardmi.h"
-#include "recmgr.h"
-#include "ecard.h"
-
-
-#ifdef EMU10K1_SEQUENCER
-#define MIDI_SYNTH_NAME "EMU10K1 MIDI"
-#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
- 
-#include "../sound_config.h"
-#include "../midi_synth.h"
-
-/* this should be in dev_table.h */
-#define SNDCARD_EMU10K1 46
-#endif
- 
-
-/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
-#define EMU10K1_DMA_MASK DMA_29BIT_MASK	/* DMA buffer mask for pci_alloc_consist */
-
-#ifndef PCI_VENDOR_ID_CREATIVE
-#define PCI_VENDOR_ID_CREATIVE 0x1102
-#endif
-
-#ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
-#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
-#endif
-#ifndef PCI_DEVICE_ID_CREATIVE_AUDIGY
-#define PCI_DEVICE_ID_CREATIVE_AUDIGY 0x0004
-#endif
-
-#define EMU_APS_SUBID	0x40011102
- 
-enum {
-	EMU10K1 = 0,
-	AUDIGY,
-};
-
-static char *card_names[] __devinitdata = {
-	"EMU10K1",
-	"Audigy",
-};
-
-static struct pci_device_id emu10k1_pci_tbl[] = {
-	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},
-	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_AUDIGY,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AUDIGY},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, emu10k1_pci_tbl);
-
-/* Global var instantiation */
-
-LIST_HEAD(emu10k1_devs);
-
-extern struct file_operations emu10k1_audio_fops;
-extern struct file_operations emu10k1_mixer_fops;
-extern struct file_operations emu10k1_midi_fops;
-
-#ifdef EMU10K1_SEQUENCER
-static struct midi_operations emu10k1_midi_operations;
-#endif
-
-extern irqreturn_t emu10k1_interrupt(int, void *);
-
-static int __devinit emu10k1_audio_init(struct emu10k1_card *card)
-{
-	/* Assign default playback voice parameters */
-	if (card->is_audigy)
-		card->mchannel_fx = 0;
-	else
-		card->mchannel_fx = 8;
-
-
-	if (card->is_audigy) {
-		/* mono voice */
-		card->waveout.send_dcba[SEND_MONO] = 0xffffffff;
-		card->waveout.send_hgfe[SEND_MONO] = 0x0000ffff;
-	
-		/* stereo voice */
-		/* left */
-		card->waveout.send_dcba[SEND_LEFT] = 0x00ff00ff;
-		card->waveout.send_hgfe[SEND_LEFT] = 0x00007f7f;	
-		/* right */
-		card->waveout.send_dcba[SEND_RIGHT] = 0xff00ff00;
-		card->waveout.send_hgfe[SEND_RIGHT] = 0x00007f7f;
-
-		card->waveout.send_routing[ROUTE_PCM] = 0x03020100; // Regular pcm
-		card->waveout.send_routing2[ROUTE_PCM] = 0x07060504;
-
-		card->waveout.send_routing[ROUTE_PT] = 0x3f3f3d3c; // Passthrough
-		card->waveout.send_routing2[ROUTE_PT] = 0x3f3f3f3f;
-		
-		card->waveout.send_routing[ROUTE_PCM1] = 0x03020100; // Spare
-		card->waveout.send_routing2[ROUTE_PCM1] = 0x07060404;
-		
-	} else {
-		/* mono voice */
-		card->waveout.send_dcba[SEND_MONO] = 0x0000ffff;
-	
-		/* stereo voice */
-		/* left */
-		card->waveout.send_dcba[SEND_LEFT] = 0x000000ff;
-		/* right */
-		card->waveout.send_dcba[SEND_RIGHT] = 0x0000ff00;
-
-		card->waveout.send_routing[ROUTE_PCM] = 0x3210; // pcm
-		card->waveout.send_routing[ROUTE_PT] = 0x3210; // passthrough
-		card->waveout.send_routing[ROUTE_PCM1] = 0x7654; // /dev/dsp1
-	}
-
-	/* Assign default recording parameters */
-	/* FIXME */
-	if (card->is_aps)
-		card->wavein.recsrc = WAVERECORD_FX;
-	else
-		card->wavein.recsrc = WAVERECORD_AC97;
-
-	card->wavein.fxwc = 0x0003;
-	return 0;
-}
-
-static void emu10k1_audio_cleanup(struct emu10k1_card *card)
-{
-}
-
-static int __devinit emu10k1_register_devices(struct emu10k1_card *card)
-{
-	card->audio_dev = register_sound_dsp(&emu10k1_audio_fops, -1);
-	if (card->audio_dev < 0) {
-		printk(KERN_ERR "emu10k1: cannot register first audio device!\n");
-		goto err_dev;
-	}
-
-	card->audio_dev1 = register_sound_dsp(&emu10k1_audio_fops, -1);
-	if (card->audio_dev1 < 0) {
-		printk(KERN_ERR "emu10k1: cannot register second audio device!\n");
-		goto err_dev1;
-	}
-
-	card->ac97->dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
-	if (card->ac97->dev_mixer < 0) {
-		printk(KERN_ERR "emu10k1: cannot register mixer device\n");
-		goto err_mixer;
-        }
-
-	card->midi_dev = register_sound_midi(&emu10k1_midi_fops, -1);
-	if (card->midi_dev < 0) {
-                printk(KERN_ERR "emu10k1: cannot register midi device!\n");
-		goto err_midi;
-        }
-
-#ifdef EMU10K1_SEQUENCER
-	card->seq_dev = sound_alloc_mididev();
-	if (card->seq_dev == -1)
-		printk(KERN_WARNING "emu10k1: unable to register sequencer device!");
-	else {
-		std_midi_synth.midi_dev = card->seq_dev;
-		midi_devs[card->seq_dev] = 
-			(struct midi_operations *)
-			kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
-
-		if (midi_devs[card->seq_dev] == NULL) {
-			printk(KERN_ERR "emu10k1: unable to allocate memory!");
-			sound_unload_mididev(card->seq_dev);
-			card->seq_dev = -1;
-			/* return without error */
-		} else {
-			memcpy((char *)midi_devs[card->seq_dev], 
-				(char *)&emu10k1_midi_operations, 
-				sizeof(struct midi_operations));
-			midi_devs[card->seq_dev]->devc = card;
-			sequencer_init();
-			card->seq_mididev = NULL;
-		}
-	}
-#endif
-	return 0;
-
-err_midi:
-	unregister_sound_mixer(card->ac97->dev_mixer);
-err_mixer:
-	unregister_sound_dsp(card->audio_dev);
-err_dev1:
-	unregister_sound_dsp(card->audio_dev);
-err_dev:
-	return -ENODEV;
-}
-
-static void emu10k1_unregister_devices(struct emu10k1_card *card)
-{
-#ifdef EMU10K1_SEQUENCER
-	if (card->seq_dev > -1) {
-		kfree(midi_devs[card->seq_dev]);
-		midi_devs[card->seq_dev] = NULL;
-		sound_unload_mididev(card->seq_dev);
-		card->seq_dev = -1;
-	}
-#endif
-
-	unregister_sound_midi(card->midi_dev);
-	unregister_sound_mixer(card->ac97->dev_mixer);
-	unregister_sound_dsp(card->audio_dev1);
-	unregister_sound_dsp(card->audio_dev);
-}
-
-static int emu10k1_info_proc (char *page, char **start, off_t off,
-			      int count, int *eof, void *data)
-{
-	struct emu10k1_card *card = data;
-	int len = 0;
-	
-	if (card == NULL)
-		return -ENODEV;
-
-	len += sprintf (page + len, "Driver Version : %s\n", DRIVER_VERSION);
-	len += sprintf (page + len, "Card type      : %s\n", card->is_aps ? "Aps" : (card->is_audigy ? "Audigy" : "Emu10k1"));
-	len += sprintf (page + len, "Revision       : %d\n", card->chiprev);
-	len += sprintf (page + len, "Model          : %#06x\n", card->model);
-	len += sprintf (page + len, "IO             : %#06lx-%#06lx\n", card->iobase, card->iobase + card->length - 1);
-	len += sprintf (page + len, "IRQ            : %d\n\n", card->irq);
-	
-	len += sprintf (page + len, "Registered /dev Entries:\n");
-	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev / 16);
-	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev1 / 16);
-	len += sprintf (page + len, "/dev/mixer%d\n", card->ac97->dev_mixer / 16);
-	len += sprintf (page + len, "/dev/midi%d\n", card->midi_dev / 16);
-
-#ifdef EMU10K1_SEQUENCER
-	len += sprintf (page + len, "/dev/sequencer\n");
-#endif
-
-	return len;
-}
-
-static int __devinit emu10k1_proc_init(struct emu10k1_card *card)
-{
-	char s[48];
-
-	if (!proc_mkdir ("driver/emu10k1", NULL)) {
-		printk(KERN_ERR "emu10k1: unable to create proc directory driver/emu10k1\n");
-		goto err_out;
-	}
-
-	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
-	if (!proc_mkdir (s, NULL)) {
-		printk(KERN_ERR "emu10k1: unable to create proc directory %s\n", s);
-		goto err_emu10k1_proc;
-	}
-
-	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
-	if (!create_proc_read_entry (s, 0, NULL, emu10k1_info_proc, card)) {
-		printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
-		goto err_dev_proc;
-	}
-
-	if (!card->is_aps) {
-		sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));
-		if (!create_proc_read_entry (s, 0, NULL, ac97_read_proc, card->ac97)) {
-			printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
-			goto err_proc_ac97;
-		}
-	}
-
-	return 0;
-
-err_proc_ac97:
-	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-
-err_dev_proc:
-	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-
-err_emu10k1_proc:
-	remove_proc_entry("driver/emu10k1", NULL);
-
-err_out:
-	return -EIO;
-}
-
-static void emu10k1_proc_cleanup(struct emu10k1_card *card)
-{
-	char s[48];
-
-	if (!card->is_aps) {
-		sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));
-		remove_proc_entry(s, NULL);
-	}
-
-	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-
-	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-		
-	remove_proc_entry("driver/emu10k1", NULL);
-}
-
-static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
-{
-	struct ac97_codec *codec  = ac97_alloc_codec();
-	
-	if(codec == NULL)
-	{
-		printk(KERN_ERR "emu10k1: cannot allocate mixer\n");
-		return -EIO;
-	}
-	card->ac97 = codec;
-	card->ac97->private_data = card;
-
-	if (!card->is_aps) {
-		card->ac97->id = 0;
-		card->ac97->codec_read = emu10k1_ac97_read;
-        	card->ac97->codec_write = emu10k1_ac97_write;
-
-		if (ac97_probe_codec (card->ac97) == 0) {
-			printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n");
-			goto err_out;
-		}
-		/* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */
-		if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){
-			printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n"); 
-			sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
-			codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0);
-		}
-
-		// Force 5bit:		    
-		//card->ac97->bit_resolution=5;
-
-		/* these will store the original values and never be modified */
-		card->ac97_supported_mixers = card->ac97->supported_mixers;
-		card->ac97_stereo_mixers = card->ac97->stereo_mixers;
-	}
-
-	return 0;
-
- err_out:
- 	ac97_release_codec(card->ac97);
-	return -EIO;
-}
-
-static void emu10k1_mixer_cleanup(struct emu10k1_card *card)
-{
-	ac97_release_codec(card->ac97);
-}
-
-static int __devinit emu10k1_midi_init(struct emu10k1_card *card)
-{
-	int ret;
-
-	card->mpuout = kzalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
-	if (card->mpuout == NULL) {
-		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
-		ret = -ENOMEM;
-		goto err_out1;
-	}
-
-	card->mpuout->intr = 1;
-	card->mpuout->status = FLAGS_AVAILABLE;
-	card->mpuout->state = CARDMIDIOUT_STATE_DEFAULT;
-
-	tasklet_init(&card->mpuout->tasklet, emu10k1_mpuout_bh, (unsigned long) card);
-
-	spin_lock_init(&card->mpuout->lock);
-
-	card->mpuin = kzalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);
-	if (card->mpuin == NULL) {
-		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");
-		ret = -ENOMEM;
-                goto err_out2;
-	}
-
-	card->mpuin->status = FLAGS_AVAILABLE;
-
-	tasklet_init(&card->mpuin->tasklet, emu10k1_mpuin_bh, (unsigned long) card->mpuin);
-
-	spin_lock_init(&card->mpuin->lock);
-
-	/* Reset the MPU port */
-	if (emu10k1_mpu_reset(card) < 0) {
-		ERROR();
-		ret = -EIO;
-		goto err_out3;
-	}
-
-	return 0;
-
-err_out3:
-	kfree(card->mpuin);
-err_out2:
-	kfree(card->mpuout);
-err_out1:
-	return ret;
-}
-
-static void emu10k1_midi_cleanup(struct emu10k1_card *card)
-{
-	tasklet_kill(&card->mpuout->tasklet);
-	kfree(card->mpuout);
-
-	tasklet_kill(&card->mpuin->tasklet);
-	kfree(card->mpuin);
-}
-
-static void __devinit voice_init(struct emu10k1_card *card)
-{
-	int i;
-
-	for (i = 0; i < NUM_G; i++)
-		card->voicetable[i] = VOICE_USAGE_FREE;
-}
-
-static void __devinit timer_init(struct emu10k1_card *card)
-{
-	INIT_LIST_HEAD(&card->timers);
-	card->timer_delay = TIMER_STOPPED;
-	spin_lock_init(&card->timer_lock);
-}
-
-static void __devinit addxmgr_init(struct emu10k1_card *card)
-{
-	u32 count;
-
-	for (count = 0; count < MAXPAGES; count++)
-		card->emupagetable[count] = 0;
-
-	/* Mark first page as used */
-	/* This page is reserved by the driver */
-	card->emupagetable[0] = 0x8001;
-	card->emupagetable[1] = MAXPAGES - 1;
-}
-
-static void fx_cleanup(struct patch_manager *mgr)
-{
-	int i;
-	for(i = 0; i < mgr->current_pages; i++)
-		free_page((unsigned long) mgr->patch[i]);
-}
-
-static int __devinit fx_init(struct emu10k1_card *card)
-{
-	struct patch_manager *mgr = &card->mgr;
-	struct dsp_patch *patch;
-	struct dsp_rpatch *rpatch;
-	s32 left, right;
-	int i;
-	u32 pc = 0;
-	u32 patch_n=0;
-	struct emu_efx_info_t emu_efx_info[2]=
-		{{ 20, 10, 0x400, 0x100, 0x20 },
-		 { 24, 12, 0x600, 0x400, 0x60 },
-		}; 
-			
-
-	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-		mgr->ctrl_gpr[i][0] = -1;
-		mgr->ctrl_gpr[i][1] = -1;
-	}
-
-
-	if (card->is_audigy)
-		mgr->current_pages = (2 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
-	else
-		/* !! The number below must equal the number of patches, currently 11 !! */
-		mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
-	
-	for (i = 0; i < mgr->current_pages; i++) {
-		mgr->patch[i] = (void *)__get_free_page(GFP_KERNEL);
-		if (mgr->patch[i] == NULL) {
-			mgr->current_pages = i;
-			fx_cleanup(mgr);
-			return -ENOMEM;
-		}
-		memset(mgr->patch[i], 0, PAGE_SIZE);
-	}
-
-	if (card->is_audigy) {
-		for (i = 0; i < 1024; i++)
-			OP(0xf, 0x0c0, 0x0c0, 0x0cf, 0x0c0);
-
-		for (i = 0; i < 512 ; i++)
-			sblive_writeptr(card, A_GPR_BASE+i,0,0);
-
-		pc=0;
-
-		//Pcm input volume
-		OP(0, 0x402, 0x0c0, 0x406, 0x000);
-		OP(0, 0x403, 0x0c0, 0x407, 0x001);
-
-		//CD-Digital input Volume
-		OP(0, 0x404, 0x0c0, 0x40d, 0x42);
-		OP(0, 0x405, 0x0c0, 0x40f, 0x43);
-
-		// CD + PCM 
-		OP(6, 0x400, 0x0c0, 0x402, 0x404);
-		OP(6, 0x401, 0x0c0, 0x403, 0x405);
-		
-		// Front Output + Master Volume
-		OP(0, 0x68, 0x0c0, 0x408, 0x400);
-		OP(0, 0x69, 0x0c0, 0x409, 0x401);
-
-		// Add-in analog inputs for other speakers
-		OP(6, 0x400, 0x40, 0x400, 0xc0);
-		OP(6, 0x401, 0x41, 0x401, 0xc0);
-
-		// Digital Front + Master Volume
-		OP(0, 0x60, 0x0c0, 0x408, 0x400);
-		OP(0, 0x61, 0x0c0, 0x409, 0x401);
-
-		// Rear Output + Rear Volume
-		OP(0, 0x06e, 0x0c0, 0x419, 0x400);
-		OP(0, 0x06f, 0x0c0, 0x41a, 0x401);		
-
-		// Digital Rear Output + Rear Volume
-		OP(0, 0x066, 0x0c0, 0x419, 0x400);
-		OP(0, 0x067, 0x0c0, 0x41a, 0x401);		
-
-		// Audigy Drive, Headphone out
-		OP(6, 0x64, 0x0c0, 0x0c0, 0x400);
-		OP(6, 0x65, 0x0c0, 0x0c0, 0x401);
-
-		// ac97 Recording
-		OP(6, 0x76, 0x0c0, 0x0c0, 0x40);
-		OP(6, 0x77, 0x0c0, 0x0c0, 0x41);
-		
-		// Center = sub = Left/2 + Right/2
-		OP(0xe, 0x400, 0x401, 0xcd, 0x400);
-
-		// center/sub  Volume (master)
-		OP(0, 0x06a, 0x0c0, 0x408, 0x400);
-		OP(0, 0x06b, 0x0c0, 0x409, 0x400);
-
-		// Digital center/sub  Volume (master)
-		OP(0, 0x062, 0x0c0, 0x408, 0x400);
-		OP(0, 0x063, 0x0c0, 0x409, 0x400);
-
-		ROUTING_PATCH_START(rpatch, "Routing");
-		ROUTING_PATCH_END(rpatch);
-
-		/* delimiter patch */
-		patch = PATCH(mgr, patch_n);
-		patch->code_size = 0;
-
-	
-		sblive_writeptr(card, 0x53, 0, 0);
-	} else {
-		for (i = 0; i < 512 ; i++)
-			OP(6, 0x40, 0x40, 0x40, 0x40);
-
-		for (i = 0; i < 256; i++)
-			sblive_writeptr_tag(card, 0,
-					    FXGPREGBASE + i, 0,
-					    TANKMEMADDRREGBASE + i, 0,
-					    TAGLIST_END);
-
-		
-		pc = 0;
-
-		//first free GPR = 0x11b
-	
-		
-		/* FX volume correction and Volume control*/
-		INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0);
-		GET_OUTPUT_GPR(patch, 0x100, 0x0);
-		GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff);
-		GET_DYNAMIC_GPR(patch, 0x112);
-
-		OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4	
-		OP(0, 0x100, 0x040, 0x112, 0x106);  //*vol	
-		INPUT_PATCH_END(patch);
-
-
-		INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0);
-		GET_OUTPUT_GPR(patch, 0x101, 0x1);
-		GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff);
-		GET_DYNAMIC_GPR(patch, 0x112);
-
-		OP(4, 0x112, 0x40, PCM_IN_R, 0x44); 
-		OP(0, 0x101, 0x040, 0x112, 0x107);
-
-		INPUT_PATCH_END(patch);
-
-
-		// CD-Digital In Volume control	
-		INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0);
-		GET_OUTPUT_GPR(patch, 0x10c, 0x12);
-		GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff);
-
-		OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d);
-		INPUT_PATCH_END(patch);
-
-		INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0);
-		GET_OUTPUT_GPR(patch, 0x10e, 0x13);
-		GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff);
-
-		OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f);
-		INPUT_PATCH_END(patch);
-
-		//Volume Correction for Multi-channel Inputs	
-		INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0);
-		patch->input=patch->output=0x3F00;
-
-		GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L);
-		GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R);
-		GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L);
-		GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R);
-		GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER);
-		GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE);
-
-		OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44);
-		OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44);
-		OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44);
-		OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44);
-		OP(4, 0x117, 0x40, MULTI_CENTER, 0x44);
-		OP(4, 0x118, 0x40, MULTI_LFE, 0x44);
-	
-		INPUT_PATCH_END(patch);
-
-
-		//Routing patch start	
-		ROUTING_PATCH_START(rpatch, "Routing");
-		GET_INPUT_GPR(rpatch, 0x100, 0x0);
-		GET_INPUT_GPR(rpatch, 0x101, 0x1);
-		GET_INPUT_GPR(rpatch, 0x10c, 0x12);
-		GET_INPUT_GPR(rpatch, 0x10e, 0x13);
-		GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L);
-		GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R);
-		GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L);
-		GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R);
-		GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER);
-		GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE);
-
-		GET_DYNAMIC_GPR(rpatch, 0x102);
-		GET_DYNAMIC_GPR(rpatch, 0x103);
-
-		GET_OUTPUT_GPR(rpatch, 0x104, 0x8);
-		GET_OUTPUT_GPR(rpatch, 0x105, 0x9);
-		GET_OUTPUT_GPR(rpatch, 0x10a, 0x2);
-		GET_OUTPUT_GPR(rpatch, 0x10b, 0x3);
-		
-		
-		/* input buffer */
-		OP(6, 0x102, AC97_IN_L, 0x40, 0x40);
-		OP(6, 0x103, AC97_IN_R, 0x40, 0x40);
-
-
-		/* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/
-		OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113);
-
-		CONNECT(MULTI_FRONT_L, AC97_FRONT_L);
-		CONNECT(PCM_IN_L, AC97_FRONT_L);
-		CONNECT(SPDIF_CD_L, AC97_FRONT_L);
-
-		OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114);
-
-		CONNECT(MULTI_FRONT_R, AC97_FRONT_R);
-		CONNECT(PCM_IN_R, AC97_FRONT_R);
-		CONNECT(SPDIF_CD_R, AC97_FRONT_R);
-
-		/* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */ 
-		OP(6, 0x104, PCM1_IN_L, 0x100, 0x115);
-		OP(6, 0x104, 0x104, 0x10c, 0x102);
-
-		CONNECT(MULTI_REAR_L, ANALOG_REAR_L);
-		CONNECT(AC97_IN_L, ANALOG_REAR_L);
-		CONNECT(PCM_IN_L, ANALOG_REAR_L);
-		CONNECT(SPDIF_CD_L, ANALOG_REAR_L);
-		CONNECT(PCM1_IN_L, ANALOG_REAR_L);
-
-		OP(6, 0x105, PCM1_IN_R, 0x101, 0x116);
-		OP(6, 0x105, 0x105, 0x10e, 0x103);
-
-		CONNECT(MULTI_REAR_R, ANALOG_REAR_R);
-		CONNECT(AC97_IN_R, ANALOG_REAR_R);
-		CONNECT(PCM_IN_R, ANALOG_REAR_R);
-		CONNECT(SPDIF_CD_R, ANALOG_REAR_R);
-		CONNECT(PCM1_IN_R, ANALOG_REAR_R);
-
-		/* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
-		OP(6, 0x10b, 0x100, 0x102, 0x10c);
-		OP(6, 0x10b, 0x10b, 0x113, 0x40);
-
-		CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
-		CONNECT(PCM_IN_L, DIGITAL_OUT_L);
-		CONNECT(AC97_IN_L, DIGITAL_OUT_L);
-		CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
-
-		OP(6, 0x10a, 0x101, 0x103, 0x10e);
-		OP(6, 0x10b, 0x10b, 0x114, 0x40);
-
-		CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
-		CONNECT(PCM_IN_R, DIGITAL_OUT_R);
-		CONNECT(AC97_IN_R, DIGITAL_OUT_R);
-		CONNECT(SPDIF_CD_R, DIGITAL_OUT_R);
-
-		/* AC97 In --> ADC Recording Buffer */
-		OP(6, ADC_REC_L, 0x102, 0x40, 0x40);
-
-		CONNECT(AC97_IN_L, ADC_REC_L);
-
-		OP(6, ADC_REC_R, 0x103, 0x40, 0x40);
-
-		CONNECT(AC97_IN_R, ADC_REC_R);
-
-
-		/* fx12:Analog-Center */
-		OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40);
-		CONNECT(MULTI_CENTER, ANALOG_CENTER);
-
-		/* fx11:Analog-LFE */
-		OP(6, ANALOG_LFE, 0x118, 0x40, 0x40);
-		CONNECT(MULTI_LFE, ANALOG_LFE);
-
-		/* fx12:Digital-Center */
-		OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40);
-		CONNECT(MULTI_CENTER, DIGITAL_CENTER);
-		
-		/* fx11:Analog-LFE */
-		OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40);
-		CONNECT(MULTI_LFE, DIGITAL_LFE);
-	
-		ROUTING_PATCH_END(rpatch);
-
-
-		// Rear volume control	
-		OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0);
-		GET_INPUT_GPR(patch, 0x104, 0x8);
-		GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff);
-
-		OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119);
-		OUTPUT_PATCH_END(patch);
-
-		OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0);
-		GET_INPUT_GPR(patch, 0x105, 0x9);
-		GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff);
-
-		OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a);
-		OUTPUT_PATCH_END(patch);
-
-
-		//Master volume control on front-digital	
-		OUTPUT_PATCH_START(patch, "Vol Master L", 0x2, 1);
-		GET_INPUT_GPR(patch, 0x10a, 0x2);
-		GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff);
-
-		OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108);
-		OUTPUT_PATCH_END(patch);
-
-
-		OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1);
-		GET_INPUT_GPR(patch, 0x10b, 0x3);
-		GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff);
-
-		OP(0, DIGITAL_OUT_R, 0x040, 0x10b, 0x109);
-		OUTPUT_PATCH_END(patch);
-
-
-		/* delimiter patch */
-		patch = PATCH(mgr, patch_n);
-		patch->code_size = 0;
-
-	
-		sblive_writeptr(card, DBG, 0, 0);
-	}
-
-	spin_lock_init(&mgr->lock);
-
-	// Set up Volume controls, try to keep this the same for both Audigy and Live
-
-	//Master volume
-	mgr->ctrl_gpr[SOUND_MIXER_VOLUME][0] = 8;
-	mgr->ctrl_gpr[SOUND_MIXER_VOLUME][1] = 9;
-
-	left = card->ac97->mixer_state[SOUND_MIXER_VOLUME] & 0xff;
-	right = (card->ac97->mixer_state[SOUND_MIXER_VOLUME] >> 8) & 0xff;
-
-	emu10k1_set_volume_gpr(card, 8, left, 1 << card->ac97->bit_resolution);
-	emu10k1_set_volume_gpr(card, 9, right, 1 << card->ac97->bit_resolution);
-
-	//Rear volume
-	mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][0] = 0x19;
-	mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][1] = 0x1a;
-
-	left = right = 67;
-	card->ac97->mixer_state[SOUND_MIXER_OGAIN] = (right << 8) | left;
-
-	card->ac97->supported_mixers |= SOUND_MASK_OGAIN;
-	card->ac97->stereo_mixers |= SOUND_MASK_OGAIN;
-
-	emu10k1_set_volume_gpr(card, 0x19, left, VOL_5BIT);
-	emu10k1_set_volume_gpr(card, 0x1a, right, VOL_5BIT);
-
-	//PCM Volume
-	mgr->ctrl_gpr[SOUND_MIXER_PCM][0] = 6;
-	mgr->ctrl_gpr[SOUND_MIXER_PCM][1] = 7;
-
-	left = card->ac97->mixer_state[SOUND_MIXER_PCM] & 0xff;
-	right = (card->ac97->mixer_state[SOUND_MIXER_PCM] >> 8) & 0xff;
-
-	emu10k1_set_volume_gpr(card, 6, left, VOL_5BIT);
-	emu10k1_set_volume_gpr(card, 7, right, VOL_5BIT);
-
-	//CD-Digital Volume
-	mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][0] = 0xd;
-	mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][1] = 0xf;
-
-	left = right = 67;
-	card->ac97->mixer_state[SOUND_MIXER_DIGITAL1] = (right << 8) | left; 
-
-	card->ac97->supported_mixers |= SOUND_MASK_DIGITAL1;
-	card->ac97->stereo_mixers |= SOUND_MASK_DIGITAL1;
-
-	emu10k1_set_volume_gpr(card, 0xd, left, VOL_5BIT);
-	emu10k1_set_volume_gpr(card, 0xf, right, VOL_5BIT);
-
-
-	//hard wire the ac97's pcm, pcm volume is done above using dsp code.
-	if (card->is_audigy)
-		//for Audigy, we mute it and use the philips 6 channel DAC instead
-		emu10k1_ac97_write(card->ac97, 0x18, 0x8000);
-	else
-		//For the Live we hardwire it to full volume
-		emu10k1_ac97_write(card->ac97, 0x18, 0x0);
-
-	//remove it from the ac97_codec's control
-	card->ac97_supported_mixers &= ~SOUND_MASK_PCM;
-	card->ac97_stereo_mixers &= ~SOUND_MASK_PCM;
-
-	//set Igain to 0dB by default, maybe consider hardwiring it here.
-	emu10k1_ac97_write(card->ac97, AC97_RECORD_GAIN, 0x0000);
-	card->ac97->mixer_state[SOUND_MIXER_IGAIN] = 0x101; 
-
-	return 0;
-}
-
-static int __devinit hw_init(struct emu10k1_card *card)
-{
-	int nCh;
-	u32 pagecount; /* tmp */
-	int ret;
-
-	/* Disable audio and lock cache */
-	emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
-
-	/* Reset recording buffers */
-	sblive_writeptr_tag(card, 0,
-			    MICBS, ADCBS_BUFSIZE_NONE,
-			    MICBA, 0,
-			    FXBS, ADCBS_BUFSIZE_NONE,
-			    FXBA, 0,
-			    ADCBS, ADCBS_BUFSIZE_NONE,
-			    ADCBA, 0,
-			    TAGLIST_END);
-
-	/* Disable channel interrupt */
-	emu10k1_writefn0(card, INTE, 0);
-	sblive_writeptr_tag(card, 0,
-			    CLIEL, 0,
-			    CLIEH, 0,
-			    SOLEL, 0,
-			    SOLEH, 0,
-			    TAGLIST_END);
-
-	if (card->is_audigy) {
-		sblive_writeptr_tag(card,0,
-				    0x5e,0xf00,
-				    0x5f,0x3,
-				    TAGLIST_END);
-	}
-
-	/* Init envelope engine */
-	for (nCh = 0; nCh < NUM_G; nCh++) {
-		sblive_writeptr_tag(card, nCh,
-				    DCYSUSV, 0,
-				    IP, 0,
-				    VTFT, 0xffff,
-				    CVCF, 0xffff,
-				    PTRX, 0,
-				    //CPF, 0,
-				    CCR, 0,
-
-				    PSST, 0,
-				    DSL, 0x10,
-				    CCCA, 0,
-				    Z1, 0,
-				    Z2, 0,
-				    FXRT, 0xd01c0000,
-
-				    ATKHLDM, 0,
-				    DCYSUSM, 0,
-				    IFATN, 0xffff,
-				    PEFE, 0,
-				    FMMOD, 0,
-				    TREMFRQ, 24,	/* 1 Hz */
-				    FM2FRQ2, 24,	/* 1 Hz */
-				    TEMPENV, 0,
-
-				    /*** These are last so OFF prevents writing ***/
-				    LFOVAL2, 0,
-				    LFOVAL1, 0,
-				    ATKHLDV, 0,
-				    ENVVOL, 0,
-				    ENVVAL, 0,
-                                    TAGLIST_END);
-		sblive_writeptr(card, CPF, nCh, 0);
-		/*
-		  Audigy FXRT initialization
-		  reversed eng'd, may not be accurate.
-		 */
-		if (card->is_audigy) {
-			sblive_writeptr_tag(card,nCh,
-					    0x4c,0x0,
-					    0x4d,0x0,
-					    0x4e,0x0,
-					    0x4f,0x0,
-					    A_FXRT1, 0x3f3f3f3f,
-					    A_FXRT2, 0x3f3f3f3f,
-					    A_SENDAMOUNTS, 0,
-					    TAGLIST_END);
-		}
-	}
-	
-
-	/*
-	 ** Init to 0x02109204 :
-	 ** Clock accuracy    = 0     (1000ppm)
-	 ** Sample Rate       = 2     (48kHz)
-	 ** Audio Channel     = 1     (Left of 2)
-	 ** Source Number     = 0     (Unspecified)
-	 ** Generation Status = 1     (Original for Cat Code 12)
-	 ** Cat Code          = 12    (Digital Signal Mixer)
-	 ** Mode              = 0     (Mode 0)
-	 ** Emphasis          = 0     (None)
-	 ** CP                = 1     (Copyright unasserted)
-	 ** AN                = 0     (Digital audio)
-	 ** P                 = 0     (Consumer)
-	 */
-
-	sblive_writeptr_tag(card, 0,
-
-			    /* SPDIF0 */
-			    SPCS0, (SPCS_CLKACCY_1000PPM | 0x002000000 |
-				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
-			    /* SPDIF1 */
-			    SPCS1, (SPCS_CLKACCY_1000PPM | 0x002000000 |
-				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
-			    /* SPDIF2 & SPDIF3 */
-			    SPCS2, (SPCS_CLKACCY_1000PPM | 0x002000000 |
-				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
-			    TAGLIST_END);
-
-	if (card->is_audigy && (card->chiprev == 4)) {
-		/* Hacks for Alice3 to work independent of haP16V driver */
-		u32 tmp;
-
-		//Setup SRCMulti_I2S SamplingRate
-		tmp = sblive_readptr(card, A_SPDIF_SAMPLERATE, 0);
-		tmp &= 0xfffff1ff;
-		tmp |= (0x2<<9);
-		sblive_writeptr(card, A_SPDIF_SAMPLERATE, 0, tmp);
-
-		/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
-		emu10k1_writefn0(card, 0x20, 0x600000);
-		emu10k1_writefn0(card, 0x24, 0x14);
-
-		/* Setup SRCMulti Input Audio Enable */
-		emu10k1_writefn0(card, 0x20, 0x6E0000);
-		emu10k1_writefn0(card, 0x24, 0xFF00FF00);
-	}
-
-	ret = fx_init(card);		/* initialize effects engine */
-	if (ret < 0)
-		return ret;
-
-	card->tankmem.size = 0;
-
-	card->virtualpagetable.size = MAXPAGES * sizeof(u32);
-
-	card->virtualpagetable.addr = pci_alloc_consistent(card->pci_dev, card->virtualpagetable.size, &card->virtualpagetable.dma_handle);
-	if (card->virtualpagetable.addr == NULL) {
-		ERROR();
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	card->silentpage.size = EMUPAGESIZE;
-
-	card->silentpage.addr = pci_alloc_consistent(card->pci_dev, card->silentpage.size, &card->silentpage.dma_handle);
-	if (card->silentpage.addr == NULL) {
-		ERROR();
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
-		((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pagecount);
-
-	/* Init page table & tank memory base register */
-	sblive_writeptr_tag(card, 0,
-			    PTB, (u32) card->virtualpagetable.dma_handle,
-			    TCB, 0,
-			    TCBS, 0,
-			    TAGLIST_END);
-
-	for (nCh = 0; nCh < NUM_G; nCh++) {
-		sblive_writeptr_tag(card, nCh,
-				    MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				    MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				    TAGLIST_END);
-	}
-
-	/* Hokay, now enable the AUD bit */
-	/* Enable Audio = 1 */
-	/* Mute Disable Audio = 0 */
-	/* Lock Tank Memory = 1 */
-	/* Lock Sound Memory = 0 */
-	/* Auto Mute = 1 */
-	if (card->is_audigy) {
-		if (card->chiprev == 4)
-			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_AC3ENABLE_CDSPDIF | HCFG_AC3ENABLE_GPSPDIF | HCFG_AUTOMUTE | HCFG_JOYENABLE);
-		else
-			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_AUTOMUTE | HCFG_JOYENABLE);
-	} else {
-		if (card->model == 0x20 || card->model == 0xc400 ||
-		 (card->model == 0x21 && card->chiprev < 6))
-	        	emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
-		else
-			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);
-	}
-	/* Enable Vol_Ctrl irqs */
-	emu10k1_irq_enable(card, INTE_VOLINCRENABLE | INTE_VOLDECRENABLE | INTE_MUTEENABLE | INTE_FXDSPENABLE);
-
-	if (card->is_audigy && (card->chiprev == 4)) {
-		/* Unmute Analog now.  Set GPO6 to 1 for Apollo.
-		 * This has to be done after init ALice3 I2SOut beyond 48KHz.
-		 * So, sequence is important. */
-		u32 tmp = emu10k1_readfn0(card, A_IOCFG);
-		tmp |= 0x0040;
-		emu10k1_writefn0(card, A_IOCFG, tmp);
-	}
-	
-	/* FIXME: TOSLink detection */
-	card->has_toslink = 0;
-
-	/* Initialize digital passthrough variables */
-	card->pt.pos_gpr = card->pt.intr_gpr = card->pt.enable_gpr = -1;
-	card->pt.selected = 0;
-	card->pt.state = PT_STATE_INACTIVE;
-	card->pt.spcs_to_use = 0x01;
-	card->pt.patch_name = "AC3pass";
-	card->pt.intr_gpr_name = "count";
-	card->pt.enable_gpr_name = "enable";
-	card->pt.pos_gpr_name = "ptr";
-	spin_lock_init(&card->pt.lock);
-	init_waitqueue_head(&card->pt.wait);
-
-/*	tmp = sblive_readfn0(card, HCFG);
-	if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
-		sblive_writefn0(card, HCFG, tmp | 0x800);
-
-		udelay(512);
-
-		if (tmp != (sblive_readfn0(card, HCFG) & ~0x800)) {
-			card->has_toslink = 1;
-			sblive_writefn0(card, HCFG, tmp);
-		}
-	}
-*/
-	return 0;
-
-  err1:
-	pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
-  err0:
-	fx_cleanup(&card->mgr);
-
-	return ret;
-}
-
-static int __devinit emu10k1_init(struct emu10k1_card *card)
-{
-	/* Init Card */
-	if (hw_init(card) < 0)
-		return -1;
-
-	voice_init(card);
-	timer_init(card);
-	addxmgr_init(card);
-
-	DPD(2, "  hw control register -> %#x\n", emu10k1_readfn0(card, HCFG));
-
-	return 0;
-}
-
-static void emu10k1_cleanup(struct emu10k1_card *card)
-{
-	int ch;
-
-	emu10k1_writefn0(card, INTE, 0);
-
-	/** Shutdown the chip **/
-	for (ch = 0; ch < NUM_G; ch++)
-		sblive_writeptr(card, DCYSUSV, ch, 0);
-
-	for (ch = 0; ch < NUM_G; ch++) {
-		sblive_writeptr_tag(card, ch,
-				    VTFT, 0,
-				    CVCF, 0,
-				    PTRX, 0,
-				    //CPF, 0,
-				    TAGLIST_END);
-		sblive_writeptr(card, CPF, ch, 0);
-	}
-
-	/* Disable audio and lock cache */
-	emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
-
-	sblive_writeptr_tag(card, 0,
-                            PTB, 0,
-
-			    /* Reset recording buffers */
-			    MICBS, ADCBS_BUFSIZE_NONE,
-			    MICBA, 0,
-			    FXBS, ADCBS_BUFSIZE_NONE,
-			    FXBA, 0,
-			    FXWC, 0,
-			    ADCBS, ADCBS_BUFSIZE_NONE,
-			    ADCBA, 0,
-			    TCBS, 0,
-			    TCB, 0,
-			    DBG, 0x8000,
-
-			    /* Disable channel interrupt */
-			    CLIEL, 0,
-			    CLIEH, 0,
-			    SOLEL, 0,
-			    SOLEH, 0,
-			    TAGLIST_END);
-
-	if (card->is_audigy)
-		sblive_writeptr(card, 0, A_DBG,  A_DBG_SINGLE_STEP);
-
-	pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
-	pci_free_consistent(card->pci_dev, card->silentpage.size, card->silentpage.addr, card->silentpage.dma_handle);
-	
-	if(card->tankmem.size != 0)
-		pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
-
-	/* release patch storage memory */
-	fx_cleanup(&card->mgr);
-}
-
-/* Driver initialization routine */
-static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
-{
-	struct emu10k1_card *card;
-	u32 subsysvid;
-	int ret;
-
-	if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) {
-		printk(KERN_ERR "emu10k1: architecture does not support 29bit PCI busmaster DMA\n");
-		return -ENODEV;
-	}
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
-
-	pci_set_master(pci_dev);
-
-	if ((card = kzalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
-                printk(KERN_ERR "emu10k1: out of memory\n");
-                return -ENOMEM;
-        }
-
-	card->iobase = pci_resource_start(pci_dev, 0);
-	card->length = pci_resource_len(pci_dev, 0); 
-
-	if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) {
-		printk(KERN_ERR "emu10k1: IO space in use\n");
-		ret = -EBUSY;
-		goto err_region;
-	}
-
-	pci_set_drvdata(pci_dev, card);
-
-	card->irq = pci_dev->irq;
-	card->pci_dev = pci_dev;
-
-	/* Reserve IRQ Line */
-	if (request_irq(card->irq, emu10k1_interrupt, IRQF_SHARED, card_names[pci_id->driver_data], card)) {
-		printk(KERN_ERR "emu10k1: IRQ in use\n");
-		ret = -EBUSY;
-		goto err_irq;
-	}
-
-	card->chiprev = pci_dev->revision;
-	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
-
-	printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n",
-		card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
-		card->iobase + card->length - 1, card->irq);
-
-	if (pci_id->device == PCI_DEVICE_ID_CREATIVE_AUDIGY)
-		card->is_audigy = 1;
-
-	pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
-	card->is_aps = (subsysvid == EMU_APS_SUBID);
-
-	spin_lock_init(&card->lock);
-	mutex_init(&card->open_sem);
-	card->open_mode = 0;
-	init_waitqueue_head(&card->open_wait);
-
-	ret = emu10k1_audio_init(card);
-	if (ret < 0) {
-                printk(KERN_ERR "emu10k1: cannot initialize audio devices\n");
-                goto err_audio;
-        }
-
-	ret = emu10k1_mixer_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot initialize AC97 codec\n");
-                goto err_mixer;
-	}
-
-	ret = emu10k1_midi_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot register midi device\n");
-		goto err_midi;
-	}
-
-	ret = emu10k1_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot initialize device\n");
-		goto err_emu10k1_init;
-	}
-
-	if (card->is_aps)
-		emu10k1_ecard_init(card);
-
-	ret = emu10k1_register_devices(card);
-	if (ret < 0)
-		goto err_register;
-
-	/* proc entries must be created after registering devices, as
-	 * emu10k1_info_proc prints card->audio_dev &co. */
-	ret = emu10k1_proc_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot initialize proc directory\n");
-                goto err_proc;
-	}
-	
-	list_add(&card->list, &emu10k1_devs);
-
-	return 0;
-
-err_proc:
-	emu10k1_unregister_devices(card);
-
-err_register:
-	emu10k1_cleanup(card);
-	
-err_emu10k1_init:
-	emu10k1_midi_cleanup(card);
-
-err_midi:
-	emu10k1_mixer_cleanup(card);
-
-err_mixer:
-	emu10k1_audio_cleanup(card);
-
-err_audio:
-	free_irq(card->irq, card);
-
-err_irq:
-	release_region(card->iobase, card->length);
-	pci_set_drvdata(pci_dev, NULL);
-
-err_region:
-	kfree(card);
-
-	return ret;
-}
-
-static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
-{
-	struct emu10k1_card *card = pci_get_drvdata(pci_dev);
-
-	list_del(&card->list);
-
-	emu10k1_unregister_devices(card);
-	emu10k1_cleanup(card);
-	emu10k1_midi_cleanup(card);
-	emu10k1_mixer_cleanup(card);
-	emu10k1_proc_cleanup(card);
-	emu10k1_audio_cleanup(card);	
-	free_irq(card->irq, card);
-	release_region(card->iobase, card->length);
-	kfree(card);
-	pci_set_drvdata(pci_dev, NULL);
-}
-
-MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@lists.sourceforge.net)");
-MODULE_DESCRIPTION("Creative EMU10K1 PCI Audio Driver v" DRIVER_VERSION "\nCopyright (C) 1999 Creative Technology Ltd.");
-MODULE_LICENSE("GPL");
-
-static struct pci_driver emu10k1_pci_driver = {
-	.name		= "emu10k1",
-	.id_table	= emu10k1_pci_tbl,
-	.probe		= emu10k1_probe,
-	.remove		= __devexit_p(emu10k1_remove),
-};
-
-static int __init emu10k1_init_module(void)
-{
-	printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
-
-	return pci_register_driver(&emu10k1_pci_driver);
-}
-
-static void __exit emu10k1_cleanup_module(void)
-{
-	pci_unregister_driver(&emu10k1_pci_driver);
-
-	return;
-}
-
-module_init(emu10k1_init_module);
-module_exit(emu10k1_cleanup_module);
-
-#ifdef EMU10K1_SEQUENCER
-
-/* in midi.c */
-extern int emu10k1_seq_midi_open(int dev, int mode, 
-				void (*input)(int dev, unsigned char midi_byte),
-				void (*output)(int dev));
-extern void emu10k1_seq_midi_close(int dev);
-extern int emu10k1_seq_midi_out(int dev, unsigned char midi_byte);
-extern int emu10k1_seq_midi_start_read(int dev);
-extern int emu10k1_seq_midi_end_read(int dev);
-extern void emu10k1_seq_midi_kick(int dev);
-extern int emu10k1_seq_midi_buffer_status(int dev);
-
-static struct midi_operations emu10k1_midi_operations =
-{
-	THIS_MODULE,
-	{"EMU10K1 MIDI", 0, 0, SNDCARD_EMU10K1},
-	&std_midi_synth,
-	{0},
-	emu10k1_seq_midi_open,
-	emu10k1_seq_midi_close,
-	NULL,
-	emu10k1_seq_midi_out,
-	emu10k1_seq_midi_start_read,
-	emu10k1_seq_midi_end_read,
-	emu10k1_seq_midi_kick,
-	NULL,
-	emu10k1_seq_midi_buffer_status,
-	NULL
-};
-
-#endif
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
deleted file mode 100644
index df1e990..0000000
--- a/sound/oss/emu10k1/midi.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- **********************************************************************
- *     midi.c - /dev/midi interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-
-#include "hwaccess.h"
-#include "cardmo.h"
-#include "cardmi.h"
-#include "midi.h"
-
-#ifdef EMU10K1_SEQUENCER
-#include "../sound_config.h"
-#endif
-
-static DEFINE_SPINLOCK(midi_spinlock);
-
-static void init_midi_hdr(struct midi_hdr *midihdr)
-{
-	midihdr->bufferlength = MIDIIN_BUFLEN;
-	midihdr->bytesrecorded = 0;
-	midihdr->flags = 0;
-}
-
-static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hdr **midihdrptr)
-{
-	struct midi_hdr *midihdr;
-
-	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
-		ERROR();
-		return -EINVAL;
-	}
-
-	init_midi_hdr(midihdr);
-
-	midihdr->data = kmalloc(MIDIIN_BUFLEN, GFP_KERNEL);
-	if (!midihdr->data) {
-		ERROR();
-		kfree(midihdr);
-		return -1;
-	}
-
-	if (emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr) < 0) {
-		ERROR();
-		kfree(midihdr->data);
-		kfree(midihdr);
-		return -1;
-	}
-
-	*midihdrptr = midihdr;
-	list_add_tail(&midihdr->list, &midi_dev->mid_hdrs);
-
-	return 0;
-}
-
-static int emu10k1_midi_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct emu10k1_card *card = NULL;
-	struct emu10k1_mididevice *midi_dev;
-	struct list_head *entry;
-
-	DPF(2, "emu10k1_midi_open()\n");
-
-	/* Check for correct device to open */
-	list_for_each(entry, &emu10k1_devs) {
-		card = list_entry(entry, struct emu10k1_card, list);
-
-		if (card->midi_dev == minor)
-			goto match;
-	}
-
-	return -ENODEV;
-
-match:
-#ifdef EMU10K1_SEQUENCER
-	if (card->seq_mididev)	/* card is opened by sequencer */
-		return -EBUSY;
-#endif
-
-	/* Wait for device to become free */
-	mutex_lock(&card->open_sem);
-	while (card->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
-		if (file->f_flags & O_NONBLOCK) {
-			mutex_unlock(&card->open_sem);
-			return -EBUSY;
-		}
-
-		mutex_unlock(&card->open_sem);
-		interruptible_sleep_on(&card->open_wait);
-
-		if (signal_pending(current)) {
-			return -ERESTARTSYS;
-		}
-
-		mutex_lock(&card->open_sem);
-	}
-
-	if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midi_dev->card = card;
-	midi_dev->mistate = MIDIIN_STATE_STOPPED;
-	init_waitqueue_head(&midi_dev->oWait);
-	init_waitqueue_head(&midi_dev->iWait);
-	midi_dev->ird = 0;
-	midi_dev->iwr = 0;
-	midi_dev->icnt = 0;
-	INIT_LIST_HEAD(&midi_dev->mid_hdrs);
-
-	if (file->f_mode & FMODE_READ) {
-		struct midi_openinfo dsCardMidiOpenInfo;
-		struct midi_hdr *midihdr1;
-		struct midi_hdr *midihdr2;
-
-		dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
-		if (emu10k1_mpuin_open(card, &dsCardMidiOpenInfo) < 0) {
-			ERROR();
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-
-		/* Add two buffers to receive sysex buffer */
-		if (midiin_add_buffer(midi_dev, &midihdr1) < 0) {
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-
-		if (midiin_add_buffer(midi_dev, &midihdr2) < 0) {
-			list_del(&midihdr1->list);
-			kfree(midihdr1->data);
-			kfree(midihdr1);
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		struct midi_openinfo dsCardMidiOpenInfo;
-
-		dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
-		if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
-			ERROR();
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-	}
-
-	file->private_data = (void *) midi_dev;
-
-	card->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
-
-	mutex_unlock(&card->open_sem);
-
-	return nonseekable_open(inode, file);
-}
-
-static int emu10k1_midi_release(struct inode *inode, struct file *file)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	struct emu10k1_card *card;
-
-	lock_kernel();
-
-	card = midi_dev->card;
-	DPF(2, "emu10k1_midi_release()\n");
-
-	if (file->f_mode & FMODE_WRITE) {
-		if (!(file->f_flags & O_NONBLOCK)) {
-
-			while (!signal_pending(current) && (card->mpuout->firstmidiq != NULL)) {
-				DPF(4, "Cannot close - buffers not empty\n");
-
-				interruptible_sleep_on(&midi_dev->oWait);
-
-			}
-		}
-
-		emu10k1_mpuout_close(card);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		struct midi_hdr *midihdr;
-
-		if (midi_dev->mistate == MIDIIN_STATE_STARTED) {
-			emu10k1_mpuin_stop(card);
-			midi_dev->mistate = MIDIIN_STATE_STOPPED;
-		}
-
-		emu10k1_mpuin_reset(card);
-		emu10k1_mpuin_close(card);
-
-		while (!list_empty(&midi_dev->mid_hdrs)) {
-			midihdr = list_entry(midi_dev->mid_hdrs.next, struct midi_hdr, list);
-
-			list_del(midi_dev->mid_hdrs.next);
-			kfree(midihdr->data);
-			kfree(midihdr);
-		}
-	}
-
-	kfree(midi_dev);
-
-	mutex_lock(&card->open_sem);
-	card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE));
-	mutex_unlock(&card->open_sem);
-	wake_up_interruptible(&card->open_wait);
-
-	unlock_kernel();
-
-	return 0;
-}
-
-static ssize_t emu10k1_midi_read(struct file *file, char __user *buffer, size_t count, loff_t * pos)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	ssize_t ret = 0;
-	u16 cnt;
-	unsigned long flags;
-
-	DPD(4, "emu10k1_midi_read(), count %#x\n", (u32) count);
-
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-
-	if (midi_dev->mistate == MIDIIN_STATE_STOPPED) {
-		if (emu10k1_mpuin_start(midi_dev->card) < 0) {
-			ERROR();
-			return -EINVAL;
-		}
-
-		midi_dev->mistate = MIDIIN_STATE_STARTED;
-	}
-
-	while (count > 0) {
-		cnt = MIDIIN_BUFLEN - midi_dev->ird;
-
-		spin_lock_irqsave(&midi_spinlock, flags);
-
-		if (midi_dev->icnt < cnt)
-			cnt = midi_dev->icnt;
-
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-
-		if (cnt > count)
-			cnt = count;
-
-		if (cnt <= 0) {
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			DPF(2, " Go to sleep...\n");
-
-			interruptible_sleep_on(&midi_dev->iWait);
-
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
-
-			continue;
-		}
-
-		if (copy_to_user(buffer, midi_dev->iBuf + midi_dev->ird, cnt)) {
-			ERROR();
-			return ret ? ret : -EFAULT;
-		}
-
-		midi_dev->ird += cnt;
-		midi_dev->ird %= MIDIIN_BUFLEN;
-
-		spin_lock_irqsave(&midi_spinlock, flags);
-
-		midi_dev->icnt -= cnt;
-
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-
-		if (midi_dev->icnt == 0)
-			break;
-	}
-
-	return ret;
-}
-
-static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t * pos)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	struct midi_hdr *midihdr;
-	unsigned long flags;
-
-	DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count);
-
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-
-	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midihdr->bufferlength = count;
-	midihdr->bytesrecorded = 0;
-	midihdr->flags = 0;
-
-	midihdr->data = kmalloc(count, GFP_KERNEL);
-	if (!midihdr->data) {
-		ERROR();
-		kfree(midihdr);
-		return -EINVAL;
-	}
-
-	if (copy_from_user(midihdr->data, buffer, count)) {
-		kfree(midihdr->data);
-		kfree(midihdr);
-		return -EFAULT;
-	}
-
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	if (emu10k1_mpuout_add_buffer(midi_dev->card, midihdr) < 0) {
-		ERROR();
-		kfree(midihdr->data);
-		kfree(midihdr);
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-		return -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return count;
-}
-
-static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	DPF(4, "emu10k1_midi_poll() called\n");
-
-	if (file->f_mode & FMODE_WRITE)
-		poll_wait(file, &midi_dev->oWait, wait);
-
-	if (file->f_mode & FMODE_READ)
-		poll_wait(file, &midi_dev->iWait, wait);
-
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	if (file->f_mode & FMODE_WRITE)
-		mask |= POLLOUT | POLLWRNORM;
-
-	if (file->f_mode & FMODE_READ) {
-		if (midi_dev->mistate == MIDIIN_STATE_STARTED)
-			if (midi_dev->icnt > 0)
-				mask |= POLLIN | POLLRDNORM;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return mask;
-}
-
-int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) refdata;
-	struct midi_hdr *midihdr = NULL;
-	unsigned long flags;
-	int i;
-
-	DPF(4, "emu10k1_midi_callback()\n");
-
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	switch (msg) {
-	case ICARDMIDI_OUTLONGDATA:
-		midihdr = (struct midi_hdr *) pmsg[2];
-
-		kfree(midihdr->data);
-		kfree(midihdr);
-		wake_up_interruptible(&midi_dev->oWait);
-
-		break;
-
-	case ICARDMIDI_INLONGDATA:
-		midihdr = (struct midi_hdr *) pmsg[2];
-
-		for (i = 0; i < midihdr->bytesrecorded; i++) {
-			midi_dev->iBuf[midi_dev->iwr++] = midihdr->data[i];
-			midi_dev->iwr %= MIDIIN_BUFLEN;
-		}
-
-		midi_dev->icnt += midihdr->bytesrecorded;
-
-		if (midi_dev->mistate == MIDIIN_STATE_STARTED) {
-			init_midi_hdr(midihdr);
-			emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr);
-			wake_up_interruptible(&midi_dev->iWait);
-		}
-		break;
-
-	case ICARDMIDI_INDATA:
-		{
-			u8 *pBuf = (u8 *) & pmsg[1];
-			u16 bytesvalid = pmsg[2];
-
-			for (i = 0; i < bytesvalid; i++) {
-				midi_dev->iBuf[midi_dev->iwr++] = pBuf[i];
-				midi_dev->iwr %= MIDIIN_BUFLEN;
-			}
-
-			midi_dev->icnt += bytesvalid;
-		}
-
-		wake_up_interruptible(&midi_dev->iWait);
-		break;
-
-	default:		/* Unknown message */
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-		return -1;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return 0;
-}
-
-/* MIDI file operations */
-const struct file_operations emu10k1_midi_fops = {
-	.owner		= THIS_MODULE,
-	.read		= emu10k1_midi_read,
-	.write		= emu10k1_midi_write,
-	.poll		= emu10k1_midi_poll,
-	.open		= emu10k1_midi_open,
-	.release	= emu10k1_midi_release,
-};
-
-
-#ifdef EMU10K1_SEQUENCER
-
-/* functions used for sequencer access */
-
-int emu10k1_seq_midi_open(int dev, int mode,
-				void (*input) (int dev, unsigned char data),
-				void (*output) (int dev))
-{
-	struct emu10k1_card *card;
-	struct midi_openinfo dsCardMidiOpenInfo;
-	struct emu10k1_mididevice *midi_dev;
-
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return -EINVAL;
-
-	card = midi_devs[dev]->devc;
-
-	if (card->open_mode)		/* card is opened native */
-		return -EBUSY;
-			
-	DPF(2, "emu10k1_seq_midi_open()\n");
-	
-	if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midi_dev->card = card;
-	midi_dev->mistate = MIDIIN_STATE_STOPPED;
-	init_waitqueue_head(&midi_dev->oWait);
-	init_waitqueue_head(&midi_dev->iWait);
-	midi_dev->ird = 0;
-	midi_dev->iwr = 0;
-	midi_dev->icnt = 0;
-	INIT_LIST_HEAD(&midi_dev->mid_hdrs);
-
-	dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
-	if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
-		ERROR();
-		return -ENODEV;
-	}
-
-	card->seq_mididev = midi_dev;
-		
-	return 0;
-}
-
-void emu10k1_seq_midi_close(int dev)
-{
-	struct emu10k1_card *card;
-
-	DPF(2, "emu10k1_seq_midi_close()\n");
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return;
-
-	card = midi_devs[dev]->devc;
-	emu10k1_mpuout_close(card);
-
-	kfree(card->seq_mididev);
-	card->seq_mididev = NULL;
-}
-
-int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
-{
-	struct emu10k1_card *card;
-	struct midi_hdr *midihdr;
-	unsigned long flags;
-
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return -EINVAL;
-
-	card = midi_devs[dev]->devc;
-
-	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midihdr->bufferlength = 1;
-	midihdr->bytesrecorded = 0;
-	midihdr->flags = 0;
-
-	midihdr->data = kmalloc(1, GFP_KERNEL);
-	if (!midihdr->data) {
-		ERROR();
-		kfree(midihdr);
-		return -EINVAL;
-	}
-
-	*(midihdr->data) = midi_byte;
-	
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	if (emu10k1_mpuout_add_buffer(card, midihdr) < 0) {
-		ERROR();
-		kfree(midihdr->data);
-		kfree(midihdr);
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-		return -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return 1;
-}
-
-int emu10k1_seq_midi_start_read(int dev)
-{
-	return 0;
-}
-
-int emu10k1_seq_midi_end_read(int dev)
-{
-	return 0;
-}
-
-void emu10k1_seq_midi_kick(int dev)
-{
-}
-
-int emu10k1_seq_midi_buffer_status(int dev)
-{
-	int count;
-	struct midi_queue *queue;
-	struct emu10k1_card *card;
-
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return -EINVAL;
-
-	count = 0;
-
-	card = midi_devs[dev]->devc;
-	queue = card->mpuout->firstmidiq;
-
-	while (queue != NULL) {
-		count++;
-		if (queue == card->mpuout->lastmidiq)
-			break;
-
-		queue = queue->next;
-	}
-
-	return count;
-}
-
-#endif
-
diff --git a/sound/oss/emu10k1/midi.h b/sound/oss/emu10k1/midi.h
deleted file mode 100644
index 2459ec9..0000000
--- a/sound/oss/emu10k1/midi.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*     
- **********************************************************************
- *     midi.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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 _MIDI_H
-#define _MIDI_H
-
-#define FMODE_MIDI_SHIFT 3
-#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)
-#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
-
-#define MIDIIN_STATE_STARTED 0x00000001
-#define MIDIIN_STATE_STOPPED 0x00000002
-
-#define MIDIIN_BUFLEN 1024
-
-struct emu10k1_mididevice
-{
-	struct emu10k1_card *card;
-	u32 mistate;
-	wait_queue_head_t oWait;
-	wait_queue_head_t iWait;
-	s8 iBuf[MIDIIN_BUFLEN];
-	u16 ird, iwr, icnt;
-	struct list_head mid_hdrs;
-};
-
-/* uncomment next line to use midi port on Audigy drive */
-//#define USE_AUDIGY_DRIVE_MIDI
-
-#ifdef USE_AUDIGY_DRIVE_MIDI
-#define A_MUDATA	A_MUDATA2
-#define A_MUCMD		A_MUCMD2
-#define A_MUSTAT	A_MUCMD2
-#define A_IPR_MIDITRANSBUFEMPTY	A_IPR_MIDITRANSBUFEMPTY2
-#define A_IPR_MIDIRECVBUFEMPTY	A_IPR_MIDIRECVBUFEMPTY2
-#define A_INTE_MIDITXENABLE	A_INTE_MIDITXENABLE2
-#define A_INTE_MIDIRXENABLE	A_INTE_MIDIRXENABLE2
-#else
-#define A_MUDATA	A_MUDATA1
-#define A_MUCMD		A_MUCMD1
-#define A_MUSTAT	A_MUCMD1
-#define A_IPR_MIDITRANSBUFEMPTY	A_IPR_MIDITRANSBUFEMPTY1
-#define A_IPR_MIDIRECVBUFEMPTY	A_IPR_MIDIRECVBUFEMPTY1
-#define A_INTE_MIDITXENABLE	A_INTE_MIDITXENABLE1
-#define A_INTE_MIDIRXENABLE	A_INTE_MIDIRXENABLE1
-#endif
-
-
-#endif /* _MIDI_H */
-
diff --git a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
deleted file mode 100644
index bc3805f..0000000
--- a/sound/oss/emu10k1/mixer.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- **********************************************************************
- *     mixer.c - /dev/mixer interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        cleaned up stuff
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/fs.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "recmgr.h"
-
-
-static const u32 bass_table[41][5] = {
-	{ 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
-	{ 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
-	{ 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
-	{ 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
-	{ 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
-	{ 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
-	{ 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
-	{ 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
-	{ 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
-	{ 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
-	{ 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
-	{ 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
-	{ 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
-	{ 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
-	{ 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
-	{ 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
-	{ 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
-	{ 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
-	{ 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
-	{ 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
-	{ 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
-	{ 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
-	{ 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
-	{ 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
-	{ 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
-	{ 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
-	{ 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
-	{ 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
-	{ 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
-	{ 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
-	{ 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
-	{ 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
-	{ 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
-	{ 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
-	{ 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
-	{ 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
-	{ 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
-	{ 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
-	{ 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
-	{ 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
-	{ 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
-};
-
-static const u32 treble_table[41][5] = {
-	{ 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
-	{ 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
-	{ 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
-	{ 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
-	{ 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
-	{ 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
-	{ 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
-	{ 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
-	{ 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
-	{ 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
-	{ 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
-	{ 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
-	{ 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
-	{ 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
-	{ 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
-	{ 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
-	{ 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
-	{ 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
-	{ 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
-	{ 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
-	{ 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
-	{ 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
-	{ 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
-	{ 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
-	{ 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
-	{ 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
-	{ 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
-	{ 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
-	{ 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
-	{ 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
-	{ 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
-	{ 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
-	{ 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
-	{ 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
-	{ 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
-	{ 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
-	{ 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
-	{ 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
-	{ 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
-	{ 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
-	{ 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
-};
-
-
-static void set_bass(struct emu10k1_card *card, int l, int r)
-{
-	int i;
-
-	l = (l * 40 + 50) / 100;
-	r = (r * 40 + 50) / 100;
-
-	for (i = 0; i < 5; i++)
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]);
-}
-
-static void set_treble(struct emu10k1_card *card, int l, int r)
-{
-	int i;
-
-	l = (l * 40 + 50) / 100;
-	r = (r * 40 + 50) / 100;
-
-	for (i = 0; i < 5; i++)
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]);
-}
-
-const char volume_params[SOUND_MIXER_NRDEVICES]= {
-/* Used by the ac97 driver */
-	[SOUND_MIXER_VOLUME]	=	VOL_6BIT,
-	[SOUND_MIXER_BASS]	=	VOL_4BIT,
-	[SOUND_MIXER_TREBLE]	=	VOL_4BIT,
-	[SOUND_MIXER_PCM]	=	VOL_5BIT,
-	[SOUND_MIXER_SPEAKER]	=	VOL_4BIT,
-	[SOUND_MIXER_LINE]	=	VOL_5BIT,
-	[SOUND_MIXER_MIC]	=	VOL_5BIT,
-	[SOUND_MIXER_CD]	=	VOL_5BIT,
-	[SOUND_MIXER_ALTPCM]	=	VOL_6BIT,
-	[SOUND_MIXER_IGAIN]	=	VOL_4BIT,
-	[SOUND_MIXER_LINE1]	=	VOL_5BIT,
-	[SOUND_MIXER_PHONEIN]	= 	VOL_5BIT,
-	[SOUND_MIXER_PHONEOUT]	= 	VOL_6BIT,
-	[SOUND_MIXER_VIDEO]	=	VOL_5BIT,
-/* Not used by the ac97 driver */
-	[SOUND_MIXER_SYNTH]	=	VOL_5BIT,
-	[SOUND_MIXER_IMIX]	=	VOL_5BIT,
-	[SOUND_MIXER_RECLEV]	=	VOL_5BIT,
-	[SOUND_MIXER_OGAIN]	=	VOL_5BIT,
-	[SOUND_MIXER_LINE2]	=	VOL_5BIT,
-	[SOUND_MIXER_LINE3]	=	VOL_5BIT,
-	[SOUND_MIXER_DIGITAL1]	=	VOL_5BIT,
-	[SOUND_MIXER_DIGITAL2]	=	VOL_5BIT,
-	[SOUND_MIXER_DIGITAL3]	=	VOL_5BIT,
-	[SOUND_MIXER_RADIO]	=	VOL_5BIT,
-	[SOUND_MIXER_MONITOR]	=	VOL_5BIT
-};
-
-/* Mixer file operations */
-static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, unsigned long arg)
-{
-	struct mixer_private_ioctl *ctl;
-	struct dsp_patch *patch;
-	u32 size, page;
-	int addr, size_reg, i, ret;
-	unsigned int id, ch;
-	void __user *argp = (void __user *)arg;
-
-	switch (cmd) {
-
-	case SOUND_MIXER_PRIVATE3:
-
-		ctl = kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
-		if (ctl == NULL)
-			return -ENOMEM;
-
-		if (copy_from_user(ctl, argp, sizeof(struct mixer_private_ioctl))) {
-			kfree(ctl);
-			return -EFAULT;
-		}
-
-		ret = 0;
-		switch (ctl->cmd) {
-#ifdef DBGEMU
-		case CMD_WRITEFN0:
-			emu10k1_writefn0_2(card, ctl->val[0], ctl->val[1], ctl->val[2]);
-			break;
-#endif
-		case CMD_WRITEPTR:
-#ifdef DBGEMU
-			if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000) {
-#else
-			if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000 || ((ctl->val[0] < 0x100 ) &&
-		    //Any register allowed raw access goes here:
-				     (ctl->val[0] != A_SPDIF_SAMPLERATE) && (ctl->val[0] != A_DBG)
-			)
-				) {
-#endif
-				ret = -EINVAL;
-				break;
-			}
-			sblive_writeptr(card, ctl->val[0], ctl->val[1], ctl->val[2]);
-			break;
-
-		case CMD_READFN0:
-			ctl->val[2] = emu10k1_readfn0(card, ctl->val[0]);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_READPTR:
-			if (ctl->val[1] >= 0x40 || (ctl->val[0] & 0x7ff) > 0xff) {
-				ret = -EINVAL;
-				break;
-			}
-
-			if ((ctl->val[0] & 0x7ff) > 0x3f)
-				ctl->val[1] = 0x00;
-
-			ctl->val[2] = sblive_readptr(card, ctl->val[0], ctl->val[1]);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETRECSRC:
-			switch (ctl->val[0]) {
-			case WAVERECORD_AC97:
-				if (card->is_aps) {
-					ret = -EINVAL;
-					break;
-				}
-
-				card->wavein.recsrc = WAVERECORD_AC97;
-				break;
-
-			case WAVERECORD_MIC:
-				card->wavein.recsrc = WAVERECORD_MIC;
-				break;
-
-			case WAVERECORD_FX:
-				card->wavein.recsrc = WAVERECORD_FX;
-				card->wavein.fxwc = ctl->val[1] & 0xffff;
-
-				if (!card->wavein.fxwc)
-					ret = -EINVAL;
-
-				break;
-
-			default:
-				ret = -EINVAL;
-				break;
-			}
-			break;
-
-		case CMD_GETRECSRC:
-			ctl->val[0] = card->wavein.recsrc;
-			ctl->val[1] = card->wavein.fxwc;
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_GETVOICEPARAM:
-			ctl->val[0] = card->waveout.send_routing[0];
-			ctl->val[1] = card->waveout.send_dcba[0];
-
-			ctl->val[2] = card->waveout.send_routing[1];
-			ctl->val[3] = card->waveout.send_dcba[1];
-
-			ctl->val[4] = card->waveout.send_routing[2];
-			ctl->val[5] = card->waveout.send_dcba[2];
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETVOICEPARAM:
-			card->waveout.send_routing[0] = ctl->val[0];
-			card->waveout.send_dcba[0] = ctl->val[1];
-
-			card->waveout.send_routing[1] = ctl->val[2];
-			card->waveout.send_dcba[1] = ctl->val[3];
-
-			card->waveout.send_routing[2] = ctl->val[4];
-			card->waveout.send_dcba[2] = ctl->val[5];
-
-			break;
-		
-		case CMD_SETMCH_FX:
-			card->mchannel_fx = ctl->val[0] & 0x000f;
-			break;
-		
-		case CMD_GETPATCH:
-			if (ctl->val[0] == 0) {
-				if (copy_to_user(argp, &card->mgr.rpatch, sizeof(struct dsp_rpatch)))
-                                	ret = -EFAULT;
-			} else {
-				if ((ctl->val[0] - 1) / PATCHES_PER_PAGE >= card->mgr.current_pages) {
-					ret = -EINVAL;
-					break;
-				}
-
-				if (copy_to_user(argp, PATCH(&card->mgr, ctl->val[0] - 1), sizeof(struct dsp_patch)))
-					ret = -EFAULT;
-			}
-
-			break;
-
-		case CMD_GETGPR:
-			id = ctl->val[0];
-
-			if (id > NUM_GPRS) {
-				ret = -EINVAL;
-				break;
-			}
-
-			if (copy_to_user(argp, &card->mgr.gpr[id], sizeof(struct dsp_gpr)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_GETCTLGPR:
-			addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, &((char *) ctl->val)[PATCH_NAME_SIZE]);
-			ctl->val[0] = sblive_readptr(card, addr, 0);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETPATCH:
-			if (ctl->val[0] == 0)
-				memcpy(&card->mgr.rpatch, &ctl->val[1], sizeof(struct dsp_rpatch));
-			else {
-				page = (ctl->val[0] - 1) / PATCHES_PER_PAGE;
-				if (page > MAX_PATCHES_PAGES) {
-					ret = -EINVAL;
-					break;
-				}
-
-				if (page >= card->mgr.current_pages) {
-					for (i = card->mgr.current_pages; i < page + 1; i++) {
-				                card->mgr.patch[i] = (void *)__get_free_page(GFP_KERNEL);
-						if(card->mgr.patch[i] == NULL) {
-							card->mgr.current_pages = i;
-							ret = -ENOMEM;
-							break;
-						}
-						memset(card->mgr.patch[i], 0, PAGE_SIZE);
-					}
-					card->mgr.current_pages = page + 1;
-				}
-
-				patch = PATCH(&card->mgr, ctl->val[0] - 1);
-
-				memcpy(patch, &ctl->val[1], sizeof(struct dsp_patch));
-
-				if (patch->code_size == 0) {
-					for(i = page + 1; i < card->mgr.current_pages; i++)
-                                                free_page((unsigned long) card->mgr.patch[i]);
-
-					card->mgr.current_pages = page + 1;
-				}
-			}
-			break;
-
-		case CMD_SETGPR:
-			if (ctl->val[0] > NUM_GPRS) {
-				ret = -EINVAL;
-				break;
-			}
-
-			memcpy(&card->mgr.gpr[ctl->val[0]], &ctl->val[1], sizeof(struct dsp_gpr));
-			break;
-
-		case CMD_SETCTLGPR:
-			addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, (char *) ctl->val + PATCH_NAME_SIZE);
-			emu10k1_set_control_gpr(card, addr, *((s32 *)((char *) ctl->val + 2 * PATCH_NAME_SIZE)), 0);
-			break;
-
-		case CMD_SETGPOUT:
-			if ( ((ctl->val[0] > 2) && (!card->is_audigy))
-			     || (ctl->val[0] > 15) || ctl->val[1] > 1) {
-				ret= -EINVAL;
-				break;
-			}
-
-			if (card->is_audigy)
-				emu10k1_writefn0(card, (1 << 24) | ((ctl->val[0]) << 16) | A_IOCFG, ctl->val[1]);
-			else
-				emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]);
-			break;
-
-		case CMD_GETGPR2OSS:
-			id = ctl->val[0];
-			ch = ctl->val[1];
-
-			if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
-				ret = -EINVAL;
-				break;
-			}
-
-			ctl->val[2] = card->mgr.ctrl_gpr[id][ch];
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETGPR2OSS:
-			id = ctl->val[0];
-			/* 0 == left, 1 == right */
-			ch = ctl->val[1];
-			addr = ctl->val[2];
-
-			if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
-				ret = -EINVAL;
-				break;
-			}
-
-			card->mgr.ctrl_gpr[id][ch] = addr;
-
-			if (card->is_aps)
-				break;
-
-			if (addr >= 0) {
-				unsigned int state = card->ac97->mixer_state[id];
-
-				if (ch == 1) {
-					state >>= 8;
-					card->ac97->stereo_mixers |= (1 << id);
-				}
-
-				card->ac97->supported_mixers |= (1 << id);
-
-				if (id == SOUND_MIXER_TREBLE) {
-					set_treble(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
-				} else if (id == SOUND_MIXER_BASS) {
-					set_bass(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
-				} else
-					emu10k1_set_volume_gpr(card, addr, state & 0xff,
-							       volume_params[id]);
-			} else {
-				card->ac97->stereo_mixers &= ~(1 << id);
-				card->ac97->stereo_mixers |= card->ac97_stereo_mixers;
-
-				if (ch == 0) {
-					card->ac97->supported_mixers &= ~(1 << id);
-					card->ac97->supported_mixers |= card->ac97_supported_mixers;
-				}
-			}
-			break;
-
-		case CMD_SETPASSTHROUGH:
-			card->pt.selected = ctl->val[0] ? 1 : 0;
-			if (card->pt.state != PT_STATE_INACTIVE)
-				break;
-
-			card->pt.spcs_to_use = ctl->val[0] & 0x07;
-			break;
-
-		case CMD_PRIVATE3_VERSION:
-			ctl->val[0] = PRIVATE3_VERSION;	//private3 version
-			ctl->val[1] = MAJOR_VER;	//major driver version
-			ctl->val[2] = MINOR_VER;	//minor driver version
-			ctl->val[3] = card->is_audigy;	//1=card is audigy
-
-			if (card->is_audigy)
-				ctl->val[4]=emu10k1_readfn0(card, 0x18);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-			break;
-
-		case CMD_AC97_BOOST:
-			if (ctl->val[0])
-				emu10k1_ac97_write(card->ac97, 0x18, 0x0);	
-			else
-				emu10k1_ac97_write(card->ac97, 0x18, 0x0808);
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-		}
-
-		kfree(ctl);
-		return ret;
-		break;
-
-	case SOUND_MIXER_PRIVATE4:
-
-		if (copy_from_user(&size, argp, sizeof(size)))
-			return -EFAULT;
-
-		DPD(2, "External tram size %#x\n", size);
-
-		if (size > 0x1fffff)
-			return -EINVAL;
-
-		size_reg = 0;
-
-		if (size != 0) {
-			size = (size - 1) >> 14;
-
-			while (size) {
-				size >>= 1;
-				size_reg++;
-			}
-
-			size = 0x4000 << size_reg;
-		}
-
-		DPD(2, "External tram size %#x %#x\n", size, size_reg);
-
-		if (size != card->tankmem.size) {
-			if (card->tankmem.size > 0) {
-				emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 1);
-
-				sblive_writeptr_tag(card, 0, TCB, 0, TCBS, 0, TAGLIST_END);
-
-				pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
-
-				card->tankmem.size = 0;
-			}
-
-			if (size != 0) {
-				card->tankmem.addr = pci_alloc_consistent(card->pci_dev, size, &card->tankmem.dma_handle);
-				if (card->tankmem.addr == NULL)
-					return -ENOMEM;
-
-				card->tankmem.size = size;
-
-				sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS,(u32) size_reg, TAGLIST_END);
-
-				emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
-			}
-		}
-		return 0;
-		break;
-
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
-static int emu10k1_dsp_mixer(struct emu10k1_card *card, unsigned int oss_mixer, unsigned long arg)
-{
-	unsigned int left, right;
-	int val;
-	int scale;
-
-	card->ac97->modcnt++;
-
-	if (get_user(val, (int __user *)arg))
-		return -EFAULT;
-
-	/* cleanse input a little */
-	right = ((val >> 8)  & 0xff);
-	left = (val  & 0xff);
-
-	if (right > 100) right = 100;
-	if (left > 100) left = 100;
-
-	card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
-	if (oss_mixer == SOUND_MIXER_TREBLE) {
-		set_treble(card, left, right);
-		return 0;
-	} if (oss_mixer == SOUND_MIXER_BASS) {
-		set_bass(card, left, right);
-		return 0;
-	}
-
-	if (oss_mixer == SOUND_MIXER_VOLUME)
-		scale = 1 << card->ac97->bit_resolution;
-	else
-		scale = volume_params[oss_mixer];
-
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, scale);
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, scale);
-
-	if (card->ac97_supported_mixers & (1 << oss_mixer))
-		card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
-
-	return 0;
-}
-
-static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	struct emu10k1_card *card = file->private_data;
-	unsigned int oss_mixer = _IOC_NR(cmd);
-	
-	ret = -EINVAL;
-	if (!card->is_aps) {
-		if (cmd == SOUND_MIXER_INFO) {
-			mixer_info info;
-
-			strlcpy(info.id, card->ac97->name, sizeof(info.id));
-
-			if (card->is_audigy)
-				strlcpy(info.name, "Audigy - Emu10k1", sizeof(info.name));
-			else
-				strlcpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
-				
-			info.modify_counter = card->ac97->modcnt;
-
-			if (copy_to_user((void __user *)arg, &info, sizeof(info)))
-				return -EFAULT;
-
-			return 0;
-		}
-
-		if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
-			ret = emu10k1_dsp_mixer(card, oss_mixer, arg);
-		else
-			ret = card->ac97->mixer_ioctl(card->ac97, cmd, arg);
-	}
-	
-	if (ret < 0)
-		ret = emu10k1_private_mixer(card, cmd, arg);
-
-	return ret;
-}
-
-static int emu10k1_mixer_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct emu10k1_card *card = NULL;
-	struct list_head *entry;
-
-	DPF(4, "emu10k1_mixer_open()\n");
-
-	list_for_each(entry, &emu10k1_devs) {
-		card = list_entry(entry, struct emu10k1_card, list);
-
-		if (card->ac97->dev_mixer == minor)
-			goto match;
-	}
-
-	return -ENODEV;
-
-      match:
-	file->private_data = card;
-	return 0;
-}
-
-static int emu10k1_mixer_release(struct inode *inode, struct file *file)
-{
-	DPF(4, "emu10k1_mixer_release()\n");
-	return 0;
-}
-
-const struct file_operations emu10k1_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.ioctl		= emu10k1_mixer_ioctl,
-	.open		= emu10k1_mixer_open,
-	.release	= emu10k1_mixer_release,
-};
diff --git a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c
deleted file mode 100644
index 6d21d43..0000000
--- a/sound/oss/emu10k1/passthrough.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- **********************************************************************
- *     passthrough.c -- Emu10k1 digital passthrough
- *     Copyright (C) 2001  Juha Yrjölä <jyrjola@cc.hut.fi>
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     May 15, 2001	    Juha Yrjölä	    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-                       
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-
-#include "hwaccess.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "recmgr.h"
-#include "irqmgr.h"
-#include "audio.h"
-#include "8010.h"
-
-static void pt_putsamples(struct pt_data *pt, u16 *ptr, u16 left, u16 right)
-{
-	unsigned int idx;
-
-	ptr[pt->copyptr] = left;
-	idx = pt->copyptr + PT_SAMPLES/2;
-	idx %= PT_SAMPLES;
-	ptr[idx] = right;
-}
-
-static inline int pt_can_write(struct pt_data *pt)
-{
-	return pt->blocks_copied < pt->blocks_played + 8;
-}
-
-static int pt_wait_for_write(struct emu10k1_wavedevice *wavedev, int nonblock)
-{
-	struct emu10k1_card *card = wavedev->card;
-	struct pt_data *pt = &card->pt;
-
-	if (nonblock && !pt_can_write(pt))
-		return -EAGAIN;
-	while (!pt_can_write(pt) && pt->state != PT_STATE_INACTIVE) {
-		interruptible_sleep_on(&pt->wait);
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-	}
-	if (pt->state == PT_STATE_INACTIVE)
-		return -EAGAIN;
-	
-	return 0;
-}
-
-static int pt_putblock(struct emu10k1_wavedevice *wave_dev, u16 *block, int nonblock)
-{
-	struct woinst *woinst = wave_dev->woinst;
-	struct emu10k1_card *card = wave_dev->card;
-	struct pt_data *pt = &card->pt;
-	u16 *ptr = (u16 *) card->tankmem.addr;
-	int i = 0, r;
-	unsigned long flags;
-
-	r = pt_wait_for_write(wave_dev, nonblock);
-	if (r < 0)
-		return r;
-	spin_lock_irqsave(&card->pt.lock, flags);
-	while (i < PT_BLOCKSAMPLES) {
-		pt_putsamples(pt, ptr, block[2*i], block[2*i+1]);
-		if (pt->copyptr == 0)
-			pt->copyptr = PT_SAMPLES;
-		pt->copyptr--;
-		i++;
-	}
-	woinst->total_copied += PT_BLOCKSIZE;
-	pt->blocks_copied++;
-	if (pt->blocks_copied >= 4 && pt->state != PT_STATE_PLAYING) {
-		DPF(2, "activating digital pass-through playback\n");
-		sblive_writeptr(card, GPR_BASE + pt->enable_gpr, 0, 1);
-		pt->state = PT_STATE_PLAYING;
-	}
-	spin_unlock_irqrestore(&card->pt.lock, flags);
-	return 0;
-}
-
-int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev)
-{
-	u32 bits;
-	struct emu10k1_card *card = wave_dev->card;
-	struct pt_data *pt = &card->pt;
-	int i;
-
-	for (i = 0; i < 3; i++) {
-		pt->old_spcs[i] = sblive_readptr(card, SPCS0 + i, 0);
-		if (pt->spcs_to_use & (1 << i)) {
-			DPD(2, "using S/PDIF port %d\n", i);
-			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
-				SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
-				0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
-			if (pt->ac3data)
-				bits |= SPCS_NOTAUDIODATA;
-			sblive_writeptr(card, SPCS0 + i, 0, bits);
-		}
-	}
-	return 0;
-}
-
-ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t count)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct emu10k1_card *card = wave_dev->card;
-	struct pt_data *pt = &card->pt;
-	int nonblock, i, r, blocks, blocks_copied, bytes_copied = 0;
-
-	DPD(3, "emu10k1_pt_write(): %d bytes\n", count);
-	
-	nonblock = file->f_flags & O_NONBLOCK;
-	
-	if (card->tankmem.size < PT_SAMPLES*2)
-		return -EFAULT;
-	if (pt->state == PT_STATE_INACTIVE) {
-		DPF(2, "bufptr init\n");
-		pt->playptr = PT_SAMPLES-1;
-		pt->copyptr = PT_INITPTR;
-		pt->blocks_played = pt->blocks_copied = 0;
-		memset(card->tankmem.addr, 0, card->tankmem.size);
-		pt->state = PT_STATE_ACTIVATED;
-		pt->buf = kmalloc(PT_BLOCKSIZE, GFP_KERNEL);
-		pt->prepend_size = 0;
-		if (pt->buf == NULL)
-			return -ENOMEM;
-		emu10k1_pt_setup(wave_dev);
-	}
-	if (pt->prepend_size) {
-		int needed = PT_BLOCKSIZE - pt->prepend_size;
-
-		DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
-		if (count < needed) {
-			if (copy_from_user(pt->buf + pt->prepend_size,
-					   buffer, count))
-				return -EFAULT;
-			pt->prepend_size += count;
-			DPD(3, "prepend size now %d\n", pt->prepend_size);
-			return count;
-		}
-		if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
-			return -EFAULT;
-		r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
-		if (r)
-			return r;
-		bytes_copied += needed;
-		pt->prepend_size = 0;
-	}
-	blocks = (count-bytes_copied)/PT_BLOCKSIZE;
-	blocks_copied = 0;
-	while (blocks > 0) {
-		u16 __user *bufptr = (u16 __user *) buffer + (bytes_copied/2);
-		if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
-			return -EFAULT;
-		r = pt_putblock(wave_dev, (u16 *)pt->buf, nonblock);
-		if (r) {
-			if (bytes_copied)
-				return bytes_copied;
-			else
-				return r;
-		}
-		bytes_copied += PT_BLOCKSIZE;
-		blocks--;
-		blocks_copied++;
-	}
-	i = count - bytes_copied;
-	if (i) {
-		pt->prepend_size = i;
-		if (copy_from_user(pt->buf, buffer + bytes_copied, i))
-			return -EFAULT;
-		bytes_copied += i;
-		DPD(3, "filling prepend buffer with %d bytes", i);
-	}
-	return bytes_copied;
-}
-
-void emu10k1_pt_stop(struct emu10k1_card *card)
-{
-	struct pt_data *pt = &card->pt;
-	int i;
-
-	if (pt->state != PT_STATE_INACTIVE) {
-		DPF(2, "digital pass-through stopped\n");
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 0);
-		for (i = 0; i < 3; i++) {
-                        if (pt->spcs_to_use & (1 << i))
-				sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]);
-		}
-		pt->state = PT_STATE_INACTIVE;
-		kfree(pt->buf);
-	}
-}
-
-void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev)
-{
-	struct woinst *woinst = wave_dev->woinst;
-	struct pt_data *pt = &wave_dev->card->pt;
-	u32 pos;
-
-	if (pt->state == PT_STATE_PLAYING && pt->pos_gpr >= 0) {
-		pos = sblive_readptr(wave_dev->card, GPR_BASE + pt->pos_gpr, 0);
-		if (pos > PT_BLOCKSAMPLES)
-			pos = PT_BLOCKSAMPLES;
-		pos = 4 * (PT_BLOCKSAMPLES - pos);
-	} else
-		pos = 0;
-	woinst->total_played = pt->blocks_played * woinst->buffer.fragment_size + pos;
-	woinst->buffer.hw_pos = pos;
-}
diff --git a/sound/oss/emu10k1/passthrough.h b/sound/oss/emu10k1/passthrough.h
deleted file mode 100644
index 420cc97..0000000
--- a/sound/oss/emu10k1/passthrough.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- **********************************************************************
- *     passthrough.h -- Emu10k1 digital passthrough header file
- *     Copyright (C) 2001  Juha Yrjölä <jyrjola@cc.hut.fi>
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     May 15, 2001	    Juha Yrjölä     base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _PASSTHROUGH_H
-#define _PASSTHROUGH_H
-
-#include "audio.h"
-
-/* number of 16-bit stereo samples in XTRAM buffer */
-#define PT_SAMPLES 0x8000
-#define PT_BLOCKSAMPLES 0x400
-#define PT_BLOCKSIZE (PT_BLOCKSAMPLES*4)
-#define PT_BLOCKSIZE_LOG2 12
-#define PT_BLOCKCOUNT (PT_SAMPLES/PT_BLOCKSAMPLES)
-#define PT_INITPTR (PT_SAMPLES/2-1)
-
-#define PT_STATE_INACTIVE 0
-#define PT_STATE_ACTIVATED 1
-#define PT_STATE_PLAYING 2
-
-/* passthrough struct */
-struct pt_data
-{
-	u8	selected, state, spcs_to_use;
-	int	intr_gpr, enable_gpr, pos_gpr;
-	u32	blocks_played, blocks_copied, old_spcs[3];
-	u32	playptr, copyptr;
-	u32	prepend_size;
-	u8	*buf;
-	u8	ac3data;
-
-	char	*patch_name, *intr_gpr_name, *enable_gpr_name, *pos_gpr_name;
-
-	wait_queue_head_t wait;
-	spinlock_t lock;
-};
-
-/*
-  Passthrough can be done in two methods:
-
-  Method 1 : tram
-     In original emu10k1, we couldn't bypass the sample rate converters. Even at 48kHz
-     (the internal sample rate of the emu10k1) the samples would get messed up.
-     To over come this, samples are copied into the tram and a special dsp patch copies
-     the samples out and generates interrupts when a block has finnished playing.
-
-  Method 2 : Interpolator bypass
-
-     Creative fixed the sample rate convert problem in emu10k1 rev 7 and higher
-     (including the emu10k2 (audigy)). This allows us to use the regular, and much simpler
-     playback method. 
-
-
-  In both methods, dsp code is used to mux audio and passthrough. This ensures that the spdif
-  doesn't receive audio and pasthrough data at the same time. The spdif flag SPCS_NOTAUDIODATA
-  is set to tell 
-
- */
-
-// emu10k1 revs greater than or equal to 7 can use method2
-
-#define USE_PT_METHOD2  (card->is_audigy)
-#define USE_PT_METHOD1	!USE_PT_METHOD2
-
-ssize_t emu10k1_pt_write(struct file *file, const char __user *buf, size_t count);
-
-int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev);
-void emu10k1_pt_stop(struct emu10k1_card *card);
-void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev);
-
-#endif /* _PASSTHROUGH_H */
diff --git a/sound/oss/emu10k1/recmgr.c b/sound/oss/emu10k1/recmgr.c
deleted file mode 100644
index 2ce5618..0000000
--- a/sound/oss/emu10k1/recmgr.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- **********************************************************************
- *     recmgr.c -- Recording manager for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include <linux/delay.h>
-#include "8010.h"
-#include "recmgr.h"
-
-void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	DPF(2, "emu10k1_reset_record()\n");
-
-	sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
-
-	sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);	
-
-	while (sblive_readptr(card, buffer->idxreg, 0))
-		udelay(5);
-}
-
-void emu10k1_start_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	DPF(2, "emu10k1_start_record()\n");
-
-	if (buffer->adcctl)
-		sblive_writeptr(card, ADCCR, 0, buffer->adcctl);
-}
-
-void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	DPF(2, "emu10k1_stop_record()\n");
-
-	/* Disable record transfer */
-	if (buffer->adcctl)
-		sblive_writeptr(card, ADCCR, 0, 0);
-}
-
-void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-
-	DPF(2, "emu10k1_set_record_src()\n");
-
-	switch (wiinst->recsrc) {
-
-	case WAVERECORD_AC97:
-		DPF(2, "recording source: AC97\n");
-		buffer->sizereg = ADCBS;
-		buffer->addrreg = ADCBA;
-		buffer->idxreg = card->is_audigy ? A_ADCIDX_IDX : ADCIDX_IDX;
-
-		switch (wiinst->format.samplingrate) {
-		case 0xBB80:
-			buffer->adcctl = ADCCR_SAMPLERATE_48;
-			break;
-		case 0xAC44:
-			buffer->adcctl = ADCCR_SAMPLERATE_44;
-			break;
-		case 0x7D00:
-			buffer->adcctl = ADCCR_SAMPLERATE_32;
-			break;
-		case 0x5DC0:
-			buffer->adcctl = ADCCR_SAMPLERATE_24;
-			break;
-		case 0x5622:
-			buffer->adcctl = ADCCR_SAMPLERATE_22;
-			break;
-		case 0x3E80:
-			buffer->adcctl = ADCCR_SAMPLERATE_16;
-			break;
-		// FIXME: audigy supports 12kHz recording
-		/*
-		case ????:
-			buffer->adcctl = A_ADCCR_SAMPLERATE_12;
-			break;
-		*/
-		case 0x2B11:
-			buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_11 : ADCCR_SAMPLERATE_11;
-			break;
-		case 0x1F40:
-			buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_8 : ADCCR_SAMPLERATE_8;
-			break;
-		default:
-			BUG();
-			break;
-		}
-
-		buffer->adcctl |= card->is_audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
-
-		if (wiinst->format.channels == 2)
-			buffer->adcctl |= card->is_audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
-
-		break;
-
-	case WAVERECORD_MIC:
-		DPF(2, "recording source: MIC\n");
-		buffer->sizereg = MICBS;
-		buffer->addrreg = MICBA;
-		buffer->idxreg = MICIDX_IDX;
-		buffer->adcctl = 0;
-		break;
-
-	case WAVERECORD_FX:
-		DPF(2, "recording source: FX\n");
-		buffer->sizereg = FXBS;
-		buffer->addrreg = FXBA;
-		buffer->idxreg = FXIDX_IDX;
-		buffer->adcctl = 0;
-
-		sblive_writeptr(card, FXWC, 0, wiinst->fxwc);
-		break;
-	default:
-		BUG();
-		break;
-	}
-
-	DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle);
-
-	sblive_writeptr(card, buffer->addrreg, 0, (u32)buffer->dma_handle);
-}
diff --git a/sound/oss/emu10k1/recmgr.h b/sound/oss/emu10k1/recmgr.h
deleted file mode 100644
index a68766a..0000000
--- a/sound/oss/emu10k1/recmgr.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*     
- **********************************************************************
- *     recmgr.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the 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 _RECORDMGR_H
-#define _RECORDMGR_H
-
-#include "hwaccess.h"
-#include "cardwi.h"
-
-/* Recording resources */
-#define WAVERECORD_AC97		0x01
-#define WAVERECORD_MIC		0x02
-#define WAVERECORD_FX		0x03
-
-void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer);
-void emu10k1_start_record(struct emu10k1_card *, struct wavein_buffer *);
-void emu10k1_stop_record(struct emu10k1_card *, struct wavein_buffer *);
-void emu10k1_set_record_src(struct emu10k1_card *, struct wiinst *wiinst);
-
-#endif /* _RECORDMGR_H */
diff --git a/sound/oss/emu10k1/timer.c b/sound/oss/emu10k1/timer.c
deleted file mode 100644
index d10d307..0000000
--- a/sound/oss/emu10k1/timer.c
+++ /dev/null
@@ -1,176 +0,0 @@
-
-/*
- **********************************************************************
- *     timer.c
- *     Copyright (C) 1999, 2000 Creative Labs, 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 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.
- *
- **********************************************************************
- */
-
-/* 3/6/2000	Improved support for different timer delays  Rui Sousa */
-
-/* 4/3/2000	Implemented timer list using list.h 	     Rui Sousa */
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "irqmgr.h"
-#include "timer.h"
-
-/* Try to schedule only once per fragment */
-
-void emu10k1_timer_irqhandler(struct emu10k1_card *card)
-{
-	struct emu_timer *t;
-	struct list_head *entry;
-
-	spin_lock(&card->timer_lock);
-
-	list_for_each(entry, &card->timers) {
-		t = list_entry(entry, struct emu_timer, list);
-
-		if (t->state & TIMER_STATE_ACTIVE) {
-			t->count++;
-			if (t->count == t->count_max) {
-				t->count = 0;
-				tasklet_hi_schedule(&t->tasklet);
-			}
-		}
-	}
-
-	spin_unlock(&card->timer_lock);
-
-	return;
-}
-
-void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u16 delay)
-{
-	struct emu_timer *t;
-	struct list_head *entry;
-	unsigned long flags;
-
-	if (delay < 5)
-		delay = 5;
-
-	timer->delay = delay;
-	timer->state = TIMER_STATE_INSTALLED;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-
-	timer->count_max = timer->delay / (card->timer_delay < 1024 ? card->timer_delay : 1024);
-	timer->count = timer->count_max - 1;
-
-	list_add(&timer->list, &card->timers);
-
-	if (card->timer_delay > delay) {
-		if (card->timer_delay == TIMER_STOPPED)
-			emu10k1_irq_enable(card, INTE_INTERVALTIMERENB);
-
-		card->timer_delay = delay;
-		delay = (delay < 1024 ? delay : 1024);
-
-		emu10k1_timer_set(card, delay);
-
-		list_for_each(entry, &card->timers) {
-			t = list_entry(entry, struct emu_timer, list);
-
-			t->count_max = t->delay / delay;
-			/* don't want to think much, just force scheduling 
-			   on the next interrupt */
-			t->count = t->count_max - 1;
-		}
-
-		DPD(2, "timer rate --> %u\n", delay);
-	}
-
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	return;
-}
-
-void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
-{
-	struct emu_timer *t;
-	struct list_head *entry;
-	u16 delay = TIMER_STOPPED;
-	unsigned long flags;
-
-	if (timer->state == TIMER_STATE_UNINSTALLED)
-		return;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-
-	list_del(&timer->list);
-
-	list_for_each(entry, &card->timers) {
-		t = list_entry(entry, struct emu_timer, list);
-
-		if (t->delay < delay)
-			delay = t->delay;
-	}
-
-	if (card->timer_delay != delay) {
-		card->timer_delay = delay;
-
-		if (delay == TIMER_STOPPED)
-			emu10k1_irq_disable(card, INTE_INTERVALTIMERENB);
-		else {
-			delay = (delay < 1024 ? delay : 1024);
-
-			emu10k1_timer_set(card, delay);
-
-			list_for_each(entry, &card->timers) {
-				t = list_entry(entry, struct emu_timer, list);
-
-				t->count_max = t->delay / delay;
-				t->count = t->count_max - 1;
-			}
-		}
-
-		DPD(2, "timer rate --> %u\n", delay);
-	}
-
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	timer->state = TIMER_STATE_UNINSTALLED;
-
-	return;
-}
-
-void emu10k1_timer_enable(struct emu10k1_card *card, struct emu_timer *timer)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-	timer->state |= TIMER_STATE_ACTIVE;
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	return;
-}
-
-void emu10k1_timer_disable(struct emu10k1_card *card, struct emu_timer *timer)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-	timer->state &= ~TIMER_STATE_ACTIVE;
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	return;
-}
diff --git a/sound/oss/emu10k1/timer.h b/sound/oss/emu10k1/timer.h
deleted file mode 100644
index b2543b4..0000000
--- a/sound/oss/emu10k1/timer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- **********************************************************************
- *     timer.h
- *     Copyright (C) 1999, 2000 Creative Labs, 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 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 _TIMER_H
-#define _TIMER_H
-
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include "hwaccess.h"
-
-struct emu_timer 
-{
-	struct list_head list;
-	struct tasklet_struct tasklet;
-	u8 state; 
-	u16 count;				/* current number of interrupts */
-	u16 count_max;				/* number of interrupts needed to schedule the bh */
-	u16 delay;                              /* timer delay */
-};
-
-void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u16);
-void emu10k1_timer_uninstall(struct emu10k1_card *, struct emu_timer *);
-void emu10k1_timer_enable(struct emu10k1_card *, struct emu_timer *);
-void emu10k1_timer_disable(struct emu10k1_card *, struct emu_timer *);
-
-#define TIMER_STOPPED 			0xffff 
-#define TIMER_STATE_INSTALLED 		0x01
-#define TIMER_STATE_ACTIVE		0x02
-#define TIMER_STATE_UNINSTALLED 	0x04
-
-#endif /* _TIMER_H */
diff --git a/sound/oss/emu10k1/voicemgr.c b/sound/oss/emu10k1/voicemgr.c
deleted file mode 100644
index d88b602..0000000
--- a/sound/oss/emu10k1/voicemgr.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- **********************************************************************
- *     voicemgr.c - Voice manager for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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.
- *
- **********************************************************************
- */
-
-#include "voicemgr.h"
-#include "8010.h"
-
-#define PITCH_48000 0x00004000
-#define PITCH_96000 0x00008000
-#define PITCH_85000 0x00007155
-#define PITCH_80726 0x00006ba2
-#define PITCH_67882 0x00005a82
-#define PITCH_57081 0x00004c1c
-
-static u32 emu10k1_select_interprom(struct emu10k1_card *card,
-				    struct emu_voice *voice)
-{
-	if(voice->pitch_target==PITCH_48000)
-		return CCCA_INTERPROM_0;
-	else if(voice->pitch_target<PITCH_48000)
-		return CCCA_INTERPROM_1;
-	else  if(voice->pitch_target>=PITCH_96000)
-		return CCCA_INTERPROM_0;
-	else  if(voice->pitch_target>=PITCH_85000)
-		return CCCA_INTERPROM_6;
-	else  if(voice->pitch_target>=PITCH_80726)
-		return CCCA_INTERPROM_5;
-	else  if(voice->pitch_target>=PITCH_67882)
-		return CCCA_INTERPROM_4;
-	else  if(voice->pitch_target>=PITCH_57081)
-		return CCCA_INTERPROM_3;
-	else  
-		return CCCA_INTERPROM_2;
-}
-
-
-/**
- * emu10k1_voice_alloc_buffer -
- *
- * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
- * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
- * is passed to the device so that it can do DMA to host memory.
- *
- */
-int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
-{
-	u32 pageindex, pagecount;
-	u32 busaddx;
-	int i;
-
-	DPD(2, "requested pages is: %d\n", pages);
-
-	if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
-	{
-		DPF(1, "couldn't allocate emu10k1 address space\n");
-		return -1;
-	}
-
-	/* Fill in virtual memory table */
-	for (pagecount = 0; pagecount < pages; pagecount++) {
-		if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
-			== NULL) {
-			mem->pages = pagecount;
-			DPF(1, "couldn't allocate dma memory\n");
-			return -1;
-		}
-
-		DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE;
-
-			DPD(3, "Bus Addx: %#x\n", busaddx);
-
-			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-
-			((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
-		}
-	}
-
-	mem->pages = pagecount;
-
-	return 0;
-}
-
-/**
- * emu10k1_voice_free_buffer -
- *
- * frees the memory buffer for a voice.
- */
-void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
-{
-	u32 pagecount, pageindex;
-	int i;
-
-	if (mem->emupageindex < 0)
-		return;
-
-	for (pagecount = 0; pagecount < mem->pages; pagecount++) {
-		pci_free_consistent(card->pci_dev, PAGE_SIZE,
-					mem->addr[pagecount],
-					mem->dma_handle[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-			((u32 *) card->virtualpagetable.addr)[pageindex] =
-				cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex);
-		}
-	}
-
-	emu10k1_addxmgr_free(card, mem->emupageindex);
-	mem->emupageindex = -1;
-}
-
-int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
-{
-	u8 *voicetable = card->voicetable;
-	int i;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_voice_alloc()\n");
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (voice->flags & VOICE_FLAGS_STEREO) {
-		for (i = 0; i < NUM_G; i += 2)
-			if ((voicetable[i] == VOICE_USAGE_FREE) && (voicetable[i + 1] == VOICE_USAGE_FREE)) {
-				voicetable[i] = voice->usage;
-				voicetable[i + 1] = voice->usage;
-				break;
-			}
-	} else {
-		for (i = 0; i < NUM_G; i++)
-			if (voicetable[i] == VOICE_USAGE_FREE) {
-				voicetable[i] = voice->usage;
-				break;
-			}
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	if (i >= NUM_G)
-		return -1;
-
-	voice->card = card;
-	voice->num = i;
-
-	for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
-		DPD(2, " voice allocated -> %d\n", voice->num + i);
-
-		sblive_writeptr_tag(card, voice->num + i, IFATN, 0xffff,
-							DCYSUSV, 0,
-							VTFT, 0x0000ffff,
-							PTRX, 0,
-							TAGLIST_END);
-	}
-
-	return 0;
-}
-
-void emu10k1_voice_free(struct emu_voice *voice)
-{
-	struct emu10k1_card *card = voice->card;
-	int i;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_voice_free()\n");
-
-	if (voice->usage == VOICE_USAGE_FREE)
-		return;
-
-	for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
-		DPD(2, " voice released -> %d\n", voice->num + i);
-
-		sblive_writeptr_tag(card, voice->num + i, DCYSUSV, 0, 
-							VTFT, 0x0000ffff,
-							PTRX_PITCHTARGET, 0,
-							CVCF, 0x0000ffff,
-							//CPF, 0,
-							TAGLIST_END);
-		
-		sblive_writeptr(card, CPF, voice->num + i, 0);
-	}
-
-	voice->usage = VOICE_USAGE_FREE;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	card->voicetable[voice->num] = VOICE_USAGE_FREE;
-
-	if (voice->flags & VOICE_FLAGS_STEREO)
-		card->voicetable[voice->num + 1] = VOICE_USAGE_FREE;
-
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-void emu10k1_voice_playback_setup(struct emu_voice *voice)
-{
-	struct emu10k1_card *card = voice->card;
-	u32 start;
-	int i;
-
-	DPF(2, "emu10k1_voice_playback_setup()\n");
-
-	if (voice->flags & VOICE_FLAGS_STEREO) {
-		/* Set stereo bit */
-		start = 28;
-		sblive_writeptr(card, CPF, voice->num, CPF_STEREO_MASK);
-		sblive_writeptr(card, CPF, voice->num + 1, CPF_STEREO_MASK);
-	} else {
-		start = 30;
-		sblive_writeptr(card, CPF, voice->num, 0);
-	}
-
-	if(!(voice->flags & VOICE_FLAGS_16BIT))
-		start *= 2;
-
-	voice->start += start;
-
-	for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
-		if (card->is_audigy) {
-			sblive_writeptr(card, A_FXRT1, voice->num + i, voice->params[i].send_routing);
-			sblive_writeptr(card, A_FXRT2, voice->num + i, voice->params[i].send_routing2);
-			sblive_writeptr(card,  A_SENDAMOUNTS, voice->num + i, voice->params[i].send_hgfe);
-		} else {
-			sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
-		}
-
-		/* Stop CA */
-		/* Assumption that PT is already 0 so no harm overwriting */
-		sblive_writeptr(card, PTRX, voice->num + i, ((voice->params[i].send_dcba & 0xff) << 8)
-				| ((voice->params[i].send_dcba & 0xff00) >> 8));
-
-		sblive_writeptr_tag(card, voice->num + i,
-				/* CSL, ST, CA */
-				    DSL, voice->endloop | (voice->params[i].send_dcba & 0xff000000),
-				    PSST, voice->startloop | ((voice->params[i].send_dcba & 0x00ff0000) << 8),
-				    CCCA, (voice->start) |  emu10k1_select_interprom(card,voice) |
-				        ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
-				    /* Clear filter delay memory */
-				    Z1, 0,
-				    Z2, 0,
-				    /* Invalidate maps */
-				    MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				    MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				/* modulation envelope */
-				    CVCF, 0x0000ffff,
-				    VTFT, 0x0000ffff,
-				    ATKHLDM, 0,
-				    DCYSUSM, 0x007f,
-				    LFOVAL1, 0x8000,
-				    LFOVAL2, 0x8000,
-				    FMMOD, 0,
-				    TREMFRQ, 0,
-				    FM2FRQ2, 0,
-				    ENVVAL, 0x8000,
-				/* volume envelope */
-				    ATKHLDV, 0x7f7f,
-				    ENVVOL, 0x8000,
-				/* filter envelope */
-				    PEFE_FILTERAMOUNT, 0x7f,
-				/* pitch envelope */
-				    PEFE_PITCHAMOUNT, 0, TAGLIST_END);
-
-		voice->params[i].fc_target = 0xffff;
-	}
-}
-
-void emu10k1_voices_start(struct emu_voice *first_voice, unsigned int num_voices, int set)
-{
-	struct emu10k1_card *card = first_voice->card;
-	struct emu_voice *voice;
-	unsigned int voicenum;
-	int j;
-
-	DPF(2, "emu10k1_voices_start()\n");
-
-	for (voicenum = 0; voicenum < num_voices; voicenum++)
-	{
-		voice = first_voice + voicenum;
-
-		if (!set) {
-			u32 cra, ccis, cs, sample;
-			if (voice->flags & VOICE_FLAGS_STEREO) {
-				cra = 64;
-				ccis = 28;
-				cs = 4;
-			} else {
-				cra = 64;
-				ccis = 30;
-				cs = 2;
-			}
-
-			if(voice->flags & VOICE_FLAGS_16BIT) {
-				sample = 0x00000000;
-			} else {
-				sample = 0x80808080;		
-				ccis *= 2;
-			}
-
-			for(j = 0; j < cs; j++)
-	        	        sblive_writeptr(card, CD0 + j, voice->num, sample);
-
-			/* Reset cache */
-			sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, 0);
-			if (voice->flags & VOICE_FLAGS_STEREO)
-				sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num + 1, 0);
-
-			sblive_writeptr(card, CCR_READADDRESS, voice->num, cra);
-
-			if (voice->flags & VOICE_FLAGS_STEREO)
-				sblive_writeptr(card, CCR_READADDRESS, voice->num + 1, cra);
-
-			/* Fill cache */
-			sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, ccis);
-		}
-
-		for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
-			sblive_writeptr_tag(card, voice->num + j,
-				    IFATN, (voice->params[j].initial_fc << 8) | voice->params[j].initial_attn,
-				    VTFT, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
-				    CVCF, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
-				    DCYSUSV, (voice->params[j].byampl_env_sustain << 8) | voice->params[j].byampl_env_decay,
-				    TAGLIST_END);
-	
-			emu10k1_clear_stop_on_loop(card, voice->num + j);
-		}
-	}
-
-
-        for (voicenum = 0; voicenum < num_voices; voicenum++)
-	{
-		voice = first_voice + voicenum;
-
-		for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
-			sblive_writeptr(card, PTRX_PITCHTARGET, voice->num + j, voice->pitch_target);
-
-			if (j == 0)
-				sblive_writeptr(card, CPF_CURRENTPITCH, voice->num, voice->pitch_target);
-
-			sblive_writeptr(card, IP, voice->num + j, voice->initial_pitch);
-		}
-	}
-}
-
-void emu10k1_voices_stop(struct emu_voice *first_voice, int num_voices)
-{
-	struct emu10k1_card *card = first_voice->card;
-	struct emu_voice *voice;
-	unsigned int voice_num;
-	int j;
-
-	DPF(2, "emu10k1_voice_stop()\n");
-
-        for (voice_num = 0; voice_num < num_voices; voice_num++)
-	{
-		voice = first_voice + voice_num;
-
-		for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
-			sblive_writeptr_tag(card, voice->num + j,
-						PTRX_PITCHTARGET, 0,
-						CPF_CURRENTPITCH, 0,
-						IFATN, 0xffff,
-						VTFT, 0x0000ffff,
-						CVCF, 0x0000ffff,
-						IP, 0,
-						TAGLIST_END);
-		}
-	}
-}
-
diff --git a/sound/oss/emu10k1/voicemgr.h b/sound/oss/emu10k1/voicemgr.h
deleted file mode 100644
index 099a8cb..0000000
--- a/sound/oss/emu10k1/voicemgr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- **********************************************************************
- *     sblive_voice.h -- EMU Voice Resource Manager header file
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the 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 _VOICEMGR_H
-#define _VOICEMGR_H
-
-#include "hwaccess.h"
-
-/* struct emu_voice.usage flags */
-#define VOICE_USAGE_FREE		0x01
-#define VOICE_USAGE_MIDI		0x02
-#define VOICE_USAGE_PLAYBACK		0x04
-
-/* struct emu_voice.flags flags */
-#define VOICE_FLAGS_STEREO		0x02
-#define VOICE_FLAGS_16BIT		0x04
-
-struct voice_param
-{
-	/* FX bus amount send */
-
-	u32 send_routing;
-	// audigy only:
-	u32 send_routing2;
-
-	u32 send_dcba;
-	// audigy only:
-	u32 send_hgfe;
-
-
-	u32 initial_fc;
-	u32 fc_target;
-
-	u32 initial_attn;
-	u32 volume_target;
-
-	u32 byampl_env_sustain;
-	u32 byampl_env_decay;
-};
-
-struct voice_mem {
-	int emupageindex;
-	void *addr[BUFMAXPAGES];
-	dma_addr_t dma_handle[BUFMAXPAGES];
-	u32 pages;
-};
-
-struct emu_voice
-{
-	struct emu10k1_card *card;
-	u8 usage;		/* Free, MIDI, playback */
-	u8 num;			/* Voice ID */
-	u8 flags;		/* Stereo/mono, 8/16 bit */
-
-	u32 startloop;
-	u32 endloop;
-	u32 start;
-
-	u32 initial_pitch;
-	u32 pitch_target;
-
-	struct voice_param params[2];
-
-	struct voice_mem mem;
-};
-
-int emu10k1_voice_alloc_buffer(struct emu10k1_card *, struct voice_mem *, u32);
-void emu10k1_voice_free_buffer(struct emu10k1_card *, struct voice_mem *);
-int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *);
-void emu10k1_voice_free(struct emu_voice *);
-void emu10k1_voice_playback_setup(struct emu_voice *);
-void emu10k1_voices_start(struct emu_voice *, unsigned int, int);
-void emu10k1_voices_stop(struct emu_voice *, int);
-
-#endif /* _VOICEMGR_H */
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 2796c0e..a690ca5 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1003,7 +1003,8 @@
 		}
 		if (!devc->shared_irq)
 		{
-			if (request_irq(devc->irq, mpuintr, 0, "mpu401", (void *)m) < 0)
+			if (request_irq(devc->irq, mpuintr, 0, "mpu401",
+					hw_config) < 0)
 			{
 				printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq);
 				ret = -ENOMEM;
@@ -1112,7 +1113,7 @@
 	return 0;
 
 out_irq:
-	free_irq(devc->irq, (void *)m);
+	free_irq(devc->irq, hw_config);
 out_mididev:
 	sound_unload_mididev(m);
 out_err:
@@ -1227,7 +1228,7 @@
 	if (n != -1) {
 		release_region(hw_config->io_base, 2);
 		if (hw_config->always_detect == 0 && hw_config->irq > 0)
-			free_irq(hw_config->irq, (void *)n);
+			free_irq(hw_config->irq, hw_config);
 		p=mpu401_synth_operations[n];
 		sound_unload_mididev(n);
 		sound_unload_timerdev(hw_config->slots[2]);
diff --git a/sound/oss/nm256.h b/sound/oss/nm256.h
deleted file mode 100644
index 1dade90..0000000
--- a/sound/oss/nm256.h
+++ /dev/null
@@ -1,292 +0,0 @@
-#ifndef _NM256_H_
-#define _NM256_H_
-
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-
-#include "ac97.h"
-
-/* The revisions that we currently handle.  */
-enum nm256rev {
-    REV_NM256AV, REV_NM256ZX
-};
-
-/* Per-card structure. */
-struct nm256_info 
-{
-    /* Magic number used to verify that this struct is valid. */
-#define NM_MAGIC_SIG 0x55aa00ff
-    int magsig;
-
-    /* Revision number */
-    enum nm256rev rev;
-
-    struct ac97_hwint mdev;
-
-    /* Our audio device numbers. */
-    int dev[2];
-
-    /* The # of times each device has been opened. (Should only be 
-       0 or 1). */
-    int opencnt[2];
-
-    /* We use two devices, because we can do simultaneous play and record.
-       This keeps track of which device is being used for what purpose;
-       these are the actual device numbers. */
-    int dev_for_play;
-    int dev_for_record;
-
-	spinlock_t lock;
-	
-    /* The mixer device. */
-    int mixer_oss_dev;
-
-    /* 
-     * Can only be opened once for each operation.  These aren't set
-     * until an actual I/O operation is performed; this allows one
-     * device to be open for read/write without inhibiting I/O to
-     * the other device.
-     */
-    int is_open_play;
-    int is_open_record;
-
-    /* Non-zero if we're currently playing a sample. */
-    int playing;
-    /* Ditto for recording a sample. */
-    int recording;
-
-    /* The two memory ports.  */
-    struct nm256_ports {
-	/* Physical address of the port. */
-	u32 physaddr;
-	/* Our mapped-in pointer. */
-	char __iomem *ptr;
-	/* PTR's offset within the physical port.  */
-	u32 start_offset;
-	/* And the offset of the end of the buffer.  */
-	u32 end_offset;
-    } port[2];
-
-    /* The following are offsets within memory port 1. */
-    u32 coeffBuf;
-    u32 allCoeffBuf;
-
-    /* Record and playback buffers. */
-    u32 abuf1, abuf2;
-
-    /* Offset of the AC97 mixer in memory port 2. */
-    u32 mixer;
-
-    /* Offset of the mixer status register in memory port 2.  */
-    u32 mixer_status_offset;
-
-    /* Non-zero if we have written initial values to the mixer. */
-    u8 mixer_values_init;
-
-    /* 
-     * Status mask bit; (*mixer_status_loc & mixer_status_mask) == 0 means
-     * it's ready.  
-     */
-    u16 mixer_status_mask;
-
-    /* The sizes of the playback and record ring buffers. */
-    u32 playbackBufferSize;
-    u32 recordBufferSize;
-
-    /* Are the coefficient values in the memory cache current? */
-    u8 coeffsCurrent;
-
-    /* For writes, the amount we last wrote. */
-    u32 requested_amt;
-    /* The start of the block currently playing. */
-    u32 curPlayPos;
-
-    /* The amount of data we were requested to record. */
-    u32 requestedRecAmt;
-    /* The offset of the currently-recording block. */
-    u32 curRecPos;
-    /* The destination buffer. */
-    char *recBuf;
-
-    /* Our IRQ number. */
-    int irq;
-
-    /* A flag indicating how many times we've grabbed the IRQ. */
-    int has_irq;
-
-    /* The card interrupt service routine. */
-    irq_handler_t introutine;
-
-    /* Current audio config, cached. */
-    struct sinfo {
-	u32 samplerate;
-	u8 bits;
-	u8 stereo;
-    } sinfo[2]; /* goes with each device */
-
-    /* The cards are stored in a chain;  this is the next card. */
-    struct nm256_info *next_card;
-};
-
-/* The BIOS signature. */
-#define NM_SIGNATURE 0x4e4d0000
-/* Signature mask. */
-#define NM_SIG_MASK 0xffff0000
-
-/* Size of the second memory area. */
-#define NM_PORT2_SIZE 4096
-
-/* The base offset of the mixer in the second memory area. */
-#define NM_MIXER_OFFSET 0x600
-
-/* The maximum size of a coefficient entry. */
-#define NM_MAX_COEFFICIENT 0x5000
-
-/* The interrupt register. */
-#define NM_INT_REG 0xa04
-/* And its bits. */
-#define NM_PLAYBACK_INT 0x40
-#define NM_RECORD_INT 0x100
-#define NM_MISC_INT_1 0x4000
-#define NM_MISC_INT_2 0x1
-#define NM_ACK_INT(CARD, X) nm256_writePort16((CARD), 2, NM_INT_REG, (X) << 1)
-
-/* The AV's "mixer ready" status bit and location. */
-#define NM_MIXER_STATUS_OFFSET 0xa04
-#define NM_MIXER_READY_MASK 0x0800
-#define NM_MIXER_PRESENCE 0xa06
-#define NM_PRESENCE_MASK 0x0050
-#define NM_PRESENCE_VALUE 0x0040
-
-/*
- * For the ZX.  It uses the same interrupt register, but it holds 32
- * bits instead of 16.
- */
-#define NM2_PLAYBACK_INT 0x10000
-#define NM2_RECORD_INT 0x80000
-#define NM2_MISC_INT_1 0x8
-#define NM2_MISC_INT_2 0x2
-#define NM2_ACK_INT(CARD, X) nm256_writePort32((CARD), 2, NM_INT_REG, (X))
-
-/* The ZX's "mixer ready" status bit and location. */
-#define NM2_MIXER_STATUS_OFFSET 0xa06
-#define NM2_MIXER_READY_MASK 0x0800
-
-/* The playback registers start from here. */
-#define NM_PLAYBACK_REG_OFFSET 0x0
-/* The record registers start from here. */
-#define NM_RECORD_REG_OFFSET 0x200
-
-/* The rate register is located 2 bytes from the start of the register area. */
-#define NM_RATE_REG_OFFSET 2
-
-/* Mono/stereo flag, number of bits on playback, and rate mask. */
-#define NM_RATE_STEREO 1
-#define NM_RATE_BITS_16 2
-#define NM_RATE_MASK 0xf0
-
-/* Playback enable register. */
-#define NM_PLAYBACK_ENABLE_REG (NM_PLAYBACK_REG_OFFSET + 0x1)
-#define NM_PLAYBACK_ENABLE_FLAG 1
-#define NM_PLAYBACK_ONESHOT 2
-#define NM_PLAYBACK_FREERUN 4
-
-/* Mutes the audio output. */
-#define NM_AUDIO_MUTE_REG (NM_PLAYBACK_REG_OFFSET + 0x18)
-#define NM_AUDIO_MUTE_LEFT 0x8000
-#define NM_AUDIO_MUTE_RIGHT 0x0080
-
-/* Recording enable register. */
-#define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0)
-#define NM_RECORD_ENABLE_FLAG 1
-#define NM_RECORD_FREERUN 2
-
-#define NM_RBUFFER_START (NM_RECORD_REG_OFFSET + 0x4)
-#define NM_RBUFFER_END   (NM_RECORD_REG_OFFSET + 0x10)
-#define NM_RBUFFER_WMARK (NM_RECORD_REG_OFFSET + 0xc)
-#define NM_RBUFFER_CURRP (NM_RECORD_REG_OFFSET + 0x8)
-
-#define NM_PBUFFER_START (NM_PLAYBACK_REG_OFFSET + 0x4)
-#define NM_PBUFFER_END   (NM_PLAYBACK_REG_OFFSET + 0x14)
-#define NM_PBUFFER_WMARK (NM_PLAYBACK_REG_OFFSET + 0xc)
-#define NM_PBUFFER_CURRP (NM_PLAYBACK_REG_OFFSET + 0x8)
-
-/* A few trivial routines to make it easier to work with the registers
-   on the chip. */
-
-/* This is a common code portion used to fix up the port offsets. */
-#define NM_FIX_PORT \
-  if (port < 1 || port > 2 || card == NULL) \
-      return -1; \
-\
-    if (offset < card->port[port - 1].start_offset \
-	|| offset >= card->port[port - 1].end_offset) { \
-	printk (KERN_ERR "Bad access: port %d, offset 0x%x\n", port, offset); \
-	return -1; \
-    } \
-    offset -= card->port[port - 1].start_offset;
-
-#define DEFwritePortX(X, func) \
-static inline int nm256_writePort##X (struct nm256_info *card,\
-				      int port, int offset, int value)\
-{\
-    u##X __iomem *addr;\
-\
-    if (nm256_debug > 1)\
-        printk (KERN_DEBUG "Writing 0x%x to %d:0x%x\n", value, port, offset);\
-\
-    NM_FIX_PORT;\
-\
-    addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
-    func (value, addr);\
-    return 0;\
-}
-
-DEFwritePortX (8, writeb)
-DEFwritePortX (16, writew)
-DEFwritePortX (32, writel)
-
-#define DEFreadPortX(X, func) \
-static inline u##X nm256_readPort##X (struct nm256_info *card,\
-					int port, int offset)\
-{\
-    u##X __iomem *addr;\
-\
-    NM_FIX_PORT\
-\
-    addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
-    return func(addr);\
-}
-
-DEFreadPortX (8, readb)
-DEFreadPortX (16, readw)
-DEFreadPortX (32, readl)
-
-static inline int
-nm256_writeBuffer8 (struct nm256_info *card, u8 *src, int port, int offset,
-		      int amt)
-{
-    NM_FIX_PORT;
-    memcpy_toio (card->port[port - 1].ptr + offset, src, amt);
-    return 0;
-}
-
-static inline int
-nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset,
-		     int amt)
-{
-    NM_FIX_PORT;
-    memcpy_fromio (dst, card->port[port - 1].ptr + offset, amt);
-    return 0;
-}
-
-/* Returns a non-zero value if we should use the coefficient cache. */
-static int nm256_cachedCoefficients (struct nm256_info *card);
-
-#endif
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
deleted file mode 100644
index 44cd155..0000000
--- a/sound/oss/nm256_audio.c
+++ /dev/null
@@ -1,1662 +0,0 @@
-/* 
- * Audio driver for the NeoMagic 256AV and 256ZX chipsets in native
- * mode, with AC97 mixer support.
- *
- * Overall design and parts of this code stolen from vidc_*.c and
- * skeleton.c.
- *
- * Yeah, there are a lot of magic constants in here.  You tell ME what
- * they are.  I just get this stuff psychically, remember? 
- *
- * This driver was written by someone who wishes to remain anonymous. 
- * It is in the public domain, so share and enjoy.  Try to make a profit
- * off of it; go on, I dare you.  
- *
- * Changes:
- * 11-10-2000	Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
- *		Added some __init
- * 19-04-2001	Marcus Meissner <mm@caldera.de>
- *		Ported to 2.4 PCI API.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include "sound_config.h"
-
-static int nm256_debug;
-static int force_load;
-
-#include "nm256.h"
-#include "nm256_coeff.h"
-
-/* 
- * The size of the playback reserve.  When the playback buffer has less
- * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new
- * buffer.
- */
-#define NM256_PLAY_WMARK_SIZE 512
-
-static struct audio_driver nm256_audio_driver;
-
-static int nm256_grabInterrupt (struct nm256_info *card);
-static int nm256_releaseInterrupt (struct nm256_info *card);
-static irqreturn_t nm256_interrupt (int irq, void *dev_id);
-static irqreturn_t nm256_interrupt_zx (int irq, void *dev_id);
-
-/* These belong in linux/pci.h. */
-#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
-
-/* List of cards.  */
-static struct nm256_info *nmcard_list;
-
-/* Release the mapped-in memory for CARD.  */
-static void
-nm256_release_ports (struct nm256_info *card)
-{
-    int x;
-
-    for (x = 0; x < 2; x++) {
-	if (card->port[x].ptr != NULL) {
-	    iounmap (card->port[x].ptr);
-	    card->port[x].ptr = NULL;
-	}
-    }
-}
-
-/* 
- * Map in the memory ports for CARD, if they aren't already mapped in
- * and have been configured.  If successful, a zero value is returned;
- * otherwise any previously mapped-in areas are released and a non-zero
- * value is returned.
- *
- * This is invoked twice, once for each port.  Ideally it would only be
- * called once, but we now need to map in the second port in order to
- * check how much memory the card has on the 256ZX.
- */
-static int
-nm256_remap_ports (struct nm256_info *card)
-{
-    int x;
-
-    for (x = 0; x < 2; x++) {
-	if (card->port[x].ptr == NULL && card->port[x].end_offset > 0) {
-	    u32 physaddr 
-		= card->port[x].physaddr + card->port[x].start_offset;
-	    u32 size 
-		= card->port[x].end_offset - card->port[x].start_offset;
-
-	    card->port[x].ptr = ioremap_nocache (physaddr, size);
-						  
-	    if (card->port[x].ptr == NULL) {
-		printk (KERN_ERR "NM256: Unable to remap port %d\n", x + 1);
-		nm256_release_ports (card);
-		return -1;
-	    }
-	}
-    }
-    return 0;
-}
-
-/* Locate the card in our list. */
-static struct nm256_info *
-nm256_find_card (int dev)
-{
-    struct nm256_info *card;
-
-    for (card = nmcard_list; card != NULL; card = card->next_card)
-	if (card->dev[0] == dev || card->dev[1] == dev)
-	    return card;
-
-    return NULL;
-}
-
-/*
- * Ditto, but find the card struct corresponding to the mixer device DEV 
- * instead. 
- */
-static struct nm256_info *
-nm256_find_card_for_mixer (int dev)
-{
-    struct nm256_info *card;
-
-    for (card = nmcard_list; card != NULL; card = card->next_card)
-	if (card->mixer_oss_dev == dev)
-	    return card;
-
-    return NULL;
-}
-
-static int usecache;
-static int buffertop;
-
-/* Check to see if we're using the bank of cached coefficients. */
-static int
-nm256_cachedCoefficients (struct nm256_info *card)
-{
-    return usecache;
-}
-
-/* The actual rates supported by the card. */
-static int samplerates[9] = {
-    8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999
-};
-
-/*
- * Set the card samplerate, word size and stereo mode to correspond to
- * the settings in the CARD struct for the specified device in DEV.
- * We keep two separate sets of information, one for each device; the
- * hardware is not actually configured until a read or write is
- * attempted.
- */
-
-static int
-nm256_setInfo (int dev, struct nm256_info *card)
-{
-    int x;
-    int w;
-    int targetrate;
-
-    if (card->dev[0] == dev)
-	w = 0;
-    else if (card->dev[1] == dev)
-	w = 1;
-    else
-	return -ENODEV;
-
-    targetrate = card->sinfo[w].samplerate;
-
-    if ((card->sinfo[w].bits != 8 && card->sinfo[w].bits != 16)
-	|| targetrate < samplerates[0]
-	|| targetrate > samplerates[7])
-	return -EINVAL;
-
-    for (x = 0; x < 8; x++)
-	if (targetrate < ((samplerates[x] + samplerates[x + 1]) / 2))
-	    break;
-
-    if (x < 8) {
-	u8 ratebits = ((x << 4) & NM_RATE_MASK);
-	if (card->sinfo[w].bits == 16)
-	    ratebits |= NM_RATE_BITS_16;
-	if (card->sinfo[w].stereo)
-	    ratebits |= NM_RATE_STEREO;
-
-	card->sinfo[w].samplerate = samplerates[x];
-
-
-	if (card->dev_for_play == dev && card->playing) {
-	    if (nm256_debug)
-		printk (KERN_DEBUG "Setting play ratebits to 0x%x\n",
-			ratebits);
-	    nm256_loadCoefficient (card, 0, x);
-	    nm256_writePort8 (card, 2,
-			      NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET,
-			      ratebits);
-	}
-
-	if (card->dev_for_record == dev && card->recording) {
-	    if (nm256_debug)
-		printk (KERN_DEBUG "Setting record ratebits to 0x%x\n",
-			ratebits);
-	    nm256_loadCoefficient (card, 1, x);
-	    nm256_writePort8 (card, 2,
-			      NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET,
-			      ratebits);
-	}
-	return 0;
-    }
-    else
-	return -EINVAL;
-}
-
-/* Start the play process going. */
-static void
-startPlay (struct nm256_info *card)
-{
-    if (! card->playing) {
-	card->playing = 1;
-	if (nm256_grabInterrupt (card) == 0) {
-	    nm256_setInfo (card->dev_for_play, card);
-
-	    /* Enable playback engine and interrupts. */
-	    nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG,
-			      NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN);
-
-	    /* Enable both channels. */
-	    nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG, 0x0);
-	}
-    }
-}
-
-/* 
- * Request one chunk of AMT bytes from the recording device.  When the
- * operation is complete, the data will be copied into BUFFER and the
- * function DMAbuf_inputintr will be invoked.
- */
-
-static void
-nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
-{
-    u32 endpos;
-    int enableEngine = 0;
-    u32 ringsize = card->recordBufferSize;
-    unsigned long flags;
-
-    if (amt > (ringsize / 2)) {
-	/*
-	 * Of course this won't actually work right, because the
-	 * caller is going to assume we will give what we got asked
-	 * for.
-	 */
-	printk (KERN_ERR "NM256: Read request too large: %d\n", amt);
-	amt = ringsize / 2;
-    }
-
-    if (amt < 8) {
-	printk (KERN_ERR "NM256: Read request too small; %d\n", amt);
-	return;
-    }
-
-    spin_lock_irqsave(&card->lock,flags);
-    /*
-     * If we're not currently recording, set up the start and end registers
-     * for the recording engine.
-     */
-    if (! card->recording) {
-	card->recording = 1;
-	if (nm256_grabInterrupt (card) == 0) {
-	    card->curRecPos = 0;
-	    nm256_setInfo (card->dev_for_record, card);
-	    nm256_writePort32 (card, 2, NM_RBUFFER_START, card->abuf2);
-	    nm256_writePort32 (card, 2, NM_RBUFFER_END,
-				 card->abuf2 + ringsize);
-
-	    nm256_writePort32 (card, 2, NM_RBUFFER_CURRP,
-				 card->abuf2 + card->curRecPos);
-	    enableEngine = 1;
-	}
-	else {
-	    /* Not sure what else to do here.  */
-	    spin_unlock_irqrestore(&card->lock,flags);
-	    return;
-	}
-    }
-
-    /* 
-     * If we happen to go past the end of the buffer a bit (due to a
-     * delayed interrupt) it's OK.  So might as well set the watermark
-     * right at the end of the data we want.
-     */
-    endpos = card->abuf2 + ((card->curRecPos + amt) % ringsize);
-
-    card->recBuf = buffer;
-    card->requestedRecAmt = amt;
-    nm256_writePort32 (card, 2, NM_RBUFFER_WMARK, endpos);
-    /* Enable recording engine and interrupts. */
-    if (enableEngine)
-	nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG,
-			    NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN);
-
-    spin_unlock_irqrestore(&card->lock,flags);
-}
-
-/* Stop the play engine. */
-static void
-stopPlay (struct nm256_info *card)
-{
-    /* Shut off sound from both channels. */
-    nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG,
-		       NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT);
-    /* Disable play engine. */
-    nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG, 0);
-    if (card->playing) {
-	nm256_releaseInterrupt (card);
-
-	/* Reset the relevant state bits. */
-	card->playing = 0;
-	card->curPlayPos = 0;
-    }
-}
-
-/* Stop recording. */
-static void
-stopRecord (struct nm256_info *card)
-{
-    /* Disable recording engine. */
-    nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, 0);
-
-    if (card->recording) {
-	nm256_releaseInterrupt (card);
-
-	card->recording = 0;
-	card->curRecPos = 0;
-    }
-}
-
-/*
- * Ring buffers, man.  That's where the hip-hop, wild-n-wooly action's at.
- * 1972?  (Well, I suppose it was cheep-n-easy to implement.)
- *
- * Write AMT bytes of BUFFER to the playback ring buffer, and start the
- * playback engine running.  It will only accept up to 1/2 of the total
- * size of the ring buffer.  No check is made that we're about to overwrite
- * the currently-playing sample.
- */
-
-static void
-nm256_write_block (struct nm256_info *card, char *buffer, u32 amt)
-{
-    u32 ringsize = card->playbackBufferSize;
-    u32 endstop;
-    unsigned long flags;
-
-    if (amt > (ringsize / 2)) {
-	printk (KERN_ERR "NM256: Write request too large: %d\n", amt);
-	amt = (ringsize / 2);
-    }
-
-    if (amt < NM256_PLAY_WMARK_SIZE) {
-	printk (KERN_ERR "NM256: Write request too small: %d\n", amt);
-	return;
-    }
-
-    card->curPlayPos %= ringsize;
-
-    card->requested_amt = amt;
-
-    spin_lock_irqsave(&card->lock,flags);
-
-    if ((card->curPlayPos + amt) >= ringsize) {
-	u32 rem = ringsize - card->curPlayPos;
-
-	nm256_writeBuffer8 (card, buffer, 1,
-			      card->abuf1 + card->curPlayPos,
-			      rem);
-	if (amt > rem)
-	    nm256_writeBuffer8 (card, buffer + rem, 1, card->abuf1,
-				  amt - rem);
-    } 
-    else
-	nm256_writeBuffer8 (card, buffer, 1,
-			      card->abuf1 + card->curPlayPos,
-			      amt);
-
-    /*
-     * Setup the start-n-stop-n-limit registers, and start that engine
-     * goin'. 
-     *
-     * Normally we just let it wrap around to avoid the click-click
-     * action scene.
-     */
-    if (! card->playing) {
-	/* The PBUFFER_END register in this case points to one sample
-	   before the end of the buffer. */
-	int w = (card->dev_for_play == card->dev[0] ? 0 : 1);
-	int sampsize = (card->sinfo[w].bits == 16 ? 2 : 1);
-
-	if (card->sinfo[w].stereo)
-	    sampsize *= 2;
-
-	/* Need to set the not-normally-changing-registers up. */
-	nm256_writePort32 (card, 2, NM_PBUFFER_START,
-			     card->abuf1 + card->curPlayPos);
-	nm256_writePort32 (card, 2, NM_PBUFFER_END,
-			     card->abuf1 + ringsize - sampsize);
-	nm256_writePort32 (card, 2, NM_PBUFFER_CURRP,
-			     card->abuf1 + card->curPlayPos);
-    }
-    endstop = (card->curPlayPos + amt - NM256_PLAY_WMARK_SIZE) % ringsize;
-    nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
-
-    if (! card->playing)
-	startPlay (card);
-
-    spin_unlock_irqrestore(&card->lock,flags);
-}
-
-/*  We just got a card playback interrupt; process it.  */
-static void
-nm256_get_new_block (struct nm256_info *card)
-{
-    /* Check to see how much got played so far. */
-    u32 amt = nm256_readPort32 (card, 2, NM_PBUFFER_CURRP) - card->abuf1;
-
-    if (amt >= card->playbackBufferSize) {
-	printk (KERN_ERR "NM256: Sound playback pointer invalid!\n");
-	amt = 0;
-    }
-
-    if (amt < card->curPlayPos)
-	amt = (card->playbackBufferSize - card->curPlayPos) + amt;
-    else
-	amt -= card->curPlayPos;
-
-    if (card->requested_amt > (amt + NM256_PLAY_WMARK_SIZE)) {
-	u32 endstop =
-	    card->curPlayPos + card->requested_amt - NM256_PLAY_WMARK_SIZE;
-	nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
-    } 
-    else {
-	card->curPlayPos += card->requested_amt;
-	/* Get a new block to write.  This will eventually invoke
-	   nm256_write_block () or stopPlay ().  */
-	DMAbuf_outputintr (card->dev_for_play, 1);
-    }
-}
-
-/* 
- * Read the last-recorded block from the ring buffer, copy it into the
- * saved buffer pointer, and invoke DMAuf_inputintr() with the recording
- * device. 
- */
-
-static void
-nm256_read_block (struct nm256_info *card)
-{
-    /* Grab the current position of the recording pointer. */
-    u32 currptr = nm256_readPort32 (card, 2, NM_RBUFFER_CURRP) - card->abuf2;
-    u32 amtToRead = card->requestedRecAmt;
-    u32 ringsize = card->recordBufferSize;
-
-    if (currptr >= card->recordBufferSize) {
-	printk (KERN_ERR "NM256: Sound buffer record pointer invalid!\n");
-        currptr = 0;
-    }
-
-    /*
-     * This test is probably redundant; we shouldn't be here unless
-     * it's true.
-     */
-    if (card->recording) {
-	/* If we wrapped around, copy everything from the start of our
-	   recording buffer to the end of the buffer. */
-	if (currptr < card->curRecPos) {
-	    u32 amt = min (ringsize - card->curRecPos, amtToRead);
-
-	    nm256_readBuffer8 (card, card->recBuf, 1,
-				 card->abuf2 + card->curRecPos,
-				 amt);
-	    amtToRead -= amt;
-	    card->curRecPos += amt;
-	    card->recBuf += amt;
-	    if (card->curRecPos == ringsize)
-		card->curRecPos = 0;
-	}
-
-	if ((card->curRecPos < currptr) && (amtToRead > 0)) {
-	    u32 amt = min (currptr - card->curRecPos, amtToRead);
-	    nm256_readBuffer8 (card, card->recBuf, 1,
-				 card->abuf2 + card->curRecPos, amt);
-	    card->curRecPos = ((card->curRecPos + amt) % ringsize);
-	}
-	card->recBuf = NULL;
-	card->requestedRecAmt = 0;
-	DMAbuf_inputintr (card->dev_for_record);
-    }
-}
-
-/*
- * Initialize the hardware. 
- */
-static void
-nm256_initHw (struct nm256_info *card)
-{
-    /* Reset everything. */
-    nm256_writePort8 (card, 2, 0x0, 0x11);
-    nm256_writePort16 (card, 2, 0x214, 0);
-
-    stopRecord (card);
-    stopPlay (card);
-}
-
-/* 
- * Handle a potential interrupt for the device referred to by DEV_ID. 
- *
- * I don't like the cut-n-paste job here either between the two routines,
- * but there are sufficient differences between the two interrupt handlers
- * that parameterizing it isn't all that great either.  (Could use a macro,
- * I suppose...yucky bleah.)
- */
-
-static irqreturn_t
-nm256_interrupt (int irq, void *dev_id)
-{
-    struct nm256_info *card = (struct nm256_info *)dev_id;
-    u16 status;
-    static int badintrcount;
-    int handled = 0;
-
-    if ((card == NULL) || (card->magsig != NM_MAGIC_SIG)) {
-	printk (KERN_ERR "NM256: Bad card pointer\n");
-	return IRQ_NONE;
-    }
-
-    status = nm256_readPort16 (card, 2, NM_INT_REG);
-
-    /* Not ours. */
-    if (status == 0) {
-	if (badintrcount++ > 1000) {
-	    /*
-	     * I'm not sure if the best thing is to stop the card from
-	     * playing or just release the interrupt (after all, we're in
-	     * a bad situation, so doing fancy stuff may not be such a good
-	     * idea).
-	     *
-	     * I worry about the card engine continuing to play noise
-	     * over and over, however--that could become a very
-	     * obnoxious problem.  And we know that when this usually
-	     * happens things are fairly safe, it just means the user's
-	     * inserted a PCMCIA card and someone's spamming us with IRQ 9s.
-	     */
-
-	    handled = 1;
-	    if (card->playing)
-		stopPlay (card);
-	    if (card->recording)
-		stopRecord (card);
-	    badintrcount = 0;
-	}
-	return IRQ_RETVAL(handled);
-    }
-
-    badintrcount = 0;
-
-    /* Rather boring; check for individual interrupts and process them. */
-
-    if (status & NM_PLAYBACK_INT) {
-	handled = 1;
-	status &= ~NM_PLAYBACK_INT;
-	NM_ACK_INT (card, NM_PLAYBACK_INT);
-
-	if (card->playing)
-	    nm256_get_new_block (card);
-    }
-
-    if (status & NM_RECORD_INT) {
-	handled = 1;
-	status &= ~NM_RECORD_INT;
-	NM_ACK_INT (card, NM_RECORD_INT);
-
-	if (card->recording)
-	    nm256_read_block (card);
-    }
-
-    if (status & NM_MISC_INT_1) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM_MISC_INT_1;
-	printk (KERN_ERR "NM256: Got misc interrupt #1\n");
-	NM_ACK_INT (card, NM_MISC_INT_1);
-	nm256_writePort16 (card, 2, NM_INT_REG, 0x8000);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte | 2);
-    }
-
-    if (status & NM_MISC_INT_2) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM_MISC_INT_2;
-	printk (KERN_ERR "NM256: Got misc interrupt #2\n");
-	NM_ACK_INT (card, NM_MISC_INT_2);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
-    }
-
-    /* Unknown interrupt. */
-    if (status) {
-	handled = 1;
-	printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
-		status);
-	/* Pray. */
-	NM_ACK_INT (card, status);
-    }
-    return IRQ_RETVAL(handled);
-}
-
-/*
- * Handle a potential interrupt for the device referred to by DEV_ID.
- * This handler is for the 256ZX, and is very similar to the non-ZX
- * routine.
- */
-
-static irqreturn_t
-nm256_interrupt_zx (int irq, void *dev_id)
-{
-    struct nm256_info *card = (struct nm256_info *)dev_id;
-    u32 status;
-    static int badintrcount;
-    int handled = 0;
-
-    if ((card == NULL) || (card->magsig != NM_MAGIC_SIG)) {
-	printk (KERN_ERR "NM256: Bad card pointer\n");
-	return IRQ_NONE;
-    }
-
-    status = nm256_readPort32 (card, 2, NM_INT_REG);
-
-    /* Not ours. */
-    if (status == 0) {
-	if (badintrcount++ > 1000) {
-	    printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n");
-	    /*
-	     * I'm not sure if the best thing is to stop the card from
-	     * playing or just release the interrupt (after all, we're in
-	     * a bad situation, so doing fancy stuff may not be such a good
-	     * idea).
-	     *
-	     * I worry about the card engine continuing to play noise
-	     * over and over, however--that could become a very
-	     * obnoxious problem.  And we know that when this usually
-	     * happens things are fairly safe, it just means the user's
-	     * inserted a PCMCIA card and someone's spamming us with 
-	     * IRQ 9s.
-	     */
-
-	    handled = 1;
-	    if (card->playing)
-		stopPlay (card);
-	    if (card->recording)
-		stopRecord (card);
-	    badintrcount = 0;
-	}
-	return IRQ_RETVAL(handled);
-    }
-
-    badintrcount = 0;
-
-    /* Rather boring; check for individual interrupts and process them. */
-
-    if (status & NM2_PLAYBACK_INT) {
-	handled = 1;
-	status &= ~NM2_PLAYBACK_INT;
-	NM2_ACK_INT (card, NM2_PLAYBACK_INT);
-
-	if (card->playing)
-	    nm256_get_new_block (card);
-    }
-
-    if (status & NM2_RECORD_INT) {
-	handled = 1;
-	status &= ~NM2_RECORD_INT;
-	NM2_ACK_INT (card, NM2_RECORD_INT);
-
-	if (card->recording)
-	    nm256_read_block (card);
-    }
-
-    if (status & NM2_MISC_INT_1) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM2_MISC_INT_1;
-	printk (KERN_ERR "NM256: Got misc interrupt #1\n");
-	NM2_ACK_INT (card, NM2_MISC_INT_1);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte | 2);
-    }
-
-    if (status & NM2_MISC_INT_2) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM2_MISC_INT_2;
-	printk (KERN_ERR "NM256: Got misc interrupt #2\n");
-	NM2_ACK_INT (card, NM2_MISC_INT_2);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
-    }
-
-    /* Unknown interrupt. */
-    if (status) {
-	handled = 1;
-	printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
-		status);
-	/* Pray. */
-	NM2_ACK_INT (card, status);
-    }
-    return IRQ_RETVAL(handled);
-}
-
-/* 
- * Request our interrupt.
- */
-static int
-nm256_grabInterrupt (struct nm256_info *card)
-{
-    if (card->has_irq++ == 0) {
-	if (request_irq (card->irq, card->introutine, IRQF_SHARED,
-			 "NM256_audio", card) < 0) {
-	    printk (KERN_ERR "NM256: can't obtain IRQ %d\n", card->irq);
-	    return -1;
-	}
-    }
-    return 0;
-}
-
-/* 
- * Release our interrupt. 
- */
-static int
-nm256_releaseInterrupt (struct nm256_info *card)
-{
-    if (card->has_irq <= 0) {
-	printk (KERN_ERR "nm256: too many calls to releaseInterrupt\n");
-	return -1;
-    }
-    card->has_irq--;
-    if (card->has_irq == 0) {
-	free_irq (card->irq, card);
-    }
-    return 0;
-}
-
-/*
- * Waits for the mixer to become ready to be written; returns a zero value
- * if it timed out.
- */
-
-static int
-nm256_isReady (struct ac97_hwint *dev)
-{
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-    int t2 = 10;
-    u32 testaddr;
-    u16 testb;
-    int done = 0;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in isReady!\n");
-	return 0;
-    }
-
-    testaddr = card->mixer_status_offset;
-    testb = card->mixer_status_mask;
-
-    /* 
-     * Loop around waiting for the mixer to become ready. 
-     */
-    while (! done && t2-- > 0) {
-	if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0)
-	    done = 1;
-	else
-	    udelay (100);
-    }
-    return done;
-}
-
-/*
- * Return the contents of the AC97 mixer register REG.  Returns a positive
- * value if successful, or a negative error code.
- */
-static int
-nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg)
-{
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in readAC97Reg!\n");
-	return -EINVAL;
-    }
-
-    if (reg < 128) {
-	int res;
-
-	nm256_isReady (dev);
-	res = nm256_readPort16 (card, 2, card->mixer + reg);
-	/* Magic delay.  Bleah yucky.  */
-        udelay (1000);
-	return res;
-    }
-    else
-	return -EINVAL;
-}
-
-/* 
- * Writes VALUE to AC97 mixer register REG.  Returns 0 if successful, or
- * a negative error code. 
- */
-static int
-nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value)
-{
-    unsigned long flags;
-    int tries = 2;
-    int done = 0;
-    u32 base;
-
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in writeAC97Reg!\n");
-	return -EINVAL;
-    }
-
-    base = card->mixer;
-
-    spin_lock_irqsave(&card->lock,flags);
-
-    nm256_isReady (dev);
-
-    /* Wait for the write to take, too. */
-    while ((tries-- > 0) && !done) {
-	nm256_writePort16 (card, 2, base + reg, value);
-	if (nm256_isReady (dev)) {
-	    done = 1;
-	    break;
-	}
-
-    }
-
-    spin_unlock_irqrestore(&card->lock,flags);
-    udelay (1000);
-
-    return ! done;
-}
-
-/* 
- * Initial register values to be written to the AC97 mixer.
- * While most of these are identical to the reset values, we do this
- * so that we have most of the register contents cached--this avoids
- * reading from the mixer directly (which seems to be problematic,
- * probably due to ignorance).
- */
-struct initialValues 
-{
-    unsigned short port;
-    unsigned short value;
-};
-
-static struct initialValues nm256_ac97_initial_values[] = 
-{
-    { AC97_MASTER_VOL_STEREO, 0x8000 },
-    { AC97_HEADPHONE_VOL,     0x8000 },
-    { AC97_MASTER_VOL_MONO,   0x0000 },
-    { AC97_PCBEEP_VOL,        0x0000 },
-    { AC97_PHONE_VOL,         0x0008 },
-    { AC97_MIC_VOL,           0x8000 },
-    { AC97_LINEIN_VOL,        0x8808 },
-    { AC97_CD_VOL,            0x8808 },
-    { AC97_VIDEO_VOL,         0x8808 },
-    { AC97_AUX_VOL,           0x8808 },
-    { AC97_PCMOUT_VOL,        0x0808 },
-    { AC97_RECORD_SELECT,     0x0000 },
-    { AC97_RECORD_GAIN,       0x0B0B },
-    { AC97_GENERAL_PURPOSE,   0x0000 },
-    { 0xffff, 0xffff }
-};
-
-/* Initialize the AC97 into a known state.  */
-static int
-nm256_resetAC97 (struct ac97_hwint *dev)
-{
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-    int x;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in resetAC97!\n");
-	return -EINVAL;
-    }
-
-    /* Reset the mixer.  'Tis magic!  */
-    nm256_writePort8 (card, 2, 0x6c0, 1);
-//  nm256_writePort8 (card, 2, 0x6cc, 0x87);	/* This crashes Dell latitudes */
-    nm256_writePort8 (card, 2, 0x6cc, 0x80);
-    nm256_writePort8 (card, 2, 0x6cc, 0x0);
-
-    if (! card->mixer_values_init) {
-	for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) {
-	    ac97_put_register (dev,
-			       nm256_ac97_initial_values[x].port,
-			       nm256_ac97_initial_values[x].value);
-	    card->mixer_values_init = 1;
-	}
-    }
-
-    return 0;
-}
-
-/*
- * We don't do anything particularly special here; it just passes the
- * mixer ioctl to the AC97 driver.
- */
-static int
-nm256_default_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
-{
-    struct nm256_info *card = nm256_find_card_for_mixer (dev);
-    if (card != NULL)
-	return ac97_mixer_ioctl (&(card->mdev), cmd, arg);
-    else
-	return -ENODEV;
-}
-
-static struct mixer_operations nm256_mixer_operations = {
-	.owner	= THIS_MODULE,
-	.id	= "NeoMagic",
-	.name	= "NM256AC97Mixer",
-	.ioctl	= nm256_default_mixer_ioctl
-};
-
-/*
- * Default settings for the OSS mixer.  These are set last, after the
- * mixer is initialized.
- *
- * I "love" C sometimes.  Got braces?
- */
-static struct ac97_mixer_value_list mixer_defaults[] = {
-    { SOUND_MIXER_VOLUME,  { { 85, 85 } } },
-    { SOUND_MIXER_SPEAKER, { { 100 } } },
-    { SOUND_MIXER_PCM,     { { 65, 65 } } },
-    { SOUND_MIXER_CD,      { { 65, 65 } } },
-    { -1,                  {  { 0,  0 } } }
-};
-
-
-/* Installs the AC97 mixer into CARD.  */
-static int __devinit
-nm256_install_mixer (struct nm256_info *card)
-{
-    int mixer;
-
-    card->mdev.reset_device = nm256_resetAC97;
-    card->mdev.read_reg = nm256_readAC97Reg;
-    card->mdev.write_reg = nm256_writeAC97Reg;
-    card->mdev.driver_private = (void *)card;
-
-    if (ac97_init (&(card->mdev)))
-	return -1;
-
-    mixer = sound_alloc_mixerdev();
-    if (num_mixers >= MAX_MIXER_DEV) {
-	printk ("NM256 mixer: Unable to alloc mixerdev\n");
-	return -1;
-    }
-
-    mixer_devs[mixer] = &nm256_mixer_operations;
-    card->mixer_oss_dev = mixer;
-
-    /* Some reasonable default values.  */
-    ac97_set_values (&(card->mdev), mixer_defaults);
-
-    printk(KERN_INFO "Initialized AC97 mixer\n");
-    return 0;
-}
-
-/* 
- * See if the signature left by the NM256 BIOS is intact; if so, we use
- * the associated address as the end of our audio buffer in the video
- * RAM.
- */
-
-static void __devinit
-nm256_peek_for_sig (struct nm256_info *card)
-{
-    u32 port1offset 
-	= card->port[0].physaddr + card->port[0].end_offset - 0x0400;
-    /* The signature is located 1K below the end of video RAM.  */
-    char __iomem *temp = ioremap_nocache (port1offset, 16);
-    /* Default buffer end is 5120 bytes below the top of RAM.  */
-    u32 default_value = card->port[0].end_offset - 0x1400;
-    u32 sig;
-
-    /* Install the default value first, so we don't have to repeatedly
-       do it if there is a problem.  */
-    card->port[0].end_offset = default_value;
-
-    if (temp == NULL) {
-	printk (KERN_ERR "NM256: Unable to scan for card signature in video RAM\n");
-	return;
-    }
-    sig = readl (temp);
-    if ((sig & NM_SIG_MASK) == NM_SIGNATURE) {
-	u32 pointer = readl (temp + 4);
-
-	/*
-	 * If it's obviously invalid, don't use it (the port already has a
-	 * suitable default value set).
-	 */
-	if (pointer != 0xffffffff)
-	    card->port[0].end_offset = pointer;
-
-	printk (KERN_INFO "NM256: Found card signature in video RAM: 0x%x\n",
-		pointer);
-    }
-
-    iounmap (temp);
-}
-
-/* 
- * Install a driver for the PCI device referenced by PCIDEV.
- * VERSTR is a human-readable version string.
- */
-
-static int __devinit
-nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
-{
-    struct nm256_info *card;
-    int x;
-
-    if (pci_enable_device(pcidev))
-	    return 0;
-
-    card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL);
-    if (card == NULL) {
-	printk (KERN_ERR "NM256: out of memory!\n");
-	return 0;
-    }
-
-    card->magsig = NM_MAGIC_SIG;
-    card->playing  = 0;
-    card->recording = 0;
-    card->rev = rev;
-    spin_lock_init(&card->lock);
-
-    /* Init the memory port info.  */
-    for (x = 0; x < 2; x++) {
-	card->port[x].physaddr = pci_resource_start (pcidev, x);
-	card->port[x].ptr = NULL;
-	card->port[x].start_offset = 0;
-	card->port[x].end_offset = 0;
-    }
-
-    /* Port 2 is easy.  */
-    card->port[1].start_offset = 0;
-    card->port[1].end_offset = NM_PORT2_SIZE;
-
-    /* Yuck.  But we have to map in port 2 so we can check how much RAM the
-       card has.  */
-    if (nm256_remap_ports (card)) {
-	kfree (card);
-	return 0;
-    }
-
-    /* 
-     * The NM256 has two memory ports.  The first port is nothing
-     * more than a chunk of video RAM, which is used as the I/O ring
-     * buffer.  The second port has the actual juicy stuff (like the
-     * mixer and the playback engine control registers).
-     */
-
-    if (card->rev == REV_NM256AV) {
-	/* Ok, try to see if this is a non-AC97 version of the hardware. */
-	int pval = nm256_readPort16 (card, 2, NM_MIXER_PRESENCE);
-	if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
-	    if (! force_load) {
-		printk (KERN_ERR "NM256: This doesn't look to me like the AC97-compatible version.\n");
-		printk (KERN_ERR "       You can force the driver to load by passing in the module\n");
-		printk (KERN_ERR "       parameter:\n");
-		printk (KERN_ERR "              force_load = 1\n");
-		printk (KERN_ERR "\n");
-		printk (KERN_ERR "       More likely, you should be using the appropriate SB-16 or\n");
-		printk (KERN_ERR "       CS4232 driver instead.  (If your BIOS has settings for\n");
-		printk (KERN_ERR "       IRQ and/or DMA for the sound card, this is *not* the correct\n");
-		printk (KERN_ERR "       driver to use.)\n");
-		nm256_release_ports (card);
-		kfree (card);
-		return 0;
-	    }
-	    else {
-		printk (KERN_INFO "NM256: Forcing driver load as per user request.\n");
-	    }
-	}
-	else {
-	 /*   printk (KERN_INFO "NM256: Congratulations. You're not running Eunice.\n")*/;
-	}
-	card->port[0].end_offset = 2560 * 1024;
-	card->introutine = nm256_interrupt;
-	card->mixer_status_offset = NM_MIXER_STATUS_OFFSET;
-	card->mixer_status_mask = NM_MIXER_READY_MASK;
-    } 
-    else {
-	/* Not sure if there is any relevant detect for the ZX or not.  */
-	if (nm256_readPort8 (card, 2, 0xa0b) != 0)
-	    card->port[0].end_offset = 6144 * 1024;
-	else
-	    card->port[0].end_offset = 4096 * 1024;
-
-	card->introutine = nm256_interrupt_zx;
-	card->mixer_status_offset = NM2_MIXER_STATUS_OFFSET;
-	card->mixer_status_mask = NM2_MIXER_READY_MASK;
-    }
-
-    if (buffertop >= 98304 && buffertop < card->port[0].end_offset)
-	card->port[0].end_offset = buffertop;
-    else
-	nm256_peek_for_sig (card);
-
-    card->port[0].start_offset = card->port[0].end_offset - 98304;
-
-    printk (KERN_INFO "NM256: Mapping port 1 from 0x%x - 0x%x\n",
-	    card->port[0].start_offset, card->port[0].end_offset);
-
-    if (nm256_remap_ports (card)) {
-	kfree (card);
-	return 0;
-    }
-
-    /* See if we can get the interrupt. */
-
-    card->irq = pcidev->irq;
-    card->has_irq = 0;
-
-    if (nm256_grabInterrupt (card) != 0) {
-	nm256_release_ports (card);
-	kfree (card);
-	return 0;
-    }
-
-    nm256_releaseInterrupt (card);
-
-    /*
-     *	Init the board.
-     */
-
-    card->playbackBufferSize = 16384;
-    card->recordBufferSize = 16384;
-
-    card->coeffBuf = card->port[0].end_offset - NM_MAX_COEFFICIENT;
-    card->abuf2 = card->coeffBuf - card->recordBufferSize;
-    card->abuf1 = card->abuf2 - card->playbackBufferSize;
-    card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4);
-
-    /* Fixed setting. */
-    card->mixer = NM_MIXER_OFFSET;
-    card->mixer_values_init = 0;
-
-    card->is_open_play = 0;
-    card->is_open_record = 0;
-
-    card->coeffsCurrent = 0;
-
-    card->opencnt[0] = 0; card->opencnt[1] = 0;
-
-    /* Reasonable default settings, but largely unnecessary. */
-    for (x = 0; x < 2; x++) {
-	card->sinfo[x].bits = 8;
-	card->sinfo[x].stereo = 0;
-	card->sinfo[x].samplerate = 8000;
-    }
-
-    nm256_initHw (card);
-
-    for (x = 0; x < 2; x++) {
-	if ((card->dev[x] =
-	     sound_install_audiodrv(AUDIO_DRIVER_VERSION,
-				    "NM256", &nm256_audio_driver,
-				    sizeof(struct audio_driver),
-				    DMA_NODMA, AFMT_U8 | AFMT_S16_LE,
-				    NULL, -1, -1)) >= 0) {
-	    /* 1K minimum buffer size. */
-	    audio_devs[card->dev[x]]->min_fragment = 10;
-	    /* Maximum of 8K buffer size. */
-	    audio_devs[card->dev[x]]->max_fragment = 13;
-	}
-	else {
-	    printk(KERN_ERR "NM256: Too many PCM devices available\n");
-	    nm256_release_ports (card);
-	    kfree (card);
-	    return 0;
-	}
-    }
-
-    pci_set_drvdata(pcidev,card);
-
-    /* Insert the card in the list.  */
-    card->next_card = nmcard_list;
-    nmcard_list = card;
-
-    printk(KERN_INFO "Initialized NeoMagic %s audio in PCI native mode\n",
-	   verstr);
-
-    /* 
-     * And our mixer.  (We should allow support for other mixers, maybe.)
-     */
-
-    nm256_install_mixer (card);
-
-    return 1;
-}
-
-
-static int __devinit
-nm256_probe(struct pci_dev *pcidev,const struct pci_device_id *pciid)
-{
-    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO)
-	return nm256_install(pcidev, REV_NM256AV, "256AV");
-    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO)
-	return nm256_install(pcidev, REV_NM256ZX, "256ZX");
-    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO)
-	return nm256_install(pcidev, REV_NM256ZX, "256XL+");
-    return -1; /* should not come here ... */
-}
-
-static void __devinit
-nm256_remove(struct pci_dev *pcidev) {
-    struct nm256_info *xcard = pci_get_drvdata(pcidev);
-    struct nm256_info *card,*next_card = NULL;
-
-    for (card = nmcard_list; card != NULL; card = next_card) {
-	next_card = card->next_card;
-	if (card == xcard) {
-	    stopPlay (card);
-	    stopRecord (card);
-	    if (card->has_irq)
-		free_irq (card->irq, card);
-	    nm256_release_ports (card);
-	    sound_unload_mixerdev (card->mixer_oss_dev);
-	    sound_unload_audiodev (card->dev[0]);
-	    sound_unload_audiodev (card->dev[1]);
-	    kfree (card);
-	    break;
-	}
-    }
-    if (nmcard_list == card)
-    	nmcard_list = next_card;
-}
-
-/*
- * Open the device
- *
- * DEV  - device
- * MODE - mode to open device (logical OR of OPEN_READ and OPEN_WRITE)
- *
- * Called when opening the DMAbuf               (dmabuf.c:259)
- */
-static int
-nm256_audio_open(int dev, int mode)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-    int w;
-	
-    if (card == NULL)
-	return -ENODEV;
-
-    if (card->dev[0] == dev)
-	w = 0;
-    else if (card->dev[1] == dev)
-	w = 1;
-    else
-	return -ENODEV;
-
-    if (card->opencnt[w] > 0)
-	return -EBUSY;
-
-    /* No bits set? Huh? */
-    if (! ((mode & OPEN_READ) || (mode & OPEN_WRITE)))
-	return -EIO;
-
-    /*
-     * If it's open for both read and write, and the card's currently
-     * being read or written to, then do the opposite of what has
-     * already been done.  Otherwise, don't specify any mode until the
-     * user actually tries to do I/O.  (Some programs open the device
-     * for both read and write, but only actually do reading or writing.)
-     */
-
-    if ((mode & OPEN_WRITE) && (mode & OPEN_READ)) {
-	if (card->is_open_play)
-	    mode = OPEN_WRITE;
-	else if (card->is_open_record)
-	    mode = OPEN_READ;
-	else mode = 0;
-    }
-	
-    if (mode & OPEN_WRITE) {
-	if (card->is_open_play == 0) {
-	    card->dev_for_play = dev;
-	    card->is_open_play = 1;
-	}
-	else
-	    return -EBUSY;
-    }
-
-    if (mode & OPEN_READ) {
-	if (card->is_open_record == 0) {
-	    card->dev_for_record = dev;
-	    card->is_open_record = 1;
-	}
-	else
-	    return -EBUSY;
-    }
-
-    card->opencnt[w]++;
-    return 0;
-}
-
-/*
- * Close the device
- *
- * DEV  - device
- *
- * Called when closing the DMAbuf               (dmabuf.c:477)
- *      after halt_xfer
- */
-static void
-nm256_audio_close(int dev)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-	
-    if (card != NULL) {
-	int w;
-
-	if (card->dev[0] == dev)
-	    w = 0;
-	else if (card->dev[1] == dev)
-	    w = 1;
-	else
-	    return;
-
-	card->opencnt[w]--;
-	if (card->opencnt[w] <= 0) {
-	    card->opencnt[w] = 0;
-
-	    if (card->dev_for_play == dev) {
-		stopPlay (card);
-		card->is_open_play = 0;
-		card->dev_for_play = -1;
-	    }
-
-	    if (card->dev_for_record == dev) {
-		stopRecord (card);
-		card->is_open_record = 0;
-		card->dev_for_record = -1;
-	    }
-	}
-    }
-}
-
-/* Standard ioctl handler. */
-static int
-nm256_audio_ioctl(int dev, unsigned int cmd, void __user *arg)
-{
-    int ret;
-    u32 oldinfo;
-    int w;
-
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card == NULL)
-	return -ENODEV;
-
-    if (dev == card->dev[0])
-	w = 0;
-    else
-	w = 1;
-
-    /* 
-     * The code here is messy.  There are probably better ways to do
-     * it.  (It should be possible to handle it the same way the AC97 mixer 
-     * is done.)
-     */
-    switch (cmd)
-	{
-	case SOUND_PCM_WRITE_RATE:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    if (ret != 0) {
-		oldinfo = card->sinfo[w].samplerate;
-		card->sinfo[w].samplerate = ret;
-		ret = nm256_setInfo(dev, card);
-		if (ret != 0)
-		    card->sinfo[w].samplerate = oldinfo;
-	    }
-	    if (ret == 0)
-		ret = card->sinfo[w].samplerate;
-	    break;
-
-	case SOUND_PCM_READ_RATE:
-	    ret = card->sinfo[w].samplerate;
-	    break;
-
-	case SNDCTL_DSP_STEREO:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    card->sinfo[w].stereo = ret ? 1 : 0;
-	    ret = nm256_setInfo (dev, card);
-	    if (ret == 0)
-		ret = card->sinfo[w].stereo;
-
-	    break;
-
-	case SOUND_PCM_WRITE_CHANNELS:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    if (ret < 1 || ret > 3)
-		ret = card->sinfo[w].stereo + 1;
-	    else {
-		card->sinfo[w].stereo = ret - 1;
-		ret = nm256_setInfo (dev, card);
-		if (ret == 0)
-		    ret = card->sinfo[w].stereo + 1;
-	    }
-	    break;
-
-	case SOUND_PCM_READ_CHANNELS:
-	    ret = card->sinfo[w].stereo + 1;
-	    break;
-
-	case SNDCTL_DSP_SETFMT:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    if (ret != 0) {
-		oldinfo = card->sinfo[w].bits;
-		card->sinfo[w].bits = ret;
-		ret = nm256_setInfo (dev, card);
-		if (ret != 0)
-		    card->sinfo[w].bits = oldinfo;
-	    }
-	    if (ret == 0)
-		ret = card->sinfo[w].bits;
-	    break;
-
-	case SOUND_PCM_READ_BITS:
-	    ret = card->sinfo[w].bits;
-	    break;
-
-	default:
-	    return -EINVAL;
-	}
-    return put_user(ret, (int __user *) arg);
-}
-
-/*
- * Given the sound device DEV and an associated physical buffer PHYSBUF, 
- * return a pointer to the actual buffer in kernel space. 
- *
- * This routine should exist as part of the soundcore routines.
- */
-
-static char *
-nm256_getDMAbuffer (int dev, unsigned long physbuf)
-{
-    struct audio_operations *adev = audio_devs[dev];
-    struct dma_buffparms *dmap = adev->dmap_out;
-    char *dma_start =
-	(char *)(physbuf - (unsigned long)dmap->raw_buf_phys 
-		 + (unsigned long)dmap->raw_buf);
-
-    return dma_start;
-}
-
-
-/*
- * Output a block to sound device
- *
- * dev          - device number
- * buf          - physical address of buffer
- * total_count  - total byte count in buffer
- * intrflag     - set if this has been called from an interrupt 
- *				  (via DMAbuf_outputintr)
- * restart_dma  - set if engine needs to be re-initialised
- *
- * Called when:
- *  1. Starting output                                  (dmabuf.c:1327)
- *  2.                                                  (dmabuf.c:1504)
- *  3. A new buffer needs to be sent to the device      (dmabuf.c:1579)
- */
-static void
-nm256_audio_output_block(int dev, unsigned long physbuf,
-				       int total_count, int intrflag)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card != NULL) {
-	char *dma_buf = nm256_getDMAbuffer (dev, physbuf);
-	card->is_open_play = 1;
-	card->dev_for_play = dev;
-	nm256_write_block (card, dma_buf, total_count);
-    }
-}
-
-/* Ditto, but do recording instead.  */
-static void
-nm256_audio_start_input(int dev, unsigned long physbuf, int count,
-			int intrflag)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card != NULL) {
-	char *dma_buf = nm256_getDMAbuffer (dev, physbuf);
-	card->is_open_record = 1;
-	card->dev_for_record = dev;
-	nm256_startRecording (card, dma_buf, count);
-    }
-}
-
-/* 
- * Prepare for inputting samples to DEV. 
- * Each requested buffer will be BSIZE byes long, with a total of
- * BCOUNT buffers. 
- */
-
-static int
-nm256_audio_prepare_for_input(int dev, int bsize, int bcount)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card == NULL) 
-	return -ENODEV;
-
-    if (card->is_open_record && card->dev_for_record != dev)
-	return -EBUSY;
-
-    audio_devs[dev]->dmap_in->flags |= DMA_NODMA;
-    return 0;
-}
-
-/*
- * Prepare for outputting samples to `dev'
- *
- * Each buffer that will be passed will be `bsize' bytes long,
- * with a total of `bcount' buffers.
- *
- * Called when:
- *  1. A trigger enables audio output                   (dmabuf.c:978)
- *  2. We get a write buffer without dma_mode setup     (dmabuf.c:1152)
- *  3. We restart a transfer                            (dmabuf.c:1324)
- */
-
-static int
-nm256_audio_prepare_for_output(int dev, int bsize, int bcount)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card == NULL)
-	return -ENODEV;
-
-    if (card->is_open_play && card->dev_for_play != dev)
-	return -EBUSY;
-
-    audio_devs[dev]->dmap_out->flags |= DMA_NODMA;
-    return 0;
-}
-
-/* Stop the current operations associated with DEV.  */
-static void
-nm256_audio_reset(int dev)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card != NULL) {
-	if (card->dev_for_play == dev)
-	    stopPlay (card);
-	if (card->dev_for_record == dev)
-	    stopRecord (card);
-    }
-}
-
-static int
-nm256_audio_local_qlen(int dev)
-{
-    return 0;
-}
-
-static struct audio_driver nm256_audio_driver =
-{
-	.owner			= THIS_MODULE,
-	.open			= nm256_audio_open,
-	.close			= nm256_audio_close,
-	.output_block		= nm256_audio_output_block,
-	.start_input		= nm256_audio_start_input,
-	.ioctl			= nm256_audio_ioctl,
-	.prepare_for_input	= nm256_audio_prepare_for_input,
-	.prepare_for_output	= nm256_audio_prepare_for_output,
-	.halt_io		= nm256_audio_reset,
-	.local_qlen		= nm256_audio_local_qlen,
-};
-
-static struct pci_device_id nm256_pci_tbl[] = {
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO,
-	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO,
-	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO,
-	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{0,}
-};
-MODULE_DEVICE_TABLE(pci, nm256_pci_tbl);
-MODULE_LICENSE("GPL");
-
-
-static struct pci_driver nm256_pci_driver = {
-	.name		= "nm256_audio",
-	.id_table	= nm256_pci_tbl,
-	.probe		= nm256_probe,
-	.remove		= nm256_remove,
-};
-
-module_param(usecache, bool, 0);
-module_param(buffertop, int, 0);
-module_param(nm256_debug, bool, 0644);
-module_param(force_load, bool, 0);
-
-static int __init do_init_nm256(void)
-{
-    printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1p\n");
-    return pci_register_driver(&nm256_pci_driver);
-}
-
-static void __exit cleanup_nm256 (void)
-{
-    pci_unregister_driver(&nm256_pci_driver);
-}
-
-module_init(do_init_nm256);
-module_exit(cleanup_nm256);
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/nm256_coeff.h b/sound/oss/nm256_coeff.h
deleted file mode 100644
index 6fc07f3..0000000
--- a/sound/oss/nm256_coeff.h
+++ /dev/null
@@ -1,4697 +0,0 @@
-#ifndef NM256_COEFF_H
-#define NM256_COEFF_H
-
-#define NM_TOTAL_COEFF_COUNT 0x3158
-
-static char coefficients[NM_TOTAL_COEFF_COUNT * 4] = { 
-	0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA5, 0x01, 0xEF, 0xFC, 0x21,
-	0x05, 0x87, 0xF7, 0x62, 0x11, 0xE9, 0x45, 0x5E, 0xF9, 0xB5, 0x01,
-	0xDE, 0xFF, 0xA4, 0xFF, 0x60, 0x00, 0xCA, 0xFF, 0x0D, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06,
-	0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1,
-	0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFD, 0xFF,
-	0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E,
-	0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC,
-	0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x02, 0x00, 0x05,
-	0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
-	0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
-	0x60, 0x00, 0xA4, 0xFF, 0xDE, 0xFF, 0xB5, 0x01, 0x5E, 0xF9, 0xE9,
-	0x45, 0x62, 0x11, 0x87, 0xF7, 0x21, 0x05, 0xEF, 0xFC, 0xA5, 0x01,
-	0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84,
-	0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
-	0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
-	0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-	0xCA, 0x01, 0x95, 0xFC, 0xEA, 0x05, 0xBB, 0xF5, 0x25, 0x17, 0x3C,
-	0x43, 0x8D, 0xF6, 0x43, 0x03, 0xF5, 0xFE, 0x26, 0x00, 0x20, 0x00,
-	0xE2, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5,
-	0x01, 0x4C, 0xFC, 0x26, 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33,
-	0x8F, 0xF1, 0xCA, 0x06, 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD5, 0xFF, 0xBC, 0x00,
-	0xF0, 0xFD, 0xEC, 0x04, 0xD9, 0xF3, 0xB1, 0x3E, 0xCD, 0x1E, 0xC1,
-	0xF3, 0xAF, 0x06, 0x49, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38,
-	0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA,
-	0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0x98, 0x01, 0x0D, 0xFD,
-	0xE0, 0x04, 0x14, 0xF8, 0xC3, 0x0F, 0x89, 0x46, 0x4C, 0xFA, 0x38,
-	0x01, 0x25, 0x00, 0x7D, 0xFF, 0x73, 0x00, 0xC2, 0xFF, 0x0F, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F,
-	0x07, 0x84, 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05,
-	0x41, 0xFD, 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x15, 0x00, 0x97, 0xFF, 0x37, 0x01, 0x22, 0xFD, 0x23, 0x06,
-	0x2F, 0xF2, 0x11, 0x39, 0x7B, 0x26, 0x50, 0xF2, 0x1B, 0x07, 0x32,
-	0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-	0xC8, 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93,
-	0xF9, 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC,
-	0xA2, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
-	0x00, 0x6A, 0xFF, 0x53, 0x01, 0xA6, 0xFD, 0xA6, 0x03, 0xA1, 0xFA,
-	0xDE, 0x08, 0x76, 0x48, 0x0C, 0xFF, 0xDE, 0xFE, 0x73, 0x01, 0xC9,
-	0xFE, 0xCA, 0x00, 0xA0, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
-	0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
-	0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x68,
-	0xFF, 0x93, 0x01, 0x92, 0xFC, 0xE2, 0x06, 0x83, 0xF1, 0x8C, 0x32,
-	0xED, 0x2D, 0x90, 0xF1, 0x1E, 0x07, 0x57, 0xFC, 0xBD, 0x01, 0x51,
-	0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00,
-	0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76,
-	0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, 0x03, 0x01, 0x53,
-	0xFE, 0x53, 0x02, 0x39, 0xFD, 0xA9, 0x02, 0xF2, 0x48, 0xB9, 0x04,
-	0x54, 0xFC, 0xCA, 0x02, 0x16, 0xFE, 0x20, 0x01, 0x7F, 0xFF, 0x20,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC3, 0x01,
-	0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7, 0x43, 0x20,
-	0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00, 0xDD, 0xFF,
-	0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCD, 0x01, 0x43,
-	0xFC, 0x2A, 0x07, 0xBC, 0xF1, 0x64, 0x2B, 0xE3, 0x34, 0xA3, 0xF1,
-	0xAE, 0x06, 0xBD, 0xFC, 0x77, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
-	0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8, 0xFD,
-	0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3, 0xC8,
-	0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x14, 0x00, 0xAC, 0xFF, 0xAC, 0x00, 0x08, 0xFF, 0xFD, 0x00, 0xB5,
-	0xFF, 0x4B, 0xFD, 0xF4, 0x47, 0x30, 0x0B, 0xBC, 0xF9, 0x17, 0x04,
-	0x6E, 0xFD, 0x6D, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01, 0x26, 0xFD, 0xAD, 0x04,
-	0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C, 0xFB, 0xD4, 0x00, 0x5D,
-	0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0x01, 0x07, 0xBE,
-	0xF2, 0xD6, 0x23, 0x1F, 0x3B, 0xA5, 0xF2, 0xC5, 0x05, 0x62, 0xFD,
-	0x10, 0x01, 0xAB, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19,
-	0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD, 0x4D, 0x06, 0x00, 0xF2,
-	0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23, 0x07, 0x34, 0xFC, 0xDD,
-	0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF,
-	0x56, 0x00, 0xB9, 0xFF, 0xB8, 0xFF, 0xF7, 0x01, 0xE2, 0xF8, 0x8D,
-	0x45, 0x46, 0x12, 0x3C, 0xF7, 0x43, 0x05, 0xDF, 0xFC, 0xAC, 0x01,
-	0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70,
-	0xFF, 0x46, 0x01, 0xC3, 0xFD, 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07,
-	0xA6, 0x48, 0xF8, 0xFF, 0x70, 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9,
-	0x00, 0x9A, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xDE, 0x01, 0x5D, 0xFC, 0x74, 0x06, 0x63, 0xF4, 0x23, 0x1C, 0x66,
-	0x40, 0xAA, 0xF4, 0x65, 0x04, 0x44, 0xFE, 0x8B, 0x00, 0xEE, 0xFF,
-	0xF5, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F,
-	0x01, 0x80, 0xFC, 0xF7, 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F,
-	0x83, 0xF1, 0x13, 0x07, 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C,
-	0x00, 0xFD, 0xFF, 0x06, 0x00, 0xED, 0xFF, 0x05, 0x00, 0x5D, 0x00,
-	0x95, 0xFE, 0xE2, 0x03, 0x7F, 0xF5, 0xCC, 0x41, 0xC7, 0x19, 0xFF,
-	0xF4, 0x37, 0x06, 0x75, 0xFC, 0xD6, 0x01, 0x39, 0xFF, 0x35, 0x00,
-	0xFE, 0xFF, 0x1B, 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18,
-	0x02, 0xAA, 0xFD, 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB,
-	0x05, 0x03, 0xF7, 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBB, 0x01, 0xBA, 0xFC,
-	0x95, 0x05, 0x83, 0xF6, 0x8C, 0x14, 0x87, 0x44, 0xBB, 0xF7, 0x98,
-	0x02, 0x5A, 0xFF, 0xEE, 0xFF, 0x3C, 0x00, 0xD8, 0xFF, 0x0A, 0x00,
-	0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A,
-	0x07, 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06,
-	0xD5, 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01,
-	0x00, 0x07, 0x00, 0xBE, 0xFF, 0xEA, 0x00, 0xA2, 0xFD, 0x65, 0x05,
-	0x28, 0xF3, 0xDB, 0x3C, 0x78, 0x21, 0x30, 0xF3, 0xDF, 0x06, 0x3A,
-	0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
-	0xB2, 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76,
-	0xFC, 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD,
-	0x79, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
-	0x00, 0x58, 0xFF, 0x82, 0x01, 0x3F, 0xFD, 0x78, 0x04, 0xF2, 0xF8,
-	0x50, 0x0D, 0x5E, 0x47, 0xD5, 0xFB, 0x6F, 0x00, 0x96, 0x00, 0x40,
-	0xFF, 0x91, 0x00, 0xB7, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
-	0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
-	0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x85,
-	0xFF, 0x5B, 0x01, 0xE9, 0xFC, 0x73, 0x06, 0xD8, 0xF1, 0xE5, 0x36,
-	0x19, 0x29, 0xF8, 0xF1, 0x29, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x42,
-	0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3, 0xFF, 0x47, 0x00,
-	0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44, 0x8D,
-	0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45, 0xFF,
-	0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x75, 0xFF, 0x39,
-	0x01, 0xE0, 0xFD, 0x33, 0x03, 0x87, 0xFB, 0xA2, 0x06, 0xCB, 0x48,
-	0xEA, 0x00, 0x01, 0xFE, 0xE9, 0x01, 0x8A, 0xFE, 0xE8, 0x00, 0x95,
-	0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF, 0xDA, 0x01,
-	0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32, 0x41, 0x1F,
-	0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF, 0xF0, 0xFF,
-	0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5B, 0xFF, 0xAB, 0x01, 0x6F,
-	0xFC, 0x08, 0x07, 0x7E, 0xF1, 0x21, 0x30, 0x67, 0x30, 0x7D, 0xF1,
-	0x05, 0x07, 0x73, 0xFC, 0xA8, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD,
-	0xFF, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0x67, 0xFE,
-	0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B, 0xA6, 0xF4, 0x5A,
-	0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-	0x1A, 0x00, 0x96, 0xFF, 0xE5, 0x00, 0x91, 0xFE, 0xDC, 0x01, 0x1A,
-	0xFE, 0xB3, 0x00, 0xC3, 0x48, 0xE1, 0x06, 0x6E, 0xFB, 0x40, 0x03,
-	0xDA, 0xFD, 0x3C, 0x01, 0x74, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05,
-	0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E,
-	0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-	0x33, 0x00, 0x41, 0xFF, 0xD9, 0x01, 0x36, 0xFC, 0x28, 0x07, 0x01,
-	0xF2, 0xCE, 0x28, 0x23, 0x37, 0xE0, 0xF1, 0x6B, 0x06, 0xEF, 0xFC,
-	0x57, 0x01, 0x87, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B,
-	0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E, 0xFD, 0x9C, 0x05, 0xDC, 0xF2,
-	0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2, 0xF3, 0x06, 0x35, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xB8, 0xFF,
-	0x8E, 0x00, 0x46, 0xFF, 0x8A, 0x00, 0x86, 0x00, 0xA7, 0xFB, 0x48,
-	0x47, 0x95, 0x0D, 0xD9, 0xF8, 0x84, 0x04, 0x39, 0xFD, 0x85, 0x01,
-	0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
-	0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
-	0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
-	0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE6, 0x01, 0x3B, 0xFC, 0xDA, 0x06, 0x3F, 0xF3, 0x2C, 0x21, 0x11,
-	0x3D, 0x3A, 0xF3, 0x58, 0x05, 0xAA, 0xFD, 0xE5, 0x00, 0xC1, 0xFF,
-	0x06, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B,
-	0x01, 0xCF, 0xFC, 0x96, 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A,
-	0xD4, 0xF1, 0x2B, 0x07, 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32,
-	0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD9, 0xFF, 0x39, 0x00, 0xF4, 0xFF,
-	0x4E, 0xFF, 0xAC, 0x02, 0x98, 0xF7, 0x65, 0x44, 0xD6, 0x14, 0x6C,
-	0xF6, 0x9F, 0x05, 0xB6, 0xFC, 0xBD, 0x01, 0x42, 0xFF, 0x32, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE,
-	0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01,
-	0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C,
-	0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD5, 0x01, 0x78, 0xFC,
-	0x2F, 0x06, 0x13, 0xF5, 0x7C, 0x19, 0xF7, 0x41, 0x9B, 0xF5, 0xD1,
-	0x03, 0x9F, 0xFE, 0x57, 0x00, 0x08, 0x00, 0xEC, 0xFF, 0x06, 0x00,
-	0xFD, 0xFF, 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16,
-	0x07, 0x85, 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06,
-	0x84, 0xFC, 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04,
-	0x00, 0xF6, 0xFF, 0xEB, 0xFF, 0x91, 0x00, 0x3B, 0xFE, 0x75, 0x04,
-	0x92, 0xF4, 0x36, 0x40, 0x6E, 0x1C, 0x50, 0xF4, 0x7B, 0x06, 0x5B,
-	0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00,
-	0x9C, 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3,
-	0xFF, 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD,
-	0x49, 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-	0x00, 0x49, 0xFF, 0xAA, 0x01, 0xE4, 0xFC, 0x38, 0x05, 0x54, 0xF7,
-	0xFE, 0x11, 0xAA, 0x45, 0x09, 0xF9, 0xE2, 0x01, 0xC4, 0xFF, 0xB3,
-	0xFF, 0x59, 0x00, 0xCD, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
-	0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
-	0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA9,
-	0xFF, 0x15, 0x01, 0x5B, 0xFD, 0xD0, 0x05, 0x97, 0xF2, 0xE6, 0x3A,
-	0x21, 0x24, 0xB1, 0xF2, 0x04, 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x39,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00,
-	0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD,
-	0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF,
-	0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x6A,
-	0x01, 0x74, 0xFD, 0x0A, 0x04, 0xD5, 0xF9, 0xED, 0x0A, 0x03, 0x48,
-	0x7C, 0xFD, 0x9E, 0xFF, 0x0A, 0x01, 0x01, 0xFF, 0xAF, 0x00, 0xAB,
-	0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01,
-	0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE, 0x3D, 0x91,
-	0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF, 0x02, 0x00,
-	0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x75, 0xFF, 0x7A, 0x01, 0xB8,
-	0xFC, 0xB4, 0x06, 0x9E, 0xF1, 0xA2, 0x34, 0xAD, 0x2B, 0xB6, 0xF1,
-	0x29, 0x07, 0x45, 0xFC, 0xCB, 0x01, 0x49, 0xFF, 0x31, 0x00, 0xFD,
-	0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B, 0xFF,
-	0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6, 0xCA,
-	0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x20, 0x00, 0x80, 0xFF, 0x1C, 0x01, 0x1C, 0xFE, 0xBD,
-	0x02, 0x6E, 0xFC, 0x7D, 0x04, 0xF3, 0x48, 0xE2, 0x02, 0x1F, 0xFD,
-	0x60, 0x02, 0x4C, 0xFE, 0x06, 0x01, 0x89, 0xFF, 0x1D, 0x00, 0xFE,
-	0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01, 0x88, 0xFC, 0x09, 0x06,
-	0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20, 0xF6, 0x83, 0x03, 0xCF,
-	0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
-	0x2E, 0x00, 0x50, 0xFF, 0xBF, 0x01, 0x54, 0xFC, 0x20, 0x07, 0x94,
-	0xF1, 0xA6, 0x2D, 0xD0, 0x32, 0x85, 0xF1, 0xDD, 0x06, 0x96, 0xFC,
-	0x90, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB,
-	0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE, 0xB9, 0x04, 0x27, 0xF4,
-	0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99, 0x06, 0x50, 0xFC, 0xE2,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA2, 0xFF,
-	0xC7, 0x00, 0xD0, 0xFE, 0x65, 0x01, 0xF6, 0xFE, 0xD9, 0xFE, 0x6A,
-	0x48, 0x1F, 0x09, 0x87, 0xFA, 0xB3, 0x03, 0xA0, 0xFD, 0x56, 0x01,
-	0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4D,
-	0xFF, 0xA0, 0x01, 0xFB, 0xFC, 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10,
-	0x2B, 0x46, 0xBB, 0xF9, 0x83, 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68,
-	0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
-	0xE1, 0x01, 0x31, 0xFC, 0x19, 0x07, 0x5B, 0xF2, 0x30, 0x26, 0x4B,
-	0x39, 0x3B, 0xF2, 0x1A, 0x06, 0x29, 0xFD, 0x33, 0x01, 0x99, 0xFF,
-	0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28,
-	0x01, 0x3A, 0xFD, 0x00, 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25,
-	0x79, 0xF2, 0x12, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35,
-	0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC4, 0xFF, 0x70, 0x00, 0x84, 0xFF,
-	0x19, 0x00, 0x4D, 0x01, 0x22, 0xFA, 0x70, 0x46, 0x0A, 0x10, 0xFC,
-	0xF7, 0xEB, 0x04, 0x08, 0xFD, 0x9A, 0x01, 0x4F, 0xFF, 0x2E, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90,
-	0xFD, 0xD2, 0x03, 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE,
-	0x33, 0xFF, 0x45, 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16,
-	0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4B, 0xFC,
-	0xA9, 0x06, 0xD2, 0xF3, 0x81, 0x1E, 0xE4, 0x3E, 0xEF, 0xF3, 0xDE,
-	0x04, 0xF9, 0xFD, 0xB7, 0x00, 0xD8, 0xFF, 0xFD, 0xFF, 0x03, 0x00,
-	0xFD, 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0,
-	0x06, 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07,
-	0x4E, 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08,
-	0x00, 0xE4, 0xFF, 0x1D, 0x00, 0x2D, 0x00, 0xEA, 0xFE, 0x56, 0x03,
-	0x6D, 0xF6, 0x17, 0x43, 0x70, 0x17, 0xA6, 0xF5, 0xF3, 0x05, 0x91,
-	0xFC, 0xCC, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-	0x86, 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73,
-	0x03, 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE,
-	0x14, 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33,
-	0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x99, 0xFC, 0xE1, 0x05, 0xD1, 0xF5,
-	0xDC, 0x16, 0x65, 0x43, 0xAD, 0xF6, 0x31, 0x03, 0x00, 0xFF, 0x20,
-	0x00, 0x23, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00,
-	0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
-	0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
-	0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xFF, 0xFF, 0xD3,
-	0xFF, 0xC1, 0x00, 0xE7, 0xFD, 0xFA, 0x04, 0xC4, 0xF3, 0x7E, 0x3E,
-	0x19, 0x1F, 0xB0, 0xF3, 0xB5, 0x06, 0x47, 0xFC, 0xE4, 0x01, 0x36,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8, 0x00,
-	0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48, 0x47,
-	0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64, 0xFF,
-	0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x96,
-	0x01, 0x13, 0xFD, 0xD5, 0x04, 0x2C, 0xF8, 0x7D, 0x0F, 0xA3, 0x46,
-	0x76, 0xFA, 0x22, 0x01, 0x32, 0x00, 0x76, 0xFF, 0x76, 0x00, 0xC1,
-	0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF, 0xE4, 0x01,
-	0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54, 0x3A, 0x74,
-	0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF, 0x11, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x95, 0xFF, 0x3B, 0x01, 0x1B,
-	0xFD, 0x2D, 0x06, 0x24, 0xF2, 0xD3, 0x38, 0xC6, 0x26, 0x45, 0xF2,
-	0x1D, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2, 0xFF, 0xE2, 0xFF,
-	0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11, 0x8F, 0xF7, 0x1D,
-	0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x51, 0x01, 0xAC, 0xFD, 0x9A,
-	0x03, 0xBA, 0xFA, 0x9E, 0x08, 0x81, 0x48, 0x40, 0xFF, 0xC6, 0xFE,
-	0x80, 0x01, 0xC2, 0xFE, 0xCE, 0x00, 0x9F, 0xFF, 0x17, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06,
-	0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23,
-	0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFD, 0xFF,
-	0x27, 0x00, 0x66, 0xFF, 0x96, 0x01, 0x8E, 0xFC, 0xE7, 0x06, 0x81,
-	0xF1, 0x48, 0x32, 0x34, 0x2E, 0x8D, 0xF1, 0x1C, 0x07, 0x5A, 0xFC,
-	0xBB, 0x01, 0x53, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9,
-	0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9, 0xFE, 0xA6, 0x03, 0xE4, 0xF5,
-	0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5, 0x1A, 0x06, 0x81, 0xFC, 0xD2,
-	0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8B, 0xFF,
-	0xFF, 0x00, 0x5A, 0xFE, 0x46, 0x02, 0x52, 0xFD, 0x70, 0x02, 0xED,
-	0x48, 0xF5, 0x04, 0x3B, 0xFC, 0xD7, 0x02, 0x0F, 0xFE, 0x23, 0x01,
-	0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-	0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
-	0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
-	0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF,
-	0xCE, 0x01, 0x41, 0xFC, 0x2A, 0x07, 0xC2, 0xF1, 0x1B, 0x2B, 0x25,
-	0x35, 0xA8, 0xF1, 0xA7, 0x06, 0xC2, 0xFC, 0x74, 0x01, 0x78, 0xFF,
-	0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9,
-	0x00, 0xBF, 0xFD, 0x38, 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20,
-	0x66, 0xF3, 0xCE, 0x06, 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAE, 0xFF, 0xA9, 0x00, 0x0F, 0xFF,
-	0xF0, 0x00, 0xCD, 0xFF, 0x1B, 0xFD, 0xE4, 0x47, 0x73, 0x0B, 0xA2,
-	0xF9, 0x23, 0x04, 0x68, 0xFD, 0x70, 0x01, 0x5F, 0xFF, 0x29, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B,
-	0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB,
-	0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC,
-	0xFD, 0x06, 0xCB, 0xF2, 0x8A, 0x23, 0x58, 0x3B, 0xB4, 0xF2, 0xBA,
-	0x05, 0x6A, 0xFD, 0x0B, 0x01, 0xAE, 0xFF, 0x0D, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56,
-	0x06, 0xF7, 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07,
-	0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
-	0x00, 0xCF, 0xFF, 0x52, 0x00, 0xC0, 0xFF, 0xAC, 0xFF, 0x0C, 0x02,
-	0xBC, 0xF8, 0x6D, 0x45, 0x8E, 0x12, 0x24, 0xF7, 0x4D, 0x05, 0xDB,
-	0xFC, 0xAE, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x24, 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E,
-	0xFB, 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01,
-	0xA3, 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xDD, 0x01, 0x60, 0xFC, 0x6D, 0x06, 0x76, 0xF4,
-	0xD8, 0x1B, 0x95, 0x40, 0xC3, 0xF4, 0x56, 0x04, 0x4E, 0xFE, 0x85,
-	0x00, 0xF1, 0xFF, 0xF4, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00,
-	0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
-	0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
-	0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x02,
-	0x00, 0x63, 0x00, 0x8A, 0xFE, 0xF3, 0x03, 0x63, 0xF5, 0xA1, 0x41,
-	0x12, 0x1A, 0xEB, 0xF4, 0x3F, 0x06, 0x72, 0xFC, 0xD7, 0x01, 0x39,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00,
-	0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07,
-	0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF,
-	0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBA,
-	0x01, 0xBF, 0xFC, 0x8B, 0x05, 0x99, 0xF6, 0x43, 0x14, 0xA9, 0x44,
-	0xDE, 0xF7, 0x85, 0x02, 0x65, 0xFF, 0xE7, 0xFF, 0x3F, 0x00, 0xD6,
-	0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD5, 0x01,
-	0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46, 0x36, 0xC5,
-	0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF, 0x1E, 0x00,
-	0xFE, 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBC, 0xFF, 0xEF, 0x00, 0x9A,
-	0xFD, 0x72, 0x05, 0x16, 0xF3, 0xA5, 0x3C, 0xC4, 0x21, 0x21, 0xF3,
-	0xE4, 0x06, 0x39, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6, 0x00,
-	0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9, 0x5A,
-	0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x80, 0x01, 0x45, 0xFD, 0x6C,
-	0x04, 0x0B, 0xF9, 0x0B, 0x0D, 0x73, 0x47, 0x02, 0xFC, 0x58, 0x00,
-	0xA3, 0x00, 0x39, 0xFF, 0x94, 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37, 0xFC, 0xEB, 0x06,
-	0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD, 0xF2, 0x84, 0x05, 0x8D,
-	0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF,
-	0x1D, 0x00, 0x83, 0xFF, 0x5E, 0x01, 0xE3, 0xFC, 0x7B, 0x06, 0xD0,
-	0xF1, 0xA5, 0x36, 0x62, 0x29, 0xEF, 0xF1, 0x29, 0x07, 0x39, 0xFC,
-	0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5,
-	0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF, 0x67, 0x02, 0x14, 0xF8,
-	0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C, 0x05, 0xC5, 0xFC, 0xB7,
-	0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00,
-	0x76, 0xFF, 0x35, 0x01, 0xE7, 0xFD, 0x26, 0x03, 0xA1, 0xFB, 0x64,
-	0x06, 0xD2, 0x48, 0x21, 0x01, 0xE8, 0xFD, 0xF7, 0x01, 0x83, 0xFE,
-	0xEC, 0x00, 0x93, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39,
-	0xFF, 0xD9, 0x01, 0x6D, 0xFC, 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A,
-	0x5F, 0x41, 0x3A, 0xF5, 0x0C, 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE,
-	0xFF, 0xEF, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF,
-	0xAD, 0x01, 0x6C, 0xFC, 0x0C, 0x07, 0x7F, 0xF1, 0xDC, 0x2F, 0xAD,
-	0x30, 0x7D, 0xF1, 0x01, 0x07, 0x76, 0xFC, 0xA6, 0x01, 0x5E, 0xFF,
-	0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D,
-	0x00, 0x5D, 0xFE, 0x3E, 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B,
-	0x93, 0xF4, 0x62, 0x06, 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0x19, 0x00, 0x97, 0xFF, 0xE2, 0x00, 0x98, 0xFE,
-	0xCF, 0x01, 0x33, 0xFE, 0x7D, 0x00, 0xBB, 0x48, 0x1F, 0x07, 0x54,
-	0xFB, 0x4C, 0x03, 0xD3, 0xFD, 0x3F, 0x01, 0x73, 0xFF, 0x23, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3,
-	0xFC, 0x5D, 0x05, 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8,
-	0x2A, 0x02, 0x9A, 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C,
-	0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDA, 0x01, 0x35, 0xFC,
-	0x27, 0x07, 0x09, 0xF2, 0x85, 0x28, 0x63, 0x37, 0xE9, 0xF1, 0x63,
-	0x06, 0xF5, 0xFC, 0x53, 0x01, 0x89, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-	0x00, 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8,
-	0x05, 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06,
-	0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
-	0x00, 0xB9, 0xFF, 0x8A, 0x00, 0x4D, 0xFF, 0x7D, 0x00, 0x9C, 0x00,
-	0x7B, 0xFB, 0x31, 0x47, 0xD9, 0x0D, 0xC0, 0xF8, 0x8F, 0x04, 0x34,
-	0xFD, 0x87, 0x01, 0x56, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x29, 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C,
-	0xF9, 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00,
-	0x19, 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD5, 0x06, 0x4F, 0xF3,
-	0xE0, 0x20, 0x45, 0x3D, 0x4D, 0xF3, 0x4B, 0x05, 0xB3, 0xFD, 0xE0,
-	0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00,
-	0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
-	0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
-	0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xDA, 0xFF, 0x36,
-	0x00, 0xFA, 0xFF, 0x43, 0xFF, 0xBF, 0x02, 0x75, 0xF7, 0x42, 0x44,
-	0x20, 0x15, 0x55, 0xF6, 0xA9, 0x05, 0xB2, 0xFC, 0xBF, 0x01, 0x41,
-	0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF,
-	0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05, 0xEA,
-	0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA, 0x00,
-	0x8D, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD4,
-	0x01, 0x7C, 0xFC, 0x27, 0x06, 0x28, 0xF5, 0x31, 0x19, 0x21, 0x42,
-	0xB8, 0xF5, 0xC0, 0x03, 0xAA, 0xFE, 0x51, 0x00, 0x0B, 0x00, 0xEA,
-	0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF, 0xB7, 0x01,
-	0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3, 0x31, 0x7E,
-	0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF, 0x28, 0x00,
-	0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xE8, 0xFF, 0x96, 0x00, 0x31,
-	0xFE, 0x84, 0x04, 0x79, 0xF4, 0x07, 0x40, 0xBA, 0x1C, 0x3E, 0xF4,
-	0x82, 0x06, 0x58, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8, 0xFE, 0x93, 0x01,
-	0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08, 0xE1, 0xFA, 0x86,
-	0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA8, 0x01, 0xE9, 0xFC, 0x2D,
-	0x05, 0x6B, 0xF7, 0xB6, 0x11, 0xC8, 0x45, 0x30, 0xF9, 0xCD, 0x01,
-	0xD0, 0xFF, 0xAC, 0xFF, 0x5C, 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07,
-	0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11,
-	0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x10, 0x00, 0xA7, 0xFF, 0x19, 0x01, 0x53, 0xFD, 0xDB, 0x05, 0x88,
-	0xF2, 0xAD, 0x3A, 0x6D, 0x24, 0xA4, 0xF2, 0x08, 0x07, 0x32, 0xFC,
-	0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBF,
-	0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44, 0x00, 0x01, 0x01, 0xB6, 0xFA,
-	0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8, 0xC4, 0x04, 0x1B, 0xFD, 0x92,
-	0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
-	0x63, 0xFF, 0x67, 0x01, 0x7A, 0xFD, 0xFE, 0x03, 0xEE, 0xF9, 0xAA,
-	0x0A, 0x16, 0x48, 0xAC, 0xFD, 0x86, 0xFF, 0x17, 0x01, 0xFA, 0xFE,
-	0xB3, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
-	0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
-	0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x73, 0xFF,
-	0x7D, 0x01, 0xB3, 0xFC, 0xBB, 0x06, 0x9A, 0xF1, 0x60, 0x34, 0xF5,
-	0x2B, 0xB0, 0xF1, 0x28, 0x07, 0x47, 0xFC, 0xCA, 0x01, 0x4A, 0xFF,
-	0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17,
-	0x00, 0x10, 0xFF, 0x15, 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16,
-	0xF1, 0xF5, 0xD3, 0x05, 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x19, 0x01,
-	0x23, 0xFE, 0xB0, 0x02, 0x87, 0xFC, 0x41, 0x04, 0xF4, 0x48, 0x1C,
-	0x03, 0x06, 0xFD, 0x6E, 0x02, 0x45, 0xFE, 0x09, 0x01, 0x88, 0xFF,
-	0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C,
-	0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6,
-	0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07,
-	0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4F, 0xFF, 0xC1, 0x01, 0x52, 0xFC,
-	0x22, 0x07, 0x98, 0xF1, 0x5E, 0x2D, 0x13, 0x33, 0x87, 0xF1, 0xD8,
-	0x06, 0x9B, 0xFC, 0x8D, 0x01, 0x6B, 0xFF, 0x25, 0x00, 0xFD, 0xFF,
-	0x03, 0x00, 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8,
-	0x04, 0x10, 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06,
-	0x4E, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16,
-	0x00, 0xA3, 0xFF, 0xC3, 0x00, 0xD7, 0xFE, 0x58, 0x01, 0x0F, 0xFF,
-	0xA6, 0xFE, 0x5D, 0x48, 0x61, 0x09, 0x6E, 0xFA, 0xC0, 0x03, 0x99,
-	0xFD, 0x59, 0x01, 0x68, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x2E, 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7,
-	0xF7, 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00,
-	0x8E, 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
-	0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x16, 0x07, 0x67, 0xF2,
-	0xE5, 0x25, 0x87, 0x39, 0x47, 0xF2, 0x10, 0x06, 0x30, 0xFD, 0x2F,
-	0x01, 0x9C, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x00,
-	0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
-	0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-	0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC5, 0xFF, 0x6D,
-	0x00, 0x8B, 0xFF, 0x0D, 0x00, 0x63, 0x01, 0xF9, 0xF9, 0x55, 0x46,
-	0x51, 0x10, 0xE3, 0xF7, 0xF7, 0x04, 0x03, 0xFD, 0x9D, 0x01, 0x4E,
-	0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF,
-	0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57,
-	0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00,
-	0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3,
-	0x01, 0x4D, 0xFC, 0xA3, 0x06, 0xE4, 0xF3, 0x36, 0x1E, 0x16, 0x3F,
-	0x05, 0xF4, 0xCF, 0x04, 0x02, 0xFE, 0xB2, 0x00, 0xDB, 0xFF, 0xFC,
-	0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF, 0x8B, 0x01,
-	0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A, 0x2D, 0x9A,
-	0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF, 0x2F, 0x00,
-	0xFD, 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x1A, 0x00, 0x33, 0x00, 0xDF,
-	0xFE, 0x68, 0x03, 0x4E, 0xF6, 0xEE, 0x42, 0xBB, 0x17, 0x90, 0xF5,
-	0xFC, 0x05, 0x8E, 0xFC, 0xCD, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74, 0x02,
-	0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC, 0xA9,
-	0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC7, 0x01, 0x9D, 0xFC, 0xD8,
-	0x05, 0xE7, 0xF5, 0x91, 0x16, 0x89, 0x43, 0xCD, 0xF6, 0x1E, 0x03,
-	0x0B, 0xFF, 0x1A, 0x00, 0x26, 0x00, 0xE0, 0xFF, 0x08, 0x00, 0xFD,
-	0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01, 0x48, 0xFC, 0x28, 0x07,
-	0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97, 0xF1, 0xBE, 0x06, 0xB0,
-	0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00,
-	0x00, 0x00, 0xD0, 0xFF, 0xC7, 0x00, 0xDE, 0xFD, 0x08, 0x05, 0xB0,
-	0xF3, 0x4A, 0x3E, 0x64, 0x1F, 0xA0, 0xF3, 0xBB, 0x06, 0x45, 0xFC,
-	0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA9,
-	0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01, 0x7A, 0xFF, 0xC5, 0xFD,
-	0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8, 0x03, 0x7D, 0xFD, 0x66,
-	0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
-	0x52, 0xFF, 0x93, 0x01, 0x18, 0xFD, 0xC9, 0x04, 0x45, 0xF8, 0x36,
-	0x0F, 0xBB, 0x46, 0xA1, 0xFA, 0x0C, 0x01, 0x3E, 0x00, 0x70, 0xFF,
-	0x7A, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39,
-	0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24,
-	0x8F, 0x3A, 0x82, 0xF2, 0xE1, 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6,
-	0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x17, 0x00, 0x93, 0xFF,
-	0x3F, 0x01, 0x15, 0xFD, 0x36, 0x06, 0x19, 0xF2, 0x97, 0x38, 0x11,
-	0x27, 0x3B, 0xF2, 0x1F, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9,
-	0xFF, 0xD6, 0xFF, 0xC3, 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11,
-	0x77, 0xF7, 0x28, 0x05, 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6D, 0xFF, 0x4E, 0x01,
-	0xB3, 0xFD, 0x8D, 0x03, 0xD4, 0xFA, 0x5D, 0x08, 0x8D, 0x48, 0x74,
-	0xFF, 0xAE, 0xFE, 0x8D, 0x01, 0xBB, 0xFE, 0xD1, 0x00, 0x9E, 0xFF,
-	0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57,
-	0xFC, 0x85, 0x06, 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4,
-	0x8C, 0x04, 0x2C, 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04,
-	0x00, 0xFD, 0xFF, 0x27, 0x00, 0x65, 0xFF, 0x98, 0x01, 0x8A, 0xFC,
-	0xEC, 0x06, 0x7F, 0xF1, 0x04, 0x32, 0x7B, 0x2E, 0x8A, 0xF1, 0x1A,
-	0x07, 0x5D, 0xFC, 0xB8, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF,
-	0x06, 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8,
-	0x03, 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06,
-	0x7D, 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C,
-	0x00, 0x8D, 0xFF, 0xFC, 0x00, 0x61, 0xFE, 0x39, 0x02, 0x6B, 0xFD,
-	0x37, 0x02, 0xEB, 0x48, 0x31, 0x05, 0x21, 0xFC, 0xE4, 0x02, 0x08,
-	0xFE, 0x26, 0x01, 0x7C, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x32, 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A,
-	0xF6, 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF,
-	0xFE, 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x32,
-	0x00, 0x47, 0xFF, 0xD0, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xCA, 0xF1,
-	0xD1, 0x2A, 0x65, 0x35, 0xAE, 0xF1, 0xA0, 0x06, 0xC7, 0xFC, 0x70,
-	0x01, 0x7A, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00,
-	0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
-	0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA5,
-	0x00, 0x16, 0xFF, 0xE3, 0x00, 0xE4, 0xFF, 0xEB, 0xFC, 0xD2, 0x47,
-	0xB6, 0x0B, 0x89, 0xF9, 0x2F, 0x04, 0x62, 0xFD, 0x72, 0x01, 0x5E,
-	0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x56, 0xFF,
-	0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D, 0x26,
-	0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89, 0x00,
-	0xBA, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6,
-	0x01, 0x34, 0xFC, 0xF9, 0x06, 0xD9, 0xF2, 0x3F, 0x23, 0x90, 0x3B,
-	0xC4, 0xF2, 0xAE, 0x05, 0x72, 0xFD, 0x07, 0x01, 0xB0, 0xFF, 0x0C,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF, 0x51, 0x01,
-	0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60, 0x28, 0x0E,
-	0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF, 0x34, 0x00,
-	0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x4F, 0x00, 0xC7, 0xFF, 0xA0,
-	0xFF, 0x20, 0x02, 0x96, 0xF8, 0x4E, 0x45, 0xD7, 0x12, 0x0D, 0xF7,
-	0x58, 0x05, 0xD6, 0xFC, 0xB0, 0x01, 0x47, 0xFF, 0x30, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40, 0x01, 0xD0, 0xFD,
-	0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48, 0x62, 0x00, 0x3F,
-	0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98, 0xFF, 0x19, 0x00,
-	0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x63, 0xFC, 0x66,
-	0x06, 0x89, 0xF4, 0x8C, 0x1B, 0xC3, 0x40, 0xDD, 0xF4, 0x46, 0x04,
-	0x58, 0xFE, 0x80, 0x00, 0xF4, 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD,
-	0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06,
-	0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A,
-	0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00,
-	0xEF, 0xFF, 0xFF, 0xFF, 0x69, 0x00, 0x80, 0xFE, 0x04, 0x04, 0x48,
-	0xF5, 0x74, 0x41, 0x5D, 0x1A, 0xD7, 0xF4, 0x47, 0x06, 0x6F, 0xFC,
-	0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x93,
-	0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD, 0x01, 0xDC, 0xFD, 0x3C, 0x01,
-	0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB, 0x1F, 0x03, 0xEA, 0xFD, 0x34,
-	0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00,
-	0x44, 0xFF, 0xB8, 0x01, 0xC3, 0xFC, 0x81, 0x05, 0xB0, 0xF6, 0xFA,
-	0x13, 0xCC, 0x44, 0x02, 0xF8, 0x71, 0x02, 0x71, 0xFF, 0xE1, 0xFF,
-	0x42, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43,
-	0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
-	0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
-	0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x09, 0x00, 0xBA, 0xFF,
-	0xF4, 0x00, 0x91, 0xFD, 0x7E, 0x05, 0x05, 0xF3, 0x6E, 0x3C, 0x10,
-	0x22, 0x12, 0xF3, 0xE9, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35,
-	0xFF, 0xA9, 0x00, 0x4D, 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C,
-	0x18, 0xF9, 0x66, 0x04, 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5A, 0xFF, 0x7D, 0x01,
-	0x4B, 0xFD, 0x60, 0x04, 0x24, 0xF9, 0xC6, 0x0C, 0x86, 0x47, 0x30,
-	0xFC, 0x41, 0x00, 0xB0, 0x00, 0x32, 0xFF, 0x98, 0x00, 0xB4, 0xFF,
-	0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38,
-	0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3,
-	0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01,
-	0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x81, 0xFF, 0x62, 0x01, 0xDD, 0xFC,
-	0x83, 0x06, 0xC9, 0xF1, 0x66, 0x36, 0xAC, 0x29, 0xE7, 0xF1, 0x2A,
-	0x07, 0x3A, 0xFC, 0xD5, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x0B, 0x00, 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B,
-	0x02, 0xF0, 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05,
-	0xC1, 0xFC, 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x22, 0x00, 0x77, 0xFF, 0x32, 0x01, 0xED, 0xFD, 0x19, 0x03,
-	0xBB, 0xFB, 0x26, 0x06, 0xD7, 0x48, 0x58, 0x01, 0xCF, 0xFD, 0x04,
-	0x02, 0x7D, 0xFE, 0xEF, 0x00, 0x92, 0xFF, 0x1B, 0x00, 0xFE, 0xFF,
-	0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1,
-	0xF4, 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE,
-	0x66, 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2B,
-	0x00, 0x59, 0xFF, 0xB0, 0x01, 0x69, 0xFC, 0x0F, 0x07, 0x80, 0xF1,
-	0x96, 0x2F, 0xF2, 0x30, 0x7C, 0xF1, 0xFD, 0x06, 0x7A, 0xFC, 0xA3,
-	0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF4, 0xFF,
-	0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
-	0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
-	0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x98, 0xFF, 0xDE,
-	0x00, 0x9F, 0xFE, 0xC2, 0x01, 0x4B, 0xFE, 0x48, 0x00, 0xB3, 0x48,
-	0x5E, 0x07, 0x3B, 0xFB, 0x59, 0x03, 0xCD, 0xFD, 0x42, 0x01, 0x71,
-	0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF,
-	0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C,
-	0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00,
-	0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDB,
-	0x01, 0x35, 0xFC, 0x25, 0x07, 0x13, 0xF2, 0x3A, 0x28, 0xA0, 0x37,
-	0xF2, 0xF1, 0x5A, 0x06, 0xFB, 0xFC, 0x4F, 0x01, 0x8B, 0xFF, 0x1A,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF, 0x09, 0x01,
-	0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64, 0x23, 0xD2,
-	0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x11, 0x00, 0xBB, 0xFF, 0x87, 0x00, 0x54, 0xFF, 0x70,
-	0x00, 0xB3, 0x00, 0x4E, 0xFB, 0x1A, 0x47, 0x1F, 0x0E, 0xA8, 0xF8,
-	0x9B, 0x04, 0x2E, 0xFD, 0x8A, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65, 0xFD,
-	0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD, 0xD9,
-	0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD0,
-	0x06, 0x5E, 0xF3, 0x94, 0x20, 0x7B, 0x3D, 0x60, 0xF3, 0x3E, 0x05,
-	0xBB, 0xFD, 0xDB, 0x00, 0xC6, 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE,
-	0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01, 0xC4, 0xFC, 0xA4, 0x06,
-	0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6, 0xF1, 0x2A, 0x07, 0x40,
-	0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00,
-	0xDB, 0xFF, 0x33, 0x00, 0x01, 0x00, 0x38, 0xFF, 0xD3, 0x02, 0x53,
-	0xF7, 0x1F, 0x44, 0x69, 0x15, 0x3F, 0xF6, 0xB2, 0x05, 0xAD, 0xFC,
-	0xC1, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20,
-	0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE, 0xDE, 0x02, 0x2E, 0xFC,
-	0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E, 0xFD, 0x3F, 0x02, 0x5D,
-	0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x3B, 0xFF, 0xD3, 0x01, 0x7F, 0xFC, 0x1F, 0x06, 0x3C, 0xF5, 0xE6,
-	0x18, 0x4D, 0x42, 0xD5, 0xF5, 0xAF, 0x03, 0xB4, 0xFE, 0x4B, 0x00,
-	0x0E, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53,
-	0xFF, 0xBA, 0x01, 0x5B, 0xFC, 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E,
-	0x26, 0x32, 0x80, 0xF1, 0xEA, 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66,
-	0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8, 0xFF, 0xE6, 0xFF,
-	0x9C, 0x00, 0x27, 0xFE, 0x94, 0x04, 0x61, 0xF4, 0xD7, 0x3F, 0x06,
-	0x1D, 0x2B, 0xF4, 0x89, 0x06, 0x56, 0xFC, 0xE0, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF,
-	0xFE, 0x86, 0x01, 0xBA, 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08,
-	0xC7, 0xFA, 0x93, 0x03, 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA6, 0x01,
-	0xEE, 0xFC, 0x23, 0x05, 0x83, 0xF7, 0x6E, 0x11, 0xE5, 0x45, 0x57,
-	0xF9, 0xB8, 0x01, 0xDC, 0xFF, 0xA5, 0xFF, 0x5F, 0x00, 0xCA, 0xFF,
-	0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32,
-	0xFC, 0x1E, 0x07, 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2,
-	0x32, 0x06, 0x18, 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x11, 0x00, 0xA4, 0xFF, 0x1D, 0x01, 0x4C, 0xFD,
-	0xE6, 0x05, 0x7B, 0xF2, 0x71, 0x3A, 0xB8, 0x24, 0x97, 0xF2, 0x0B,
-	0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x0F, 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17,
-	0x01, 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04,
-	0x15, 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x28, 0x00, 0x64, 0xFF, 0x65, 0x01, 0x81, 0xFD, 0xF2, 0x03,
-	0x08, 0xFA, 0x68, 0x0A, 0x25, 0x48, 0xDE, 0xFD, 0x6E, 0xFF, 0x24,
-	0x01, 0xF3, 0xFE, 0xB6, 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8,
-	0xF3, 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD,
-	0xC4, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x23,
-	0x00, 0x71, 0xFF, 0x81, 0x01, 0xAE, 0xFC, 0xC1, 0x06, 0x95, 0xF1,
-	0x1E, 0x34, 0x3E, 0x2C, 0xAB, 0xF1, 0x27, 0x07, 0x49, 0xFC, 0xC8,
-	0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF,
-	0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
-	0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
-	0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83,
-	0xFF, 0x16, 0x01, 0x2A, 0xFE, 0xA3, 0x02, 0xA1, 0xFC, 0x06, 0x04,
-	0xF5, 0x48, 0x56, 0x03, 0xED, 0xFC, 0x7B, 0x02, 0x3E, 0xFE, 0x0C,
-	0x01, 0x86, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-	0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17, 0x02,
-	0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B, 0x00,
-	0xE4, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3,
-	0x01, 0x4F, 0xFC, 0x24, 0x07, 0x9C, 0xF1, 0x17, 0x2D, 0x57, 0x33,
-	0x8A, 0xF1, 0xD3, 0x06, 0x9F, 0xFC, 0x8A, 0x01, 0x6D, 0xFF, 0x25,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF, 0xB4, 0x00,
-	0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B, 0x1E, 0xDB,
-	0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC0, 0x00, 0xDE, 0xFE, 0x4B,
-	0x01, 0x27, 0xFF, 0x73, 0xFE, 0x4F, 0x48, 0xA2, 0x09, 0x54, 0xFA,
-	0xCC, 0x03, 0x93, 0xFD, 0x5C, 0x01, 0x67, 0xFF, 0x27, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C, 0x01, 0x05, 0xFD,
-	0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46, 0x0D, 0xFA, 0x58,
-	0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4, 0xFF, 0x0E, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x14,
-	0x07, 0x73, 0xF2, 0x99, 0x25, 0xC2, 0x39, 0x54, 0xF2, 0x05, 0x06,
-	0x37, 0xFD, 0x2B, 0x01, 0x9E, 0xFF, 0x13, 0x00, 0xFF, 0xFF, 0xFF,
-	0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06,
-	0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31,
-	0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-	0xC6, 0xFF, 0x69, 0x00, 0x91, 0xFF, 0x00, 0x00, 0x78, 0x01, 0xD0,
-	0xF9, 0x39, 0x46, 0x98, 0x10, 0xCB, 0xF7, 0x02, 0x05, 0xFE, 0xFC,
-	0x9F, 0x01, 0x4D, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
-	0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D, 0xFD, 0xB9, 0x03, 0x7B, 0xFA,
-	0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE, 0x03, 0xFF, 0x5F, 0x01, 0xD4,
-	0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE2, 0x01, 0x4F, 0xFC, 0x9C, 0x06, 0xF5, 0xF3, 0xEA,
-	0x1D, 0x47, 0x3F, 0x1B, 0xF4, 0xC1, 0x04, 0x0B, 0xFE, 0xAC, 0x00,
-	0xDE, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
-	0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
-	0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
-	0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE6, 0xFF, 0x17, 0x00,
-	0x39, 0x00, 0xD4, 0xFE, 0x7A, 0x03, 0x2F, 0xF6, 0xC7, 0x42, 0x06,
-	0x18, 0x7B, 0xF5, 0x05, 0x06, 0x8A, 0xFC, 0xCF, 0x01, 0x3C, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49,
-	0xFE, 0x67, 0x02, 0x13, 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04,
-	0x7A, 0xFC, 0xB6, 0x02, 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01,
-	0xA1, 0xFC, 0xCF, 0x05, 0xFC, 0xF5, 0x47, 0x16, 0xB0, 0x43, 0xEE,
-	0xF6, 0x0C, 0x03, 0x16, 0xFF, 0x14, 0x00, 0x29, 0x00, 0xDF, 0xFF,
-	0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46,
-	0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1,
-	0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE,
-	0xFF, 0x02, 0x00, 0x01, 0x00, 0xCE, 0xFF, 0xCC, 0x00, 0xD5, 0xFD,
-	0x16, 0x05, 0x9B, 0xF3, 0x18, 0x3E, 0xB1, 0x1F, 0x8F, 0xF3, 0xC0,
-	0x06, 0x43, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x15, 0x00, 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92,
-	0xFF, 0x94, 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04,
-	0x77, 0xFD, 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x91, 0x01, 0x1E, 0xFD, 0xBE, 0x04,
-	0x5E, 0xF8, 0xF0, 0x0E, 0xD3, 0x46, 0xCB, 0xFA, 0xF6, 0x00, 0x4B,
-	0x00, 0x69, 0xFF, 0x7D, 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA,
-	0xF2, 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD,
-	0x17, 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18,
-	0x00, 0x91, 0xFF, 0x43, 0x01, 0x0E, 0xFD, 0x40, 0x06, 0x0F, 0xF2,
-	0x5B, 0x38, 0x5C, 0x27, 0x30, 0xF2, 0x21, 0x07, 0x33, 0xFC, 0xDE,
-	0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCC, 0xFF,
-	0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
-	0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
-	0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6E,
-	0xFF, 0x4B, 0x01, 0xB9, 0xFD, 0x80, 0x03, 0xEE, 0xFA, 0x1D, 0x08,
-	0x98, 0x48, 0xA8, 0xFF, 0x95, 0xFE, 0x9A, 0x01, 0xB4, 0xFE, 0xD4,
-	0x00, 0x9C, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F,
-	0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF,
-	0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9B,
-	0x01, 0x86, 0xFC, 0xF1, 0x06, 0x7E, 0xF1, 0xC0, 0x31, 0xC2, 0x2E,
-	0x87, 0xF1, 0x17, 0x07, 0x5F, 0xFC, 0xB6, 0x01, 0x55, 0xFF, 0x2D,
-	0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00, 0x54, 0x00,
-	0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56, 0x19, 0x1E,
-	0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF, 0x35, 0x00,
-	0xFE, 0xFF, 0x1C, 0x00, 0x8E, 0xFF, 0xF9, 0x00, 0x68, 0xFE, 0x2C,
-	0x02, 0x84, 0xFD, 0xFF, 0x01, 0xE6, 0x48, 0x6E, 0x05, 0x07, 0xFC,
-	0xF1, 0x02, 0x01, 0xFE, 0x29, 0x01, 0x7B, 0xFF, 0x21, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4, 0xFC,
-	0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7, 0xB6,
-	0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A, 0x00,
-	0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3E, 0xFC, 0x2B,
-	0x07, 0xD0, 0xF1, 0x89, 0x2A, 0xA6, 0x35, 0xB4, 0xF1, 0x99, 0x06,
-	0xCD, 0xFC, 0x6D, 0x01, 0x7C, 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01,
-	0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00, 0xAE, 0xFD, 0x52, 0x05,
-	0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47, 0xF3, 0xD8, 0x06, 0x3C,
-	0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
-	0xB0, 0xFF, 0xA2, 0x00, 0x1D, 0xFF, 0xD6, 0x00, 0xFC, 0xFF, 0xBC,
-	0xFC, 0xC0, 0x47, 0xFA, 0x0B, 0x70, 0xF9, 0x3C, 0x04, 0x5C, 0xFD,
-	0x75, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
-	0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD, 0x89, 0x04, 0xCD, 0xF8,
-	0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91, 0x00, 0x83, 0x00, 0x4A,
-	0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF5, 0x06, 0xE7, 0xF2, 0xF2,
-	0x22, 0xC7, 0x3B, 0xD4, 0xF2, 0xA2, 0x05, 0x7A, 0xFD, 0x02, 0x01,
-	0xB2, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88,
-	0xFF, 0x55, 0x01, 0xF2, 0xFC, 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37,
-	0xAA, 0x28, 0x05, 0xF2, 0x27, 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41,
-	0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD2, 0xFF, 0x4C, 0x00,
-	0xCD, 0xFF, 0x94, 0xFF, 0x34, 0x02, 0x70, 0xF8, 0x2E, 0x45, 0x20,
-	0x13, 0xF6, 0xF6, 0x62, 0x05, 0xD1, 0xFC, 0xB2, 0x01, 0x46, 0xFF,
-	0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D,
-	0x01, 0xD6, 0xFD, 0x46, 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48,
-	0x98, 0x00, 0x26, 0xFE, 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96,
-	0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01,
-	0x66, 0xFC, 0x5E, 0x06, 0x9C, 0xF4, 0x40, 0x1B, 0xEF, 0x40, 0xF7,
-	0xF4, 0x35, 0x04, 0x62, 0xFE, 0x7A, 0x00, 0xF7, 0xFF, 0xF2, 0xFF,
-	0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75,
-	0xFC, 0x03, 0x07, 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1,
-	0x0A, 0x07, 0x6E, 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD,
-	0xFF, 0x05, 0x00, 0xF0, 0xFF, 0xFC, 0xFF, 0x6E, 0x00, 0x76, 0xFE,
-	0x15, 0x04, 0x2C, 0xF5, 0x49, 0x41, 0xA9, 0x1A, 0xC3, 0xF4, 0x4F,
-	0x06, 0x6C, 0xFC, 0xD9, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-	0x1A, 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5,
-	0xFD, 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03,
-	0xE4, 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB6, 0x01, 0xC8, 0xFC, 0x77, 0x05,
-	0xC7, 0xF6, 0xB1, 0x13, 0xED, 0x44, 0x26, 0xF8, 0x5D, 0x02, 0x7D,
-	0xFF, 0xDA, 0xFF, 0x46, 0x00, 0xD4, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-	0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3,
-	0xF1, 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC,
-	0x5C, 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
-	0x00, 0xB7, 0xFF, 0xF9, 0x00, 0x89, 0xFD, 0x8A, 0x05, 0xF4, 0xF2,
-	0x37, 0x3C, 0x5B, 0x22, 0x03, 0xF3, 0xED, 0x06, 0x37, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
-	0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
-	0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
-	0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B,
-	0xFF, 0x7A, 0x01, 0x50, 0xFD, 0x54, 0x04, 0x3D, 0xF9, 0x82, 0x0C,
-	0x9A, 0x47, 0x5E, 0xFC, 0x2A, 0x00, 0xBD, 0x00, 0x2B, 0xFF, 0x9B,
-	0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21, 0xC0,
-	0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD, 0xFF,
-	0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x80, 0xFF, 0x66,
-	0x01, 0xD8, 0xFC, 0x8B, 0x06, 0xC1, 0xF1, 0x27, 0x36, 0xF6, 0x29,
-	0xDF, 0xF1, 0x2A, 0x07, 0x3B, 0xFC, 0xD4, 0x01, 0x44, 0xFF, 0x32,
-	0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00, 0xEA, 0xFF,
-	0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68, 0x14, 0x8E,
-	0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF, 0x32, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x79, 0xFF, 0x2F, 0x01, 0xF4,
-	0xFD, 0x0C, 0x03, 0xD4, 0xFB, 0xE9, 0x05, 0xDE, 0x48, 0x8F, 0x01,
-	0xB6, 0xFD, 0x11, 0x02, 0x76, 0xFE, 0xF2, 0x00, 0x91, 0xFF, 0x1B,
-	0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, 0x01, 0x73, 0xFC,
-	0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41, 0x71, 0xF5, 0xEB,
-	0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED, 0xFF, 0x06, 0x00,
-	0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB2, 0x01, 0x65, 0xFC, 0x12,
-	0x07, 0x82, 0xF1, 0x50, 0x2F, 0x38, 0x31, 0x7C, 0xF1, 0xF9, 0x06,
-	0x7E, 0xFC, 0xA1, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04,
-	0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04,
-	0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F,
-	0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
-	0x9A, 0xFF, 0xDB, 0x00, 0xA6, 0xFE, 0xB4, 0x01, 0x64, 0xFE, 0x12,
-	0x00, 0xAA, 0x48, 0x9E, 0x07, 0x21, 0xFB, 0x66, 0x03, 0xC6, 0xFD,
-	0x45, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-	0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD, 0xFC, 0x48, 0x05, 0x30, 0xF7,
-	0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8, 0x01, 0x02, 0xB2, 0xFF, 0xBD,
-	0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x24, 0x07, 0x1C, 0xF2, 0xF0,
-	0x27, 0xDF, 0x37, 0xFB, 0xF1, 0x51, 0x06, 0x01, 0xFD, 0x4B, 0x01,
-	0x8D, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
-	0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
-	0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0x84, 0x00,
-	0x5B, 0xFF, 0x64, 0x00, 0xC9, 0x00, 0x22, 0xFB, 0x02, 0x47, 0x64,
-	0x0E, 0x8F, 0xF8, 0xA7, 0x04, 0x29, 0xFD, 0x8C, 0x01, 0x54, 0xFF,
-	0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E,
-	0x01, 0x6B, 0xFD, 0x1D, 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47,
-	0x33, 0xFD, 0xC1, 0xFF, 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD,
-	0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-	0x40, 0xFC, 0xCB, 0x06, 0x6E, 0xF3, 0x49, 0x20, 0xB0, 0x3D, 0x73,
-	0xF3, 0x31, 0x05, 0xC4, 0xFD, 0xD6, 0x00, 0xC8, 0xFF, 0x03, 0x00,
-	0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF,
-	0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1,
-	0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD,
-	0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x2F, 0x00, 0x07, 0x00, 0x2C, 0xFF,
-	0xE6, 0x02, 0x31, 0xF7, 0xFA, 0x43, 0xB3, 0x15, 0x29, 0xF6, 0xBC,
-	0x05, 0xA9, 0xFC, 0xC2, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1,
-	0x02, 0x47, 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD,
-	0x4D, 0x02, 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFE,
-	0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01, 0x83, 0xFC, 0x16, 0x06,
-	0x51, 0xF5, 0x9B, 0x18, 0x75, 0x42, 0xF3, 0xF5, 0x9D, 0x03, 0xBF,
-	0xFE, 0x45, 0x00, 0x11, 0x00, 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
-	0x2E, 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E,
-	0xF1, 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC,
-	0x94, 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF9,
-	0xFF, 0xE3, 0xFF, 0xA1, 0x00, 0x1E, 0xFE, 0xA3, 0x04, 0x49, 0xF4,
-	0xA8, 0x3F, 0x52, 0x1D, 0x19, 0xF4, 0x90, 0x06, 0x53, 0xFC, 0xE1,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
-	0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
-	0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
-	0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C,
-	0xFF, 0xA3, 0x01, 0xF3, 0xFC, 0x18, 0x05, 0x9B, 0xF7, 0x27, 0x11,
-	0x02, 0x46, 0x7F, 0xF9, 0xA3, 0x01, 0xE8, 0xFF, 0x9F, 0xFF, 0x63,
-	0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
-	0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2,
-	0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF,
-	0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA2, 0xFF, 0x22,
-	0x01, 0x45, 0xFD, 0xF1, 0x05, 0x6D, 0xF2, 0x38, 0x3A, 0x03, 0x25,
-	0x8B, 0xF2, 0x0E, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x3A, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00, 0x7A, 0xFF,
-	0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0, 0x0F, 0x20,
-	0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF, 0x2E, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x62, 0x01, 0x87,
-	0xFD, 0xE5, 0x03, 0x21, 0xFA, 0x25, 0x0A, 0x33, 0x48, 0x0F, 0xFE,
-	0x57, 0xFF, 0x31, 0x01, 0xEC, 0xFE, 0xB9, 0x00, 0xA7, 0xFF, 0x15,
-	0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48, 0xFC,
-	0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3, 0xF3,
-	0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
-	0xFE, 0xFF, 0x23, 0x00, 0x70, 0xFF, 0x84, 0x01, 0xA9, 0xFC, 0xC7,
-	0x06, 0x91, 0xF1, 0xDC, 0x33, 0x87, 0x2C, 0xA5, 0xF1, 0x26, 0x07,
-	0x4B, 0xFC, 0xC6, 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
-	0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00, 0xFA, 0xFE, 0x3A, 0x03,
-	0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6, 0xF5, 0xE6, 0x05, 0x97,
-	0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00,
-	0x1E, 0x00, 0x84, 0xFF, 0x13, 0x01, 0x31, 0xFE, 0x95, 0x02, 0xBA,
-	0xFC, 0xCB, 0x03, 0xF7, 0x48, 0x91, 0x03, 0xD3, 0xFC, 0x88, 0x02,
-	0x38, 0xFE, 0x10, 0x01, 0x85, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
-	0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC, 0xEF, 0x05, 0xB0, 0xF5,
-	0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D, 0x03, 0xEF, 0xFE, 0x2A,
-	0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4D, 0xFF, 0xC4, 0x01, 0x4D, 0xFC, 0x25, 0x07, 0xA1, 0xF1, 0xCE,
-	0x2C, 0x99, 0x33, 0x8E, 0xF1, 0xCD, 0x06, 0xA4, 0xFC, 0x87, 0x01,
-	0x6E, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD7,
-	0xFF, 0xBA, 0x00, 0xF4, 0xFD, 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E,
-	0xA7, 0x1E, 0xCA, 0xF3, 0xAC, 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36,
-	0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBD, 0x00,
-	0xE5, 0xFE, 0x3E, 0x01, 0x3F, 0xFF, 0x41, 0xFE, 0x41, 0x48, 0xE4,
-	0x09, 0x3B, 0xFA, 0xD9, 0x03, 0x8D, 0xFD, 0x5F, 0x01, 0x66, 0xFF,
-	0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99,
-	0x01, 0x0B, 0xFD, 0xE6, 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46,
-	0x37, 0xFA, 0x42, 0x01, 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3,
-	0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01,
-	0x31, 0xFC, 0x11, 0x07, 0x7F, 0xF2, 0x4E, 0x25, 0xFD, 0x39, 0x60,
-	0xF2, 0xFB, 0x05, 0x3E, 0xFD, 0x26, 0x01, 0xA0, 0xFF, 0x12, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25,
-	0xFD, 0x1E, 0x06, 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2,
-	0x1A, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x66, 0x00, 0x98, 0xFF, 0xF4, 0xFF,
-	0x8E, 0x01, 0xA7, 0xF9, 0x1D, 0x46, 0xDF, 0x10, 0xB3, 0xF7, 0x0D,
-	0x05, 0xF8, 0xFC, 0xA1, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD,
-	0x03, 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE,
-	0x6C, 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x51, 0xFC, 0x96, 0x06,
-	0x07, 0xF4, 0x9E, 0x1D, 0x77, 0x3F, 0x32, 0xF4, 0xB2, 0x04, 0x15,
-	0xFE, 0xA7, 0x00, 0xE0, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
-	0x26, 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84,
-	0xF1, 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC,
-	0xBE, 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE7,
-	0xFF, 0x14, 0x00, 0x3F, 0x00, 0xC9, 0xFE, 0x8C, 0x03, 0x11, 0xF6,
-	0x9E, 0x42, 0x50, 0x18, 0x66, 0xF5, 0x0D, 0x06, 0x86, 0xFC, 0xD0,
-	0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
-	0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
-	0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
-	0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-	0xFF, 0xC4, 0x01, 0xA5, 0xFC, 0xC5, 0x05, 0x13, 0xF6, 0xFD, 0x15,
-	0xD4, 0x43, 0x0F, 0xF7, 0xF9, 0x02, 0x21, 0xFF, 0x0D, 0x00, 0x2C,
-	0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49, 0xFF,
-	0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B, 0xC3,
-	0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76, 0xFF,
-	0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00, 0xCB, 0xFF, 0xD1,
-	0x00, 0xCC, 0xFD, 0x24, 0x05, 0x87, 0xF3, 0xE4, 0x3D, 0xFD, 0x1F,
-	0x7F, 0xF3, 0xC6, 0x06, 0x41, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00, 0x05, 0xFF,
-	0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E, 0x0B, 0xC8,
-	0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF, 0x28, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x8F, 0x01, 0x23,
-	0xFD, 0xB2, 0x04, 0x76, 0xF8, 0xAA, 0x0E, 0xED, 0x46, 0xF7, 0xFA,
-	0xDF, 0x00, 0x57, 0x00, 0x62, 0xFF, 0x80, 0x00, 0xBD, 0xFF, 0x10,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x33, 0xFC,
-	0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B, 0x9E, 0xF2, 0xCB,
-	0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x18, 0x00, 0x8F, 0xFF, 0x47, 0x01, 0x08, 0xFD, 0x49,
-	0x06, 0x05, 0xF2, 0x1D, 0x38, 0xA6, 0x27, 0x26, 0xF2, 0x23, 0x07,
-	0x33, 0xFC, 0xDD, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
-	0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01,
-	0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2,
-	0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x24, 0x00, 0x6F, 0xFF, 0x48, 0x01, 0xC0, 0xFD, 0x73, 0x03, 0x07,
-	0xFB, 0xDD, 0x07, 0xA1, 0x48, 0xDD, 0xFF, 0x7D, 0xFE, 0xA7, 0x01,
-	0xAD, 0xFE, 0xD8, 0x00, 0x9B, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C, 0xFC, 0x78, 0x06, 0x5A, 0xF4,
-	0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4, 0x6D, 0x04, 0x3F, 0xFE, 0x8E,
-	0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-	0x62, 0xFF, 0x9E, 0x01, 0x82, 0xFC, 0xF5, 0x06, 0x7D, 0xF1, 0x7B,
-	0x31, 0x09, 0x2F, 0x84, 0xF1, 0x15, 0x07, 0x62, 0xFC, 0xB4, 0x01,
-	0x56, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
-	0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
-	0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x8F, 0xFF, 0xF5, 0x00,
-	0x6F, 0xFE, 0x1E, 0x02, 0x9D, 0xFD, 0xC7, 0x01, 0xE1, 0x48, 0xAB,
-	0x05, 0xEE, 0xFB, 0xFE, 0x02, 0xFB, 0xFD, 0x2C, 0x01, 0x7A, 0xFF,
-	0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC,
-	0x01, 0xB8, 0xFC, 0x9A, 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44,
-	0xA9, 0xF7, 0xA2, 0x02, 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8,
-	0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD3, 0x01,
-	0x3C, 0xFC, 0x2A, 0x07, 0xD8, 0xF1, 0x3F, 0x2A, 0xE6, 0x35, 0xBB,
-	0xF1, 0x92, 0x06, 0xD2, 0xFC, 0x69, 0x01, 0x7E, 0xFF, 0x1F, 0x00,
-	0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6,
-	0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3,
-	0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x13, 0x00, 0xB1, 0xFF, 0x9F, 0x00, 0x24, 0xFF, 0xC9, 0x00,
-	0x13, 0x00, 0x8D, 0xFC, 0xAE, 0x47, 0x3E, 0x0C, 0x56, 0xF9, 0x48,
-	0x04, 0x56, 0xFD, 0x78, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E,
-	0x04, 0xE6, 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00,
-	0x90, 0x00, 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xF1, 0x06,
-	0xF5, 0xF2, 0xA7, 0x22, 0xFF, 0x3B, 0xE4, 0xF2, 0x96, 0x05, 0x81,
-	0xFD, 0xFD, 0x00, 0xB5, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF,
-	0x1C, 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC,
-	0xF1, 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC,
-	0xD8, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3,
-	0xFF, 0x49, 0x00, 0xD4, 0xFF, 0x88, 0xFF, 0x49, 0x02, 0x4B, 0xF8,
-	0x0D, 0x45, 0x68, 0x13, 0xDF, 0xF6, 0x6C, 0x05, 0xCC, 0xFC, 0xB4,
-	0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
-	0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
-	0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
-	0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-	0xFF, 0xDA, 0x01, 0x69, 0xFC, 0x57, 0x06, 0xAF, 0xF4, 0xF5, 0x1A,
-	0x1D, 0x41, 0x11, 0xF5, 0x25, 0x04, 0x6C, 0xFE, 0x74, 0x00, 0xF9,
-	0xFF, 0xF1, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF,
-	0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44,
-	0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF,
-	0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF1, 0xFF, 0xF9, 0xFF, 0x74,
-	0x00, 0x6C, 0xFE, 0x25, 0x04, 0x11, 0xF5, 0x1D, 0x41, 0xF5, 0x1A,
-	0xAF, 0xF4, 0x57, 0x06, 0x69, 0xFC, 0xDA, 0x01, 0x38, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00, 0x8E, 0xFE,
-	0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1, 0x06, 0x7B,
-	0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF, 0x23, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB4, 0x01, 0xCC,
-	0xFC, 0x6C, 0x05, 0xDF, 0xF6, 0x68, 0x13, 0x0D, 0x45, 0x4B, 0xF8,
-	0x49, 0x02, 0x88, 0xFF, 0xD4, 0xFF, 0x49, 0x00, 0xD3, 0xFF, 0x0B,
-	0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37, 0xFC,
-	0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1, 0x6F,
-	0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE, 0xFF,
-	0x01, 0x00, 0x0B, 0x00, 0xB5, 0xFF, 0xFD, 0x00, 0x81, 0xFD, 0x96,
-	0x05, 0xE4, 0xF2, 0xFF, 0x3B, 0xA7, 0x22, 0xF5, 0xF2, 0xF1, 0x06,
-	0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
-	0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF, 0x90, 0x00, 0x7A, 0x00,
-	0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6, 0xF8, 0x7E, 0x04, 0x3C,
-	0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x2A, 0x00, 0x5C, 0xFF, 0x78, 0x01, 0x56, 0xFD, 0x48, 0x04, 0x56,
-	0xF9, 0x3E, 0x0C, 0xAE, 0x47, 0x8D, 0xFC, 0x13, 0x00, 0xC9, 0x00,
-	0x24, 0xFF, 0x9F, 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC, 0xDD, 0x06, 0x37, 0xF3,
-	0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F, 0x05, 0xA6, 0xFD, 0xE8,
-	0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00,
-	0x7E, 0xFF, 0x69, 0x01, 0xD2, 0xFC, 0x92, 0x06, 0xBB, 0xF1, 0xE6,
-	0x35, 0x3F, 0x2A, 0xD8, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
-	0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD8, 0xFF, 0x3A,
-	0x00, 0xF1, 0xFF, 0x54, 0xFF, 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44,
-	0xB1, 0x14, 0x77, 0xF6, 0x9A, 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42,
-	0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
-	0x2C, 0x01, 0xFB, 0xFD, 0xFE, 0x02, 0xEE, 0xFB, 0xAB, 0x05, 0xE1,
-	0x48, 0xC7, 0x01, 0x9D, 0xFD, 0x1E, 0x02, 0x6F, 0xFE, 0xF5, 0x00,
-	0x8F, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6,
-	0x01, 0x77, 0xFC, 0x33, 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41,
-	0x8D, 0xF5, 0xDA, 0x03, 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC,
-	0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x56, 0xFF, 0xB4, 0x01,
-	0x62, 0xFC, 0x15, 0x07, 0x84, 0xF1, 0x09, 0x2F, 0x7B, 0x31, 0x7D,
-	0xF1, 0xF5, 0x06, 0x82, 0xFC, 0x9E, 0x01, 0x62, 0xFF, 0x28, 0x00,
-	0xFD, 0xFF, 0x04, 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F,
-	0xFE, 0x6D, 0x04, 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4,
-	0x78, 0x06, 0x5C, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0x18, 0x00, 0x9B, 0xFF, 0xD8, 0x00, 0xAD, 0xFE, 0xA7, 0x01,
-	0x7D, 0xFE, 0xDD, 0xFF, 0xA1, 0x48, 0xDD, 0x07, 0x07, 0xFB, 0x73,
-	0x03, 0xC0, 0xFD, 0x48, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D,
-	0x05, 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01,
-	0xBE, 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDD, 0x01, 0x33, 0xFC, 0x23, 0x07,
-	0x26, 0xF2, 0xA6, 0x27, 0x1D, 0x38, 0x05, 0xF2, 0x49, 0x06, 0x08,
-	0xFD, 0x47, 0x01, 0x8F, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x0E, 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E,
-	0xF2, 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC,
-	0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBD,
-	0xFF, 0x80, 0x00, 0x62, 0xFF, 0x57, 0x00, 0xDF, 0x00, 0xF7, 0xFA,
-	0xED, 0x46, 0xAA, 0x0E, 0x76, 0xF8, 0xB2, 0x04, 0x23, 0xFD, 0x8F,
-	0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
-	0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
-	0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
-	0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE5, 0x01, 0x41, 0xFC, 0xC6, 0x06, 0x7F, 0xF3, 0xFD, 0x1F,
-	0xE4, 0x3D, 0x87, 0xF3, 0x24, 0x05, 0xCC, 0xFD, 0xD1, 0x00, 0xCB,
-	0xFF, 0x02, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76, 0xFF,
-	0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34, 0x89,
-	0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49, 0xFF,
-	0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2C, 0x00, 0x0D,
-	0x00, 0x21, 0xFF, 0xF9, 0x02, 0x0F, 0xF7, 0xD4, 0x43, 0xFD, 0x15,
-	0x13, 0xF6, 0xC5, 0x05, 0xA5, 0xFC, 0xC4, 0x01, 0x40, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0x1E, 0x01,
-	0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2, 0x48, 0xC6,
-	0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01, 0x8A, 0xFF,
-	0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD0, 0x01, 0x86,
-	0xFC, 0x0D, 0x06, 0x66, 0xF5, 0x50, 0x18, 0x9E, 0x42, 0x11, 0xF6,
-	0x8C, 0x03, 0xC9, 0xFE, 0x3F, 0x00, 0x14, 0x00, 0xE7, 0xFF, 0x07,
-	0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE, 0x01, 0x56, 0xFC,
-	0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32, 0x84, 0xF1, 0xE0,
-	0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF,
-	0x03, 0x00, 0xFA, 0xFF, 0xE0, 0xFF, 0xA7, 0x00, 0x15, 0xFE, 0xB2,
-	0x04, 0x32, 0xF4, 0x77, 0x3F, 0x9E, 0x1D, 0x07, 0xF4, 0x96, 0x06,
-	0x51, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
-	0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE,
-	0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3,
-	0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x2F, 0x00, 0x4C, 0xFF, 0xA1, 0x01, 0xF8, 0xFC, 0x0D, 0x05, 0xB3,
-	0xF7, 0xDF, 0x10, 0x1D, 0x46, 0xA7, 0xF9, 0x8E, 0x01, 0xF4, 0xFF,
-	0x98, 0xFF, 0x66, 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
-	0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31, 0xFC, 0x1A, 0x07, 0x56, 0xF2,
-	0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2, 0x1E, 0x06, 0x25, 0xFD, 0x35,
-	0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x12, 0x00,
-	0xA0, 0xFF, 0x26, 0x01, 0x3E, 0xFD, 0xFB, 0x05, 0x60, 0xF2, 0xFD,
-	0x39, 0x4E, 0x25, 0x7F, 0xF2, 0x11, 0x07, 0x31, 0xFC, 0xE3, 0x01,
-	0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
-	0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
-	0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
-	0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF,
-	0x5F, 0x01, 0x8D, 0xFD, 0xD9, 0x03, 0x3B, 0xFA, 0xE4, 0x09, 0x41,
-	0x48, 0x41, 0xFE, 0x3F, 0xFF, 0x3E, 0x01, 0xE5, 0xFE, 0xBD, 0x00,
-	0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-	0x01, 0x4A, 0xFC, 0xAC, 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E,
-	0xE4, 0xF3, 0xE5, 0x04, 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE,
-	0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6E, 0xFF, 0x87, 0x01,
-	0xA4, 0xFC, 0xCD, 0x06, 0x8E, 0xF1, 0x99, 0x33, 0xCE, 0x2C, 0xA1,
-	0xF1, 0x25, 0x07, 0x4D, 0xFC, 0xC4, 0x01, 0x4D, 0xFF, 0x2F, 0x00,
-	0xFD, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF,
-	0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5,
-	0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0x1E, 0x00, 0x85, 0xFF, 0x10, 0x01, 0x38, 0xFE, 0x88, 0x02,
-	0xD3, 0xFC, 0x91, 0x03, 0xF7, 0x48, 0xCB, 0x03, 0xBA, 0xFC, 0x95,
-	0x02, 0x31, 0xFE, 0x13, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00, 0x00,
-	0xFE, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6,
-	0x05, 0xC6, 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03,
-	0xFA, 0xFE, 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0xFD,
-	0xFF, 0x30, 0x00, 0x4C, 0xFF, 0xC6, 0x01, 0x4B, 0xFC, 0x26, 0x07,
-	0xA5, 0xF1, 0x87, 0x2C, 0xDC, 0x33, 0x91, 0xF1, 0xC7, 0x06, 0xA9,
-	0xFC, 0x84, 0x01, 0x70, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x03, 0x00,
-	0xFF, 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF,
-	0xF3, 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC,
-	0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA7,
-	0xFF, 0xB9, 0x00, 0xEC, 0xFE, 0x31, 0x01, 0x57, 0xFF, 0x0F, 0xFE,
-	0x33, 0x48, 0x25, 0x0A, 0x21, 0xFA, 0xE5, 0x03, 0x87, 0xFD, 0x62,
-	0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
-	0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
-	0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
-	0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A,
-	0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0E, 0x07, 0x8B, 0xF2, 0x03, 0x25,
-	0x38, 0x3A, 0x6D, 0xF2, 0xF1, 0x05, 0x45, 0xFD, 0x22, 0x01, 0xA2,
-	0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF,
-	0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0,
-	0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF,
-	0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x63, 0x00, 0x9F,
-	0xFF, 0xE8, 0xFF, 0xA3, 0x01, 0x7F, 0xF9, 0x02, 0x46, 0x27, 0x11,
-	0x9B, 0xF7, 0x18, 0x05, 0xF3, 0xFC, 0xA3, 0x01, 0x4C, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF, 0x52, 0x01,
-	0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C, 0x48, 0x26,
-	0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00, 0xA0, 0xFF,
-	0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE1, 0x01, 0x53,
-	0xFC, 0x90, 0x06, 0x19, 0xF4, 0x52, 0x1D, 0xA8, 0x3F, 0x49, 0xF4,
-	0xA3, 0x04, 0x1E, 0xFE, 0xA1, 0x00, 0xE3, 0xFF, 0xF9, 0xFF, 0x04,
-	0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90, 0xFC,
-	0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1, 0x1D,
-	0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-	0x07, 0x00, 0xE8, 0xFF, 0x11, 0x00, 0x45, 0x00, 0xBF, 0xFE, 0x9D,
-	0x03, 0xF3, 0xF5, 0x75, 0x42, 0x9B, 0x18, 0x51, 0xF5, 0x16, 0x06,
-	0x83, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
-	0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE, 0x4D, 0x02, 0x45, 0xFD,
-	0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47, 0xFC, 0xD1, 0x02, 0x12,
-	0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x33, 0x00, 0x40, 0xFF, 0xC2, 0x01, 0xA9, 0xFC, 0xBC, 0x05, 0x29,
-	0xF6, 0xB3, 0x15, 0xFA, 0x43, 0x31, 0xF7, 0xE6, 0x02, 0x2C, 0xFF,
-	0x07, 0x00, 0x2F, 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
-	0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC, 0x2A, 0x07, 0xBF, 0xF1,
-	0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB, 0x06, 0xBF, 0xFC, 0x75,
-	0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00,
-	0xC8, 0xFF, 0xD6, 0x00, 0xC4, 0xFD, 0x31, 0x05, 0x73, 0xF3, 0xB0,
-	0x3D, 0x49, 0x20, 0x6E, 0xF3, 0xCB, 0x06, 0x40, 0xFC, 0xE6, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA,
-	0x00, 0x0C, 0xFF, 0xF7, 0x00, 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47,
-	0x51, 0x0B, 0xAF, 0xF9, 0x1D, 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60,
-	0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF,
-	0x8C, 0x01, 0x29, 0xFD, 0xA7, 0x04, 0x8F, 0xF8, 0x64, 0x0E, 0x02,
-	0x47, 0x22, 0xFB, 0xC9, 0x00, 0x64, 0x00, 0x5B, 0xFF, 0x84, 0x00,
-	0xBC, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5,
-	0x01, 0x33, 0xFC, 0xFF, 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B,
-	0xAD, 0xF2, 0xBF, 0x05, 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8D, 0xFF, 0x4B, 0x01,
-	0x01, 0xFD, 0x51, 0x06, 0xFB, 0xF1, 0xDF, 0x37, 0xF0, 0x27, 0x1C,
-	0xF2, 0x24, 0x07, 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00,
-	0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2,
-	0xFF, 0x01, 0x02, 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7,
-	0x48, 0x05, 0xDD, 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x45, 0x01, 0xC6, 0xFD,
-	0x66, 0x03, 0x21, 0xFB, 0x9E, 0x07, 0xAA, 0x48, 0x12, 0x00, 0x64,
-	0xFE, 0xB4, 0x01, 0xA6, 0xFE, 0xDB, 0x00, 0x9A, 0xFF, 0x19, 0x00,
-	0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70,
-	0x06, 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04,
-	0x49, 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFD,
-	0xFF, 0x29, 0x00, 0x61, 0xFF, 0xA1, 0x01, 0x7E, 0xFC, 0xF9, 0x06,
-	0x7C, 0xF1, 0x38, 0x31, 0x50, 0x2F, 0x82, 0xF1, 0x12, 0x07, 0x65,
-	0xFC, 0xB2, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00,
-	0xED, 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71,
-	0xF5, 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC,
-	0xD7, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91,
-	0xFF, 0xF2, 0x00, 0x76, 0xFE, 0x11, 0x02, 0xB6, 0xFD, 0x8F, 0x01,
-	0xDE, 0x48, 0xE9, 0x05, 0xD4, 0xFB, 0x0C, 0x03, 0xF4, 0xFD, 0x2F,
-	0x01, 0x79, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
-	0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
-	0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
-	0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44,
-	0xFF, 0xD4, 0x01, 0x3B, 0xFC, 0x2A, 0x07, 0xDF, 0xF1, 0xF6, 0x29,
-	0x27, 0x36, 0xC1, 0xF1, 0x8B, 0x06, 0xD8, 0xFC, 0x66, 0x01, 0x80,
-	0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xBD, 0xFF,
-	0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C, 0x9E,
-	0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x9B, 0x00, 0x2B,
-	0xFF, 0xBD, 0x00, 0x2A, 0x00, 0x5E, 0xFC, 0x9A, 0x47, 0x82, 0x0C,
-	0x3D, 0xF9, 0x54, 0x04, 0x50, 0xFD, 0x7A, 0x01, 0x5B, 0xFF, 0x2A,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x81, 0x01,
-	0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69, 0x47, 0xEB,
-	0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00, 0xB6, 0xFF,
-	0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37,
-	0xFC, 0xED, 0x06, 0x03, 0xF3, 0x5B, 0x22, 0x37, 0x3C, 0xF4, 0xF2,
-	0x8A, 0x05, 0x89, 0xFD, 0xF9, 0x00, 0xB7, 0xFF, 0x0A, 0x00, 0x01,
-	0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C, 0x01, 0xE6, 0xFC,
-	0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29, 0xF3, 0xF1, 0x29,
-	0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x0B, 0x00, 0xD4, 0xFF, 0x46, 0x00, 0xDA, 0xFF, 0x7D, 0xFF, 0x5D,
-	0x02, 0x26, 0xF8, 0xED, 0x44, 0xB1, 0x13, 0xC7, 0xF6, 0x77, 0x05,
-	0xC8, 0xFC, 0xB6, 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03,
-	0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0,
-	0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-	0x35, 0x00, 0x38, 0xFF, 0xD9, 0x01, 0x6C, 0xFC, 0x4F, 0x06, 0xC3,
-	0xF4, 0xA9, 0x1A, 0x49, 0x41, 0x2C, 0xF5, 0x15, 0x04, 0x76, 0xFE,
-	0x6E, 0x00, 0xFC, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B,
-	0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E, 0xFC, 0x0A, 0x07, 0x7E, 0xF1,
-	0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1, 0x03, 0x07, 0x75, 0xFC, 0xA7,
-	0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF2, 0xFF,
-	0xF7, 0xFF, 0x7A, 0x00, 0x62, 0xFE, 0x35, 0x04, 0xF7, 0xF4, 0xEF,
-	0x40, 0x40, 0x1B, 0x9C, 0xF4, 0x5E, 0x06, 0x66, 0xFC, 0xDB, 0x01,
-	0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
-	0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
-	0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
-	0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF,
-	0xB2, 0x01, 0xD1, 0xFC, 0x62, 0x05, 0xF6, 0xF6, 0x20, 0x13, 0x2E,
-	0x45, 0x70, 0xF8, 0x34, 0x02, 0x94, 0xFF, 0xCD, 0xFF, 0x4C, 0x00,
-	0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA,
-	0x01, 0x36, 0xFC, 0x27, 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37,
-	0xE4, 0xF1, 0x67, 0x06, 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B,
-	0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B, 0x00, 0xB2, 0xFF, 0x02, 0x01,
-	0x7A, 0xFD, 0xA2, 0x05, 0xD4, 0xF2, 0xC7, 0x3B, 0xF2, 0x22, 0xE7,
-	0xF2, 0xF5, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83,
-	0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8,
-	0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x75, 0x01, 0x5C, 0xFD,
-	0x3C, 0x04, 0x70, 0xF9, 0xFA, 0x0B, 0xC0, 0x47, 0xBC, 0xFC, 0xFC,
-	0xFF, 0xD6, 0x00, 0x1D, 0xFF, 0xA2, 0x00, 0xB0, 0xFF, 0x13, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8,
-	0x06, 0x47, 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05,
-	0xAE, 0xFD, 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0xFE,
-	0xFF, 0x1F, 0x00, 0x7C, 0xFF, 0x6D, 0x01, 0xCD, 0xFC, 0x99, 0x06,
-	0xB4, 0xF1, 0xA6, 0x35, 0x89, 0x2A, 0xD0, 0xF1, 0x2B, 0x07, 0x3E,
-	0xFC, 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
-	0xD9, 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86,
-	0xF7, 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC,
-	0xBE, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
-	0x00, 0x7B, 0xFF, 0x29, 0x01, 0x01, 0xFE, 0xF1, 0x02, 0x07, 0xFC,
-	0x6E, 0x05, 0xE6, 0x48, 0xFF, 0x01, 0x84, 0xFD, 0x2C, 0x02, 0x68,
-	0xFE, 0xF9, 0x00, 0x8E, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
-	0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
-	0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x55,
-	0xFF, 0xB6, 0x01, 0x5F, 0xFC, 0x17, 0x07, 0x87, 0xF1, 0xC2, 0x2E,
-	0xC0, 0x31, 0x7E, 0xF1, 0xF1, 0x06, 0x86, 0xFC, 0x9B, 0x01, 0x63,
-	0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF,
-	0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94,
-	0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9C, 0xFF, 0xD4, 0x00, 0xB4,
-	0xFE, 0x9A, 0x01, 0x95, 0xFE, 0xA8, 0xFF, 0x98, 0x48, 0x1D, 0x08,
-	0xEE, 0xFA, 0x80, 0x03, 0xB9, 0xFD, 0x4B, 0x01, 0x6E, 0xFF, 0x25,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA9, 0x01,
-	0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8, 0x45, 0x1C,
-	0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00, 0xCC, 0xFF,
-	0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDE, 0x01, 0x33,
-	0xFC, 0x21, 0x07, 0x30, 0xF2, 0x5C, 0x27, 0x5B, 0x38, 0x0F, 0xF2,
-	0x40, 0x06, 0x0E, 0xFD, 0x43, 0x01, 0x91, 0xFF, 0x18, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57, 0xFD,
-	0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2, 0x06,
-	0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x10, 0x00, 0xBE, 0xFF, 0x7D, 0x00, 0x69, 0xFF, 0x4B, 0x00, 0xF6,
-	0x00, 0xCB, 0xFA, 0xD3, 0x46, 0xF0, 0x0E, 0x5E, 0xF8, 0xBE, 0x04,
-	0x1E, 0xFD, 0x91, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01, 0x77, 0xFD, 0x04, 0x04,
-	0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94, 0xFD, 0x92, 0xFF, 0x10,
-	0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x43, 0xFC, 0xC0, 0x06, 0x8F,
-	0xF3, 0xB1, 0x1F, 0x18, 0x3E, 0x9B, 0xF3, 0x16, 0x05, 0xD5, 0xFD,
-	0xCC, 0x00, 0xCE, 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22,
-	0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC, 0xB8, 0x06, 0x9C, 0xF1,
-	0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29, 0x07, 0x46, 0xFC, 0xCA,
-	0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF,
-	0x29, 0x00, 0x14, 0x00, 0x16, 0xFF, 0x0C, 0x03, 0xEE, 0xF6, 0xB0,
-	0x43, 0x47, 0x16, 0xFC, 0xF5, 0xCF, 0x05, 0xA1, 0xFC, 0xC6, 0x01,
-	0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81,
-	0xFF, 0x1B, 0x01, 0x20, 0xFE, 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04,
-	0xF4, 0x48, 0xFF, 0x02, 0x13, 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07,
-	0x01, 0x88, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
-	0xCF, 0x01, 0x8A, 0xFC, 0x05, 0x06, 0x7B, 0xF5, 0x06, 0x18, 0xC7,
-	0x42, 0x2F, 0xF6, 0x7A, 0x03, 0xD4, 0xFE, 0x39, 0x00, 0x17, 0x00,
-	0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0,
-	0x01, 0x53, 0xFC, 0x21, 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32,
-	0x86, 0xF1, 0xDB, 0x06, 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDE, 0xFF, 0xAC, 0x00,
-	0x0B, 0xFE, 0xC1, 0x04, 0x1B, 0xF4, 0x47, 0x3F, 0xEA, 0x1D, 0xF5,
-	0xF3, 0x9C, 0x06, 0x4F, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x16, 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F,
-	0x01, 0x03, 0xFF, 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA,
-	0xB9, 0x03, 0x9D, 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4D, 0xFF, 0x9F, 0x01, 0xFE, 0xFC,
-	0x02, 0x05, 0xCB, 0xF7, 0x98, 0x10, 0x39, 0x46, 0xD0, 0xF9, 0x78,
-	0x01, 0x00, 0x00, 0x91, 0xFF, 0x69, 0x00, 0xC6, 0xFF, 0x0E, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17,
-	0x07, 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06,
-	0x2C, 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF,
-	0xFF, 0x13, 0x00, 0x9E, 0xFF, 0x2B, 0x01, 0x37, 0xFD, 0x05, 0x06,
-	0x54, 0xF2, 0xC2, 0x39, 0x99, 0x25, 0x73, 0xF2, 0x14, 0x07, 0x31,
-	0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-	0xC4, 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D,
-	0xFA, 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD,
-	0x9C, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
-	0x00, 0x67, 0xFF, 0x5C, 0x01, 0x93, 0xFD, 0xCC, 0x03, 0x54, 0xFA,
-	0xA2, 0x09, 0x4F, 0x48, 0x73, 0xFE, 0x27, 0xFF, 0x4B, 0x01, 0xDE,
-	0xFE, 0xC0, 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
-	0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
-	0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6D,
-	0xFF, 0x8A, 0x01, 0x9F, 0xFC, 0xD3, 0x06, 0x8A, 0xF1, 0x57, 0x33,
-	0x17, 0x2D, 0x9C, 0xF1, 0x24, 0x07, 0x4F, 0xFC, 0xC3, 0x01, 0x4E,
-	0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE4, 0xFF, 0x1B, 0x00,
-	0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43, 0x96,
-	0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x86, 0xFF, 0x0C, 0x01, 0x3E,
-	0xFE, 0x7B, 0x02, 0xED, 0xFC, 0x56, 0x03, 0xF5, 0x48, 0x06, 0x04,
-	0xA1, 0xFC, 0xA3, 0x02, 0x2A, 0xFE, 0x16, 0x01, 0x83, 0xFF, 0x1F,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC8, 0x01,
-	0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77, 0x43, 0xBD,
-	0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00, 0xE1, 0xFF,
-	0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC8, 0x01, 0x49,
-	0xFC, 0x27, 0x07, 0xAB, 0xF1, 0x3E, 0x2C, 0x1E, 0x34, 0x95, 0xF1,
-	0xC1, 0x06, 0xAE, 0xFC, 0x81, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE,
-	0xFF, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4, 0x00, 0xE2, 0xFD,
-	0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F, 0xA8, 0xF3, 0xB8,
-	0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x15, 0x00, 0xA8, 0xFF, 0xB6, 0x00, 0xF3, 0xFE, 0x24, 0x01, 0x6E,
-	0xFF, 0xDE, 0xFD, 0x25, 0x48, 0x68, 0x0A, 0x08, 0xFA, 0xF2, 0x03,
-	0x81, 0xFD, 0x65, 0x01, 0x64, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04,
-	0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38,
-	0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0B, 0x07, 0x97,
-	0xF2, 0xB8, 0x24, 0x71, 0x3A, 0x7B, 0xF2, 0xE6, 0x05, 0x4C, 0xFD,
-	0x1D, 0x01, 0xA4, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16,
-	0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18, 0xFD, 0x32, 0x06, 0x1F, 0xF2,
-	0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2, 0x1E, 0x07, 0x32, 0xFC, 0xDF,
-	0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
-	0x5F, 0x00, 0xA5, 0xFF, 0xDC, 0xFF, 0xB8, 0x01, 0x57, 0xF9, 0xE5,
-	0x45, 0x6E, 0x11, 0x83, 0xF7, 0x23, 0x05, 0xEE, 0xFC, 0xA6, 0x01,
-	0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C,
-	0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
-	0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
-	0x00, 0x9E, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE0, 0x01, 0x56, 0xFC, 0x89, 0x06, 0x2B, 0xF4, 0x06, 0x1D, 0xD7,
-	0x3F, 0x61, 0xF4, 0x94, 0x04, 0x27, 0xFE, 0x9C, 0x00, 0xE6, 0xFF,
-	0xF8, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97,
-	0x01, 0x8C, 0xFC, 0xEA, 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E,
-	0x8B, 0xF1, 0x1B, 0x07, 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D,
-	0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9, 0xFF, 0x0E, 0x00, 0x4B, 0x00,
-	0xB4, 0xFE, 0xAF, 0x03, 0xD5, 0xF5, 0x4D, 0x42, 0xE6, 0x18, 0x3C,
-	0xF5, 0x1F, 0x06, 0x7F, 0xFC, 0xD3, 0x01, 0x3B, 0xFF, 0x35, 0x00,
-	0xFE, 0xFF, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F,
-	0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC,
-	0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xC1, 0x01, 0xAD, 0xFC,
-	0xB2, 0x05, 0x3F, 0xF6, 0x69, 0x15, 0x1F, 0x44, 0x53, 0xF7, 0xD3,
-	0x02, 0x38, 0xFF, 0x01, 0x00, 0x33, 0x00, 0xDB, 0xFF, 0x09, 0x00,
-	0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A,
-	0x07, 0xC6, 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06,
-	0xC4, 0xFC, 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02,
-	0x00, 0x04, 0x00, 0xC6, 0xFF, 0xDB, 0x00, 0xBB, 0xFD, 0x3E, 0x05,
-	0x60, 0xF3, 0x7B, 0x3D, 0x94, 0x20, 0x5E, 0xF3, 0xD0, 0x06, 0x3E,
-	0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00,
-	0xAE, 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03,
-	0xFD, 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD,
-	0x71, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C,
-	0x00, 0x55, 0xFF, 0x8A, 0x01, 0x2E, 0xFD, 0x9B, 0x04, 0xA8, 0xF8,
-	0x1F, 0x0E, 0x1A, 0x47, 0x4E, 0xFB, 0xB3, 0x00, 0x70, 0x00, 0x54,
-	0xFF, 0x87, 0x00, 0xBB, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
-	0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
-	0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8B,
-	0xFF, 0x4F, 0x01, 0xFB, 0xFC, 0x5A, 0x06, 0xF2, 0xF1, 0xA0, 0x37,
-	0x3A, 0x28, 0x13, 0xF2, 0x25, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40,
-	0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00,
-	0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2,
-	0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF,
-	0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x42,
-	0x01, 0xCD, 0xFD, 0x59, 0x03, 0x3B, 0xFB, 0x5E, 0x07, 0xB3, 0x48,
-	0x48, 0x00, 0x4B, 0xFE, 0xC2, 0x01, 0x9F, 0xFE, 0xDE, 0x00, 0x98,
-	0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDD, 0x01,
-	0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB, 0x40, 0xD0,
-	0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF, 0xF4, 0xFF,
-	0x05, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA3, 0x01, 0x7A,
-	0xFC, 0xFD, 0x06, 0x7C, 0xF1, 0xF2, 0x30, 0x96, 0x2F, 0x80, 0xF1,
-	0x0F, 0x07, 0x69, 0xFC, 0xB0, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD,
-	0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85, 0xFE,
-	0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4, 0x43,
-	0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-	0x1B, 0x00, 0x92, 0xFF, 0xEF, 0x00, 0x7D, 0xFE, 0x04, 0x02, 0xCF,
-	0xFD, 0x58, 0x01, 0xD7, 0x48, 0x26, 0x06, 0xBB, 0xFB, 0x19, 0x03,
-	0xED, 0xFD, 0x32, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01, 0xC1, 0xFC, 0x86, 0x05,
-	0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0, 0xF7, 0x7B, 0x02, 0x6B,
-	0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-	0x33, 0x00, 0x43, 0xFF, 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE7,
-	0xF1, 0xAC, 0x29, 0x66, 0x36, 0xC9, 0xF1, 0x83, 0x06, 0xDD, 0xFC,
-	0x62, 0x01, 0x81, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x08,
-	0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD, 0x78, 0x05, 0x0E, 0xF3,
-	0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6, 0x06, 0x38, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB4, 0xFF,
-	0x98, 0x00, 0x32, 0xFF, 0xB0, 0x00, 0x41, 0x00, 0x30, 0xFC, 0x86,
-	0x47, 0xC6, 0x0C, 0x24, 0xF9, 0x60, 0x04, 0x4B, 0xFD, 0x7D, 0x01,
-	0x5A, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x5A,
-	0xFF, 0x7E, 0x01, 0x48, 0xFD, 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C,
-	0x7C, 0x47, 0x19, 0xFC, 0x4D, 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96,
-	0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE6, 0x01, 0x38, 0xFC, 0xE9, 0x06, 0x12, 0xF3, 0x10, 0x22, 0x6E,
-	0x3C, 0x05, 0xF3, 0x7E, 0x05, 0x91, 0xFD, 0xF4, 0x00, 0xBA, 0xFF,
-	0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60,
-	0x01, 0xE0, 0xFC, 0x7F, 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29,
-	0xEB, 0xF1, 0x2A, 0x07, 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33,
-	0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5, 0xFF, 0x42, 0x00, 0xE1, 0xFF,
-	0x71, 0xFF, 0x71, 0x02, 0x02, 0xF8, 0xCC, 0x44, 0xFA, 0x13, 0xB0,
-	0xF6, 0x81, 0x05, 0xC3, 0xFC, 0xB8, 0x01, 0x44, 0xFF, 0x31, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA,
-	0xFD, 0x1F, 0x03, 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01,
-	0xDC, 0xFD, 0xFD, 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B,
-	0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x6F, 0xFC,
-	0x47, 0x06, 0xD7, 0xF4, 0x5D, 0x1A, 0x74, 0x41, 0x48, 0xF5, 0x04,
-	0x04, 0x80, 0xFE, 0x69, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
-	0xFD, 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D,
-	0x07, 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06,
-	0x78, 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05,
-	0x00, 0xF3, 0xFF, 0xF4, 0xFF, 0x80, 0x00, 0x58, 0xFE, 0x46, 0x04,
-	0xDD, 0xF4, 0xC3, 0x40, 0x8C, 0x1B, 0x89, 0xF4, 0x66, 0x06, 0x63,
-	0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
-	0x98, 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62,
-	0x00, 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD,
-	0x40, 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-	0x00, 0x47, 0xFF, 0xB0, 0x01, 0xD6, 0xFC, 0x58, 0x05, 0x0D, 0xF7,
-	0xD7, 0x12, 0x4E, 0x45, 0x96, 0xF8, 0x20, 0x02, 0xA0, 0xFF, 0xC7,
-	0xFF, 0x4F, 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
-	0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
-	0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 0xB0,
-	0xFF, 0x07, 0x01, 0x72, 0xFD, 0xAE, 0x05, 0xC4, 0xF2, 0x90, 0x3B,
-	0x3F, 0x23, 0xD9, 0xF2, 0xF9, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89, 0x00,
-	0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47, 0xFC,
-	0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56, 0xFF,
-	0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5E, 0xFF, 0x72,
-	0x01, 0x62, 0xFD, 0x2F, 0x04, 0x89, 0xF9, 0xB6, 0x0B, 0xD2, 0x47,
-	0xEB, 0xFC, 0xE4, 0xFF, 0xE3, 0x00, 0x16, 0xFF, 0xA5, 0x00, 0xAF,
-	0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-	0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61, 0x3D, 0x56,
-	0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF, 0x05, 0x00,
-	0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x7A, 0xFF, 0x70, 0x01, 0xC7,
-	0xFC, 0xA0, 0x06, 0xAE, 0xF1, 0x65, 0x35, 0xD1, 0x2A, 0xCA, 0xF1,
-	0x2A, 0x07, 0x40, 0xFC, 0xD0, 0x01, 0x47, 0xFF, 0x32, 0x00, 0xFD,
-	0xFF, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x3D, 0xFF,
-	0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15, 0x4A, 0xF6, 0xAD,
-	0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF, 0x26, 0x01, 0x08, 0xFE, 0xE4,
-	0x02, 0x21, 0xFC, 0x31, 0x05, 0xEB, 0x48, 0x37, 0x02, 0x6B, 0xFD,
-	0x39, 0x02, 0x61, 0xFE, 0xFC, 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFE,
-	0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06,
-	0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF,
-	0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFD, 0xFF,
-	0x2D, 0x00, 0x54, 0xFF, 0xB8, 0x01, 0x5D, 0xFC, 0x1A, 0x07, 0x8A,
-	0xF1, 0x7B, 0x2E, 0x04, 0x32, 0x7F, 0xF1, 0xEC, 0x06, 0x8A, 0xFC,
-	0x98, 0x01, 0x65, 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8,
-	0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C, 0xFE, 0x8C, 0x04, 0x6D, 0xF4,
-	0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4, 0x85, 0x06, 0x57, 0xFC, 0xE0,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9E, 0xFF,
-	0xD1, 0x00, 0xBB, 0xFE, 0x8D, 0x01, 0xAE, 0xFE, 0x74, 0xFF, 0x8D,
-	0x48, 0x5D, 0x08, 0xD4, 0xFA, 0x8D, 0x03, 0xB3, 0xFD, 0x4E, 0x01,
-	0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
-	0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
-	0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
-	0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-	0xDF, 0x01, 0x32, 0xFC, 0x1F, 0x07, 0x3B, 0xF2, 0x11, 0x27, 0x97,
-	0x38, 0x19, 0xF2, 0x36, 0x06, 0x15, 0xFD, 0x3F, 0x01, 0x93, 0xFF,
-	0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B,
-	0x01, 0x50, 0xFD, 0xE1, 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24,
-	0x9D, 0xF2, 0x09, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x7A, 0x00, 0x70, 0xFF,
-	0x3E, 0x00, 0x0C, 0x01, 0xA1, 0xFA, 0xBB, 0x46, 0x36, 0x0F, 0x45,
-	0xF8, 0xC9, 0x04, 0x18, 0xFD, 0x93, 0x01, 0x52, 0xFF, 0x2D, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D,
-	0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD,
-	0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x45, 0xFC,
-	0xBB, 0x06, 0xA0, 0xF3, 0x64, 0x1F, 0x4A, 0x3E, 0xB0, 0xF3, 0x08,
-	0x05, 0xDE, 0xFD, 0xC7, 0x00, 0xD0, 0xFF, 0x00, 0x00, 0x02, 0x00,
-	0xFE, 0xFF, 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE,
-	0x06, 0x97, 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07,
-	0x48, 0xFC, 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
-	0x00, 0xE0, 0xFF, 0x26, 0x00, 0x1A, 0x00, 0x0B, 0xFF, 0x1E, 0x03,
-	0xCD, 0xF6, 0x89, 0x43, 0x91, 0x16, 0xE7, 0xF5, 0xD8, 0x05, 0x9D,
-	0xFC, 0xC7, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x1F, 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94,
-	0xFC, 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02,
-	0x42, 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
-	0x00, 0x3C, 0xFF, 0xCD, 0x01, 0x8E, 0xFC, 0xFC, 0x05, 0x90, 0xF5,
-	0xBB, 0x17, 0xEE, 0x42, 0x4E, 0xF6, 0x68, 0x03, 0xDF, 0xFE, 0x33,
-	0x00, 0x1A, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
-	0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
-	0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFC, 0xFF, 0xDB,
-	0xFF, 0xB2, 0x00, 0x02, 0xFE, 0xCF, 0x04, 0x05, 0xF4, 0x16, 0x3F,
-	0x36, 0x1E, 0xE4, 0xF3, 0xA3, 0x06, 0x4D, 0xFC, 0xE3, 0x01, 0x36,
-	0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00,
-	0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81,
-	0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF,
-	0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9D,
-	0x01, 0x03, 0xFD, 0xF7, 0x04, 0xE3, 0xF7, 0x51, 0x10, 0x55, 0x46,
-	0xF9, 0xF9, 0x63, 0x01, 0x0D, 0x00, 0x8B, 0xFF, 0x6D, 0x00, 0xC5,
-	0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01,
-	0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5, 0x39, 0x4D,
-	0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF, 0x13, 0x00,
-	0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x9C, 0xFF, 0x2F, 0x01, 0x30,
-	0xFD, 0x10, 0x06, 0x47, 0xF2, 0x87, 0x39, 0xE5, 0x25, 0x67, 0xF2,
-	0x16, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06, 0x00,
-	0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7, 0xFC,
-	0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x59, 0x01, 0x99, 0xFD, 0xC0,
-	0x03, 0x6E, 0xFA, 0x61, 0x09, 0x5D, 0x48, 0xA6, 0xFE, 0x0F, 0xFF,
-	0x58, 0x01, 0xD7, 0xFE, 0xC3, 0x00, 0xA3, 0xFF, 0x16, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4E, 0xFC, 0xA0, 0x06,
-	0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10, 0xF4, 0xC8, 0x04, 0x07,
-	0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
-	0x25, 0x00, 0x6B, 0xFF, 0x8D, 0x01, 0x9B, 0xFC, 0xD8, 0x06, 0x87,
-	0xF1, 0x13, 0x33, 0x5E, 0x2D, 0x98, 0xF1, 0x22, 0x07, 0x52, 0xFC,
-	0xC1, 0x01, 0x4F, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE5,
-	0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE, 0x71, 0x03, 0x3F, 0xF6,
-	0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00, 0x06, 0x8C, 0xFC, 0xCE,
-	0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF,
-	0x09, 0x01, 0x45, 0xFE, 0x6E, 0x02, 0x06, 0xFD, 0x1C, 0x03, 0xF4,
-	0x48, 0x41, 0x04, 0x87, 0xFC, 0xB0, 0x02, 0x23, 0xFE, 0x19, 0x01,
-	0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F,
-	0xFF, 0xC6, 0x01, 0x9F, 0xFC, 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16,
-	0x9E, 0x43, 0xDD, 0xF6, 0x15, 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28,
-	0x00, 0xDF, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-	0xCA, 0x01, 0x47, 0xFC, 0x28, 0x07, 0xB0, 0xF1, 0xF5, 0x2B, 0x60,
-	0x34, 0x9A, 0xF1, 0xBB, 0x06, 0xB3, 0xFC, 0x7D, 0x01, 0x73, 0xFF,
-	0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9,
-	0x00, 0xDA, 0xFD, 0x0F, 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F,
-	0x97, 0xF3, 0xBD, 0x06, 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x15, 0x00, 0xAA, 0xFF, 0xB3, 0x00, 0xFA, 0xFE,
-	0x17, 0x01, 0x86, 0xFF, 0xAC, 0xFD, 0x16, 0x48, 0xAA, 0x0A, 0xEE,
-	0xF9, 0xFE, 0x03, 0x7A, 0xFD, 0x67, 0x01, 0x63, 0xFF, 0x28, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B,
-	0xFD, 0xC4, 0x04, 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA,
-	0x01, 0x01, 0x44, 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC,
-	0x08, 0x07, 0xA4, 0xF2, 0x6D, 0x24, 0xAD, 0x3A, 0x88, 0xF2, 0xDB,
-	0x05, 0x53, 0xFD, 0x19, 0x01, 0xA7, 0xFF, 0x10, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B,
-	0x06, 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07,
-	0x33, 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D,
-	0x00, 0xCB, 0xFF, 0x5C, 0x00, 0xAC, 0xFF, 0xD0, 0xFF, 0xCD, 0x01,
-	0x30, 0xF9, 0xC8, 0x45, 0xB6, 0x11, 0x6B, 0xF7, 0x2D, 0x05, 0xE9,
-	0xFC, 0xA8, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x25, 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1,
-	0xFA, 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01,
-	0xB8, 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xE0, 0x01, 0x58, 0xFC, 0x82, 0x06, 0x3E, 0xF4,
-	0xBA, 0x1C, 0x07, 0x40, 0x79, 0xF4, 0x84, 0x04, 0x31, 0xFE, 0x96,
-	0x00, 0xE8, 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-	0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
-	0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
-	0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEA, 0xFF, 0x0B,
-	0x00, 0x51, 0x00, 0xAA, 0xFE, 0xC0, 0x03, 0xB8, 0xF5, 0x21, 0x42,
-	0x31, 0x19, 0x28, 0xF5, 0x27, 0x06, 0x7C, 0xFC, 0xD4, 0x01, 0x3A,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA, 0x00,
-	0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48, 0x50,
-	0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C, 0xFF,
-	0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xBF,
-	0x01, 0xB2, 0xFC, 0xA9, 0x05, 0x55, 0xF6, 0x20, 0x15, 0x42, 0x44,
-	0x75, 0xF7, 0xBF, 0x02, 0x43, 0xFF, 0xFA, 0xFF, 0x36, 0x00, 0xDA,
-	0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01,
-	0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86, 0x35, 0xB1,
-	0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF, 0x20, 0x00,
-	0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE0, 0x00, 0xB3,
-	0xFD, 0x4B, 0x05, 0x4D, 0xF3, 0x45, 0x3D, 0xE0, 0x20, 0x4F, 0xF3,
-	0xD5, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19, 0xFF, 0xDD, 0x00,
-	0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B, 0x7C, 0xF9, 0x35,
-	0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x2C, 0x00, 0x56, 0xFF, 0x87, 0x01, 0x34, 0xFD, 0x8F,
-	0x04, 0xC0, 0xF8, 0xD9, 0x0D, 0x31, 0x47, 0x7B, 0xFB, 0x9C, 0x00,
-	0x7D, 0x00, 0x4D, 0xFF, 0x8A, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06,
-	0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76,
-	0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF,
-	0x1A, 0x00, 0x89, 0xFF, 0x53, 0x01, 0xF5, 0xFC, 0x63, 0x06, 0xE9,
-	0xF1, 0x63, 0x37, 0x85, 0x28, 0x09, 0xF2, 0x27, 0x07, 0x35, 0xFC,
-	0xDA, 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD1,
-	0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A, 0xFF, 0x2A, 0x02, 0x83, 0xF8,
-	0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7, 0x5D, 0x05, 0xD3, 0xFC, 0xB1,
-	0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
-	0x73, 0xFF, 0x3F, 0x01, 0xD3, 0xFD, 0x4C, 0x03, 0x54, 0xFB, 0x1F,
-	0x07, 0xBB, 0x48, 0x7D, 0x00, 0x33, 0xFE, 0xCF, 0x01, 0x98, 0xFE,
-	0xE2, 0x00, 0x97, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-	0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
-	0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
-	0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5E, 0xFF,
-	0xA6, 0x01, 0x76, 0xFC, 0x01, 0x07, 0x7D, 0xF1, 0xAD, 0x30, 0xDC,
-	0x2F, 0x7F, 0xF1, 0x0C, 0x07, 0x6C, 0xFC, 0xAD, 0x01, 0x5A, 0xFF,
-	0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C,
-	0x00, 0x7B, 0xFE, 0x0C, 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A,
-	0xCD, 0xF4, 0x4B, 0x06, 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35,
-	0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x93, 0xFF, 0xEC, 0x00, 0x83, 0xFE,
-	0xF7, 0x01, 0xE8, 0xFD, 0x21, 0x01, 0xD2, 0x48, 0x64, 0x06, 0xA1,
-	0xFB, 0x26, 0x03, 0xE7, 0xFD, 0x35, 0x01, 0x76, 0xFF, 0x22, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5,
-	0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8,
-	0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B,
-	0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x39, 0xFC,
-	0x29, 0x07, 0xEF, 0xF1, 0x62, 0x29, 0xA5, 0x36, 0xD0, 0xF1, 0x7B,
-	0x06, 0xE3, 0xFC, 0x5E, 0x01, 0x83, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
-	0x01, 0x00, 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84,
-	0x05, 0xFD, 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06,
-	0x37, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12,
-	0x00, 0xB5, 0xFF, 0x94, 0x00, 0x39, 0xFF, 0xA3, 0x00, 0x58, 0x00,
-	0x02, 0xFC, 0x73, 0x47, 0x0B, 0x0D, 0x0B, 0xF9, 0x6C, 0x04, 0x45,
-	0xFD, 0x80, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x2A, 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31,
-	0xF9, 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00,
-	0x2E, 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xE6, 0x01, 0x39, 0xFC, 0xE4, 0x06, 0x21, 0xF3,
-	0xC4, 0x21, 0xA5, 0x3C, 0x16, 0xF3, 0x72, 0x05, 0x9A, 0xFD, 0xEF,
-	0x00, 0xBC, 0xFF, 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-	0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
-	0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
-	0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD6, 0xFF, 0x3F,
-	0x00, 0xE7, 0xFF, 0x65, 0xFF, 0x85, 0x02, 0xDE, 0xF7, 0xA9, 0x44,
-	0x43, 0x14, 0x99, 0xF6, 0x8B, 0x05, 0xBF, 0xFC, 0xBA, 0x01, 0x43,
-	0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF,
-	0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB,
-	0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00,
-	0x91, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
-	0x01, 0x72, 0xFC, 0x3F, 0x06, 0xEB, 0xF4, 0x12, 0x1A, 0xA1, 0x41,
-	0x63, 0xF5, 0xF3, 0x03, 0x8A, 0xFE, 0x63, 0x00, 0x02, 0x00, 0xEE,
-	0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF, 0xB1, 0x01,
-	0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15, 0x31, 0x7C,
-	0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF, 0x29, 0x00,
-	0xFD, 0xFF, 0x04, 0x00, 0xF4, 0xFF, 0xF1, 0xFF, 0x85, 0x00, 0x4E,
-	0xFE, 0x56, 0x04, 0xC3, 0xF4, 0x95, 0x40, 0xD8, 0x1B, 0x76, 0xF4,
-	0x6D, 0x06, 0x60, 0xFC, 0xDD, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB, 0x01,
-	0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB, 0x60,
-	0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAE, 0x01, 0xDB, 0xFC, 0x4D,
-	0x05, 0x24, 0xF7, 0x8E, 0x12, 0x6D, 0x45, 0xBC, 0xF8, 0x0C, 0x02,
-	0xAC, 0xFF, 0xC0, 0xFF, 0x52, 0x00, 0xCF, 0xFF, 0x0C, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x25, 0x07,
-	0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7, 0xF1, 0x56, 0x06, 0xFE,
-	0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x0D, 0x00, 0xAE, 0xFF, 0x0B, 0x01, 0x6A, 0xFD, 0xBA, 0x05, 0xB4,
-	0xF2, 0x58, 0x3B, 0x8A, 0x23, 0xCB, 0xF2, 0xFD, 0x06, 0x34, 0xFC,
-	0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBB,
-	0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00, 0xBE, 0x00, 0x38, 0xFB,
-	0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1, 0x04, 0x2B, 0xFD, 0x8B,
-	0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00,
-	0x5F, 0xFF, 0x70, 0x01, 0x68, 0xFD, 0x23, 0x04, 0xA2, 0xF9, 0x73,
-	0x0B, 0xE4, 0x47, 0x1B, 0xFD, 0xCD, 0xFF, 0xF0, 0x00, 0x0F, 0xFF,
-	0xA9, 0x00, 0xAE, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE6, 0x01, 0x3F, 0xFC, 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20,
-	0x96, 0x3D, 0x69, 0xF3, 0x38, 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7,
-	0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x78, 0xFF,
-	0x74, 0x01, 0xC2, 0xFC, 0xA7, 0x06, 0xA8, 0xF1, 0x25, 0x35, 0x1B,
-	0x2B, 0xC2, 0xF1, 0x2A, 0x07, 0x41, 0xFC, 0xCE, 0x01, 0x47, 0xFF,
-	0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04,
-	0x00, 0x32, 0xFF, 0xDC, 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15,
-	0x34, 0xF6, 0xB7, 0x05, 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x23, 0x01,
-	0x0F, 0xFE, 0xD7, 0x02, 0x3B, 0xFC, 0xF5, 0x04, 0xED, 0x48, 0x70,
-	0x02, 0x52, 0xFD, 0x46, 0x02, 0x5A, 0xFE, 0xFF, 0x00, 0x8B, 0xFF,
-	0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81,
-	0xFC, 0x1A, 0x06, 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5,
-	0xA6, 0x03, 0xB9, 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07,
-	0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x53, 0xFF, 0xBB, 0x01, 0x5A, 0xFC,
-	0x1C, 0x07, 0x8D, 0xF1, 0x34, 0x2E, 0x48, 0x32, 0x81, 0xF1, 0xE7,
-	0x06, 0x8E, 0xFC, 0x96, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
-	0x04, 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B,
-	0x04, 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06,
-	0x55, 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
-	0x00, 0x9F, 0xFF, 0xCE, 0x00, 0xC2, 0xFE, 0x80, 0x01, 0xC6, 0xFE,
-	0x40, 0xFF, 0x81, 0x48, 0x9E, 0x08, 0xBA, 0xFA, 0x9A, 0x03, 0xAC,
-	0xFD, 0x51, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x2F, 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F,
-	0xF7, 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF,
-	0xA2, 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35,
-	0x00, 0x3D, 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1D, 0x07, 0x45, 0xF2,
-	0xC6, 0x26, 0xD3, 0x38, 0x24, 0xF2, 0x2D, 0x06, 0x1B, 0xFD, 0x3B,
-	0x01, 0x95, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00,
-	0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
-	0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
-	0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC1, 0xFF, 0x76,
-	0x00, 0x76, 0xFF, 0x32, 0x00, 0x22, 0x01, 0x76, 0xFA, 0xA3, 0x46,
-	0x7D, 0x0F, 0x2C, 0xF8, 0xD5, 0x04, 0x13, 0xFD, 0x96, 0x01, 0x51,
-	0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64, 0xFF,
-	0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A, 0x2C,
-	0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8, 0x00,
-	0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-	0x01, 0x47, 0xFC, 0xB5, 0x06, 0xB0, 0xF3, 0x19, 0x1F, 0x7E, 0x3E,
-	0xC4, 0xF3, 0xFA, 0x04, 0xE7, 0xFD, 0xC1, 0x00, 0xD3, 0xFF, 0xFF,
-	0xFF, 0x02, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF, 0x82, 0x01,
-	0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62, 0x2C, 0xA8,
-	0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF, 0x30, 0x00,
-	0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF, 0x23, 0x00, 0x20, 0x00, 0x00,
-	0xFF, 0x31, 0x03, 0xAD, 0xF6, 0x65, 0x43, 0xDC, 0x16, 0xD1, 0xF5,
-	0xE1, 0x05, 0x99, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14, 0x01, 0x2D, 0xFE,
-	0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48, 0x73, 0x03, 0xE0,
-	0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86, 0xFF, 0x1E, 0x00,
-	0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCC, 0x01, 0x91, 0xFC, 0xF3,
-	0x05, 0xA6, 0xF5, 0x70, 0x17, 0x17, 0x43, 0x6D, 0xF6, 0x56, 0x03,
-	0xEA, 0xFE, 0x2D, 0x00, 0x1D, 0x00, 0xE4, 0xFF, 0x08, 0x00, 0xFD,
-	0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07,
-	0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2,
-	0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00,
-	0xFD, 0xFF, 0xD8, 0xFF, 0xB7, 0x00, 0xF9, 0xFD, 0xDE, 0x04, 0xEF,
-	0xF3, 0xE4, 0x3E, 0x81, 0x1E, 0xD2, 0xF3, 0xA9, 0x06, 0x4B, 0xFC,
-	0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA5,
-	0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45, 0x01, 0x33, 0xFF, 0x5A, 0xFE,
-	0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA, 0xD2, 0x03, 0x90, 0xFD, 0x5E,
-	0x01, 0x66, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
-	0x4F, 0xFF, 0x9A, 0x01, 0x08, 0xFD, 0xEB, 0x04, 0xFC, 0xF7, 0x0A,
-	0x10, 0x70, 0x46, 0x22, 0xFA, 0x4D, 0x01, 0x19, 0x00, 0x84, 0xFF,
-	0x70, 0x00, 0xC4, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
-	0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
-	0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
-	0xFF, 0x13, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x99, 0xFF,
-	0x33, 0x01, 0x29, 0xFD, 0x1A, 0x06, 0x3B, 0xF2, 0x4B, 0x39, 0x30,
-	0x26, 0x5B, 0xF2, 0x19, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF,
-	0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95,
-	0xFF, 0xFA, 0xFF, 0x83, 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10,
-	0xBF, 0xF7, 0x07, 0x05, 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x56, 0x01,
-	0xA0, 0xFD, 0xB3, 0x03, 0x87, 0xFA, 0x1F, 0x09, 0x6A, 0x48, 0xD9,
-	0xFE, 0xF6, 0xFE, 0x65, 0x01, 0xD0, 0xFE, 0xC7, 0x00, 0xA2, 0xFF,
-	0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50,
-	0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4,
-	0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03,
-	0x00, 0xFD, 0xFF, 0x26, 0x00, 0x69, 0xFF, 0x90, 0x01, 0x96, 0xFC,
-	0xDD, 0x06, 0x85, 0xF1, 0xD0, 0x32, 0xA6, 0x2D, 0x94, 0xF1, 0x20,
-	0x07, 0x54, 0xFC, 0xBF, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-	0x07, 0x00, 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83,
-	0x03, 0x20, 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06,
-	0x88, 0xFC, 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
-	0x00, 0x89, 0xFF, 0x06, 0x01, 0x4C, 0xFE, 0x60, 0x02, 0x1F, 0xFD,
-	0xE2, 0x02, 0xF3, 0x48, 0x7D, 0x04, 0x6E, 0xFC, 0xBD, 0x02, 0x1C,
-	0xFE, 0x1C, 0x01, 0x80, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x33, 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07,
-	0xF6, 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF,
-	0x11, 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
-	0x00, 0x49, 0xFF, 0xCB, 0x01, 0x45, 0xFC, 0x29, 0x07, 0xB6, 0xF1,
-	0xAD, 0x2B, 0xA2, 0x34, 0x9E, 0xF1, 0xB4, 0x06, 0xB8, 0xFC, 0x7A,
-	0x01, 0x75, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00,
-	0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
-	0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAB, 0xFF, 0xAF,
-	0x00, 0x01, 0xFF, 0x0A, 0x01, 0x9E, 0xFF, 0x7C, 0xFD, 0x03, 0x48,
-	0xED, 0x0A, 0xD5, 0xF9, 0x0A, 0x04, 0x74, 0xFD, 0x6A, 0x01, 0x62,
-	0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF,
-	0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1,
-	0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00,
-	0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-	0x01, 0x33, 0xFC, 0x04, 0x07, 0xB1, 0xF2, 0x21, 0x24, 0xE6, 0x3A,
-	0x97, 0xF2, 0xD0, 0x05, 0x5B, 0xFD, 0x15, 0x01, 0xA9, 0xFF, 0x0F,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF, 0x45, 0x01,
-	0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80, 0x27, 0x2B,
-	0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF, 0x34, 0x00,
-	0xFD, 0xFF, 0x0D, 0x00, 0xCD, 0xFF, 0x59, 0x00, 0xB3, 0xFF, 0xC4,
-	0xFF, 0xE2, 0x01, 0x09, 0xF9, 0xAA, 0x45, 0xFE, 0x11, 0x54, 0xF7,
-	0x38, 0x05, 0xE4, 0xFC, 0xAA, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC, 0xFD,
-	0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF, 0x89,
-	0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18, 0x00,
-	0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5B, 0xFC, 0x7B,
-	0x06, 0x50, 0xF4, 0x6E, 0x1C, 0x36, 0x40, 0x92, 0xF4, 0x75, 0x04,
-	0x3B, 0xFE, 0x91, 0x00, 0xEB, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD,
-	0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01, 0x84, 0xFC, 0xF3, 0x06,
-	0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85, 0xF1, 0x16, 0x07, 0x61,
-	0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00,
-	0xEC, 0xFF, 0x08, 0x00, 0x57, 0x00, 0x9F, 0xFE, 0xD1, 0x03, 0x9B,
-	0xF5, 0xF7, 0x41, 0x7C, 0x19, 0x13, 0xF5, 0x2F, 0x06, 0x78, 0xFC,
-	0xD5, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8F,
-	0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02, 0x91, 0xFD, 0xE3, 0x01,
-	0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8, 0x02, 0xFE, 0xFD, 0x2B,
-	0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
-	0x42, 0xFF, 0xBD, 0x01, 0xB6, 0xFC, 0x9F, 0x05, 0x6C, 0xF6, 0xD6,
-	0x14, 0x65, 0x44, 0x98, 0xF7, 0xAC, 0x02, 0x4E, 0xFF, 0xF4, 0xFF,
-	0x39, 0x00, 0xD9, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45,
-	0xFF, 0xD2, 0x01, 0x3D, 0xFC, 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A,
-	0xC6, 0x35, 0xB7, 0xF1, 0x96, 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D,
-	0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x06, 0x00, 0xC1, 0xFF,
-	0xE5, 0x00, 0xAA, 0xFD, 0x58, 0x05, 0x3A, 0xF3, 0x11, 0x3D, 0x2C,
-	0x21, 0x3F, 0xF3, 0xDA, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20,
-	0xFF, 0xD0, 0x00, 0x07, 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C,
-	0x63, 0xF9, 0x42, 0x04, 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x85, 0x01,
-	0x39, 0xFD, 0x84, 0x04, 0xD9, 0xF8, 0x95, 0x0D, 0x48, 0x47, 0xA7,
-	0xFB, 0x86, 0x00, 0x8A, 0x00, 0x46, 0xFF, 0x8E, 0x00, 0xB8, 0xFF,
-	0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35,
-	0xFC, 0xF3, 0x06, 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2,
-	0x9C, 0x05, 0x7E, 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01,
-	0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x87, 0xFF, 0x57, 0x01, 0xEF, 0xFC,
-	0x6B, 0x06, 0xE0, 0xF1, 0x23, 0x37, 0xCE, 0x28, 0x01, 0xF2, 0x28,
-	0x07, 0x36, 0xFC, 0xD9, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x0B, 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F,
-	0x02, 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05,
-	0xCF, 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x23, 0x00, 0x74, 0xFF, 0x3C, 0x01, 0xDA, 0xFD, 0x40, 0x03,
-	0x6E, 0xFB, 0xE1, 0x06, 0xC3, 0x48, 0xB3, 0x00, 0x1A, 0xFE, 0xDC,
-	0x01, 0x91, 0xFE, 0xE5, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-	0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6,
-	0xF4, 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE,
-	0x77, 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A,
-	0x00, 0x5C, 0xFF, 0xA8, 0x01, 0x73, 0xFC, 0x05, 0x07, 0x7D, 0xF1,
-	0x67, 0x30, 0x21, 0x30, 0x7E, 0xF1, 0x08, 0x07, 0x6F, 0xFC, 0xAB,
-	0x01, 0x5B, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF0, 0xFF,
-	0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
-	0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
-	0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE8,
-	0x00, 0x8A, 0xFE, 0xE9, 0x01, 0x01, 0xFE, 0xEA, 0x00, 0xCB, 0x48,
-	0xA2, 0x06, 0x87, 0xFB, 0x33, 0x03, 0xE0, 0xFD, 0x39, 0x01, 0x75,
-	0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF,
-	0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13, 0xFD,
-	0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47, 0x00,
-	0xD3, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD8,
-	0x01, 0x37, 0xFC, 0x29, 0x07, 0xF8, 0xF1, 0x19, 0x29, 0xE5, 0x36,
-	0xD8, 0xF1, 0x73, 0x06, 0xE9, 0xFC, 0x5B, 0x01, 0x85, 0xFF, 0x1C,
-	0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF, 0xFB, 0x00,
-	0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81, 0x22, 0xFC,
-	0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x12, 0x00, 0xB7, 0xFF, 0x91, 0x00, 0x40, 0xFF, 0x96,
-	0x00, 0x6F, 0x00, 0xD5, 0xFB, 0x5E, 0x47, 0x50, 0x0D, 0xF2, 0xF8,
-	0x78, 0x04, 0x3F, 0xFD, 0x82, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79, 0x01, 0x53, 0xFD,
-	0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47, 0x76, 0xFC, 0x1F,
-	0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2, 0xFF, 0x13, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xDF,
-	0x06, 0x30, 0xF3, 0x78, 0x21, 0xDB, 0x3C, 0x28, 0xF3, 0x65, 0x05,
-	0xA2, 0xFD, 0xEA, 0x00, 0xBE, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE,
-	0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06,
-	0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C,
-	0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
-	0xD8, 0xFF, 0x3C, 0x00, 0xEE, 0xFF, 0x5A, 0xFF, 0x98, 0x02, 0xBB,
-	0xF7, 0x87, 0x44, 0x8C, 0x14, 0x83, 0xF6, 0x95, 0x05, 0xBA, 0xFC,
-	0xBB, 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
-	0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7, 0xFD, 0x05, 0x03, 0xE1, 0xFB,
-	0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01, 0xAA, 0xFD, 0x18, 0x02, 0x72,
-	0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x39, 0xFF, 0xD6, 0x01, 0x75, 0xFC, 0x37, 0x06, 0xFF, 0xF4, 0xC7,
-	0x19, 0xCC, 0x41, 0x7F, 0xF5, 0xE2, 0x03, 0x95, 0xFE, 0x5D, 0x00,
-	0x05, 0x00, 0xED, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
-	0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
-	0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
-	0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF5, 0xFF, 0xEE, 0xFF,
-	0x8B, 0x00, 0x44, 0xFE, 0x65, 0x04, 0xAA, 0xF4, 0x66, 0x40, 0x23,
-	0x1C, 0x63, 0xF4, 0x74, 0x06, 0x5D, 0xFC, 0xDE, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA,
-	0xFE, 0xAE, 0x01, 0x70, 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07,
-	0x14, 0xFB, 0x6D, 0x03, 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAC, 0x01,
-	0xDF, 0xFC, 0x43, 0x05, 0x3C, 0xF7, 0x46, 0x12, 0x8D, 0x45, 0xE2,
-	0xF8, 0xF7, 0x01, 0xB8, 0xFF, 0xB9, 0xFF, 0x56, 0x00, 0xCE, 0xFF,
-	0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34,
-	0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2,
-	0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAB, 0xFF, 0x10, 0x01, 0x62, 0xFD,
-	0xC5, 0x05, 0xA5, 0xF2, 0x1F, 0x3B, 0xD6, 0x23, 0xBE, 0xF2, 0x01,
-	0x07, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x10, 0x00, 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4,
-	0x00, 0x0C, 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04,
-	0x26, 0xFD, 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x29, 0x00, 0x60, 0xFF, 0x6D, 0x01, 0x6E, 0xFD, 0x17, 0x04,
-	0xBC, 0xF9, 0x30, 0x0B, 0xF4, 0x47, 0x4B, 0xFD, 0xB5, 0xFF, 0xFD,
-	0x00, 0x08, 0xFF, 0xAC, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76,
-	0xF3, 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD,
-	0xD4, 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21,
-	0x00, 0x77, 0xFF, 0x77, 0x01, 0xBD, 0xFC, 0xAE, 0x06, 0xA3, 0xF1,
-	0xE3, 0x34, 0x64, 0x2B, 0xBC, 0xF1, 0x2A, 0x07, 0x43, 0xFC, 0xCD,
-	0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDD, 0xFF,
-	0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
-	0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
-	0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F,
-	0xFF, 0x20, 0x01, 0x16, 0xFE, 0xCA, 0x02, 0x54, 0xFC, 0xB9, 0x04,
-	0xF2, 0x48, 0xA9, 0x02, 0x39, 0xFD, 0x53, 0x02, 0x53, 0xFE, 0x03,
-	0x01, 0x8A, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF,
-	0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89,
-	0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00,
-	0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBD,
-	0x01, 0x57, 0xFC, 0x1E, 0x07, 0x90, 0xF1, 0xED, 0x2D, 0x8C, 0x32,
-	0x83, 0xF1, 0xE2, 0x06, 0x92, 0xFC, 0x93, 0x01, 0x68, 0xFF, 0x26,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF, 0xA4, 0x00,
-	0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78, 0x1D, 0x10,
-	0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF, 0xCA, 0x00, 0xC9, 0xFE, 0x73,
-	0x01, 0xDE, 0xFE, 0x0C, 0xFF, 0x76, 0x48, 0xDE, 0x08, 0xA1, 0xFA,
-	0xA6, 0x03, 0xA6, 0xFD, 0x53, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6, 0xFC,
-	0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9, 0x98,
-	0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x32, 0xFC, 0x1B,
-	0x07, 0x50, 0xF2, 0x7B, 0x26, 0x11, 0x39, 0x2F, 0xF2, 0x23, 0x06,
-	0x22, 0xFD, 0x37, 0x01, 0x97, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01, 0x41, 0xFD, 0xF6, 0x05,
-	0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84, 0xF2, 0x0F, 0x07, 0x31,
-	0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00,
-	0xC2, 0xFF, 0x73, 0x00, 0x7D, 0xFF, 0x25, 0x00, 0x38, 0x01, 0x4C,
-	0xFA, 0x89, 0x46, 0xC3, 0x0F, 0x14, 0xF8, 0xE0, 0x04, 0x0D, 0xFD,
-	0x98, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
-	0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD, 0xDF, 0x03, 0x2E, 0xFA,
-	0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B, 0xFF, 0x38, 0x01, 0xE9,
-	0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE4, 0x01, 0x49, 0xFC, 0xAF, 0x06, 0xC1, 0xF3, 0xCD,
-	0x1E, 0xB1, 0x3E, 0xD9, 0xF3, 0xEC, 0x04, 0xF0, 0xFD, 0xBC, 0x00,
-	0xD5, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F,
-	0xFF, 0x85, 0x01, 0xA6, 0xFC, 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33,
-	0xAB, 0x2C, 0xA3, 0xF1, 0x26, 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D,
-	0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE2, 0xFF, 0x20, 0x00,
-	0x26, 0x00, 0xF5, 0xFE, 0x43, 0x03, 0x8D, 0xF6, 0x3C, 0x43, 0x25,
-	0x17, 0xBB, 0xF5, 0xEA, 0x05, 0x95, 0xFC, 0xCA, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11,
-	0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48,
-	0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84,
-	0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-	0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A,
-	0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00,
-	0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1,
-	0xFD, 0x4E, 0x05, 0x4A, 0xF3, 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3,
-	0xD6, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE,
-	0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7,
-	0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00,
-	0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5, 0x01, 0x4C, 0xFC, 0x26,
-	0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33, 0x8F, 0xF1, 0xCA, 0x06,
-	0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x16,
-	0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF,
-	0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A,
-	0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F, 0x07, 0x84,
-	0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05, 0x41, 0xFD,
-	0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8,
-	0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9,
-	0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2,
-	0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
-	0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
-	0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0x07, 0x00, 0xE8, 0xFF, 0x12,
-	0x00, 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42,
-	0x76, 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B,
-	0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF,
-	0xC3, 0x01, 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7,
-	0x43, 0x20, 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00,
-	0xDD, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4,
-	0x00, 0xC8, 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20,
-	0x76, 0xF3, 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01,
-	0x26, 0xFD, 0xAD, 0x04, 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C,
-	0xFB, 0xD4, 0x00, 0x5D, 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF,
-	0x10, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04,
-	0xFD, 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2,
-	0x23, 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x46, 0x01, 0xC3, 0xFD,
-	0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07, 0xA6, 0x48, 0xF8, 0xFF, 0x70,
-	0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9, 0x00, 0x9A, 0xFF, 0x19, 0x00,
-	0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
-	0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
-	0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B,
-	0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18, 0x02, 0xAA, 0xFD,
-	0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB, 0x05, 0x03, 0xF7,
-	0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07, 0xDC,
-	0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5, 0xFC,
-	0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xB2,
-	0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76, 0xFC,
-	0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD, 0x79,
-	0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
-	0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
-	0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xD3, 0xFF, 0x47,
-	0x00, 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44,
-	0x8D, 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45,
-	0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF,
-	0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32,
-	0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF,
-	0xF0, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77,
-	0x00, 0x67, 0xFE, 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B,
-	0xA6, 0xF4, 0x5A, 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01,
-	0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E,
-	0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF,
-	0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E,
-	0xFD, 0x9C, 0x05, 0xDC, 0xF2, 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2,
-	0xF3, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x76, 0x01, 0x59, 0xFD,
-	0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, 0xB6, 0x47, 0xA4, 0xFC, 0x07,
-	0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, 0x00, 0xB1, 0xFF, 0x13, 0x00,
-	0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B, 0x01, 0xCF, 0xFC, 0x96,
-	0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A, 0xD4, 0xF1, 0x2B, 0x07,
-	0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02,
-	0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25,
-	0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C, 0x00, 0xFD, 0xFF,
-	0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16, 0x07, 0x85,
-	0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06, 0x84, 0xFC,
-	0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9C,
-	0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF,
-	0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49,
-	0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
-	0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
-	0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F,
-	0x00, 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46,
-	0xCD, 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53,
-	0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE5, 0x01, 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE,
-	0x3D, 0x91, 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF,
-	0x02, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11,
-	0x00, 0x1B, 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16,
-	0x07, 0xF6, 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01,
-	0x88, 0xFC, 0x09, 0x06, 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20,
-	0xF6, 0x83, 0x03, 0xCF, 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF,
-	0x07, 0x00, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10,
-	0xFE, 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3,
-	0x99, 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4D, 0xFF, 0xA0, 0x01, 0xFB, 0xFC,
-	0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10, 0x2B, 0x46, 0xBB, 0xF9, 0x83,
-	0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68, 0x00, 0xC7, 0xFF, 0x0E, 0x00,
-	0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
-	0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
-	0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90, 0xFD, 0xD2, 0x03,
-	0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE, 0x33, 0xFF, 0x45,
-	0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16, 0x00, 0xFD, 0xFF,
-	0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06, 0x8C,
-	0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E, 0xFC,
-	0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x86,
-	0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73, 0x03,
-	0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE, 0x14,
-	0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00,
-	0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
-	0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
-	0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8,
-	0x00, 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48,
-	0x47, 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64,
-	0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF,
-	0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54,
-	0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF,
-	0x11, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2,
-	0xFF, 0xE2, 0xFF, 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11,
-	0x8F, 0xF7, 0x1D, 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01,
-	0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55,
-	0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF,
-	0x04, 0x00, 0x07, 0x00, 0xE9, 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9,
-	0xFE, 0xA6, 0x03, 0xE4, 0xF5, 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5,
-	0x1A, 0x06, 0x81, 0xFC, 0xD2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC1, 0x01, 0xAB, 0xFC,
-	0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, 0x0B, 0x44, 0x42, 0xF7, 0xDC,
-	0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, 0x00, 0xDC, 0xFF, 0x09, 0x00,
-	0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9, 0x00, 0xBF, 0xFD, 0x38,
-	0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20, 0x66, 0xF3, 0xCE, 0x06,
-	0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-	0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04,
-	0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A,
-	0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
-	0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56, 0x06, 0xF7,
-	0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07, 0x34, 0xFC,
-	0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24,
-	0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB,
-	0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3,
-	0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00,
-	0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
-	0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
-	0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1,
-	0x00, 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48,
-	0x07, 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78,
-	0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF,
-	0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46,
-	0x36, 0xC5, 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF,
-	0x1E, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E,
-	0xFF, 0xB6, 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C,
-	0x31, 0xF9, 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01,
-	0x37, 0xFC, 0xEB, 0x06, 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD,
-	0xF2, 0x84, 0x05, 0x8D, 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00,
-	0x01, 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77,
-	0xFF, 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6,
-	0x7C, 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF,
-	0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD9, 0x01, 0x6D, 0xFC,
-	0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A, 0x5F, 0x41, 0x3A, 0xF5, 0x0C,
-	0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
-	0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
-	0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
-	0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF,
-	0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3, 0xFC, 0x5D, 0x05,
-	0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8, 0x2A, 0x02, 0x9A,
-	0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C, 0x00, 0x00, 0x00,
-	0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05, 0xCC,
-	0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35, 0xFC,
-	0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29,
-	0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C, 0xF9,
-	0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00, 0x19,
-	0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x20, 0x00,
-	0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
-	0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
-	0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C,
-	0xFF, 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05,
-	0xEA, 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA,
-	0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF,
-	0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3,
-	0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF,
-	0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8,
-	0xFE, 0x93, 0x01, 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08,
-	0xE1, 0xFA, 0x86, 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01,
-	0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14,
-	0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00,
-	0xFF, 0xFF, 0x10, 0x00, 0xBF, 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44,
-	0x00, 0x01, 0x01, 0xB6, 0xFA, 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8,
-	0xC4, 0x04, 0x1B, 0xFD, 0x92, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF,
-	0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x44, 0xFC,
-	0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, 0x31, 0x3E, 0xA5, 0xF3, 0x0F,
-	0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, 0xFF, 0x01, 0x00, 0x02, 0x00,
-	0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17, 0x00, 0x10, 0xFF, 0x15,
-	0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16, 0xF1, 0xF5, 0xD3, 0x05,
-	0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06,
-	0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9,
-	0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0x03, 0x00,
-	0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8, 0x04, 0x10,
-	0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06, 0x4E, 0xFC,
-	0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E,
-	0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7,
-	0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E,
-	0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x13, 0x00,
-	0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
-	0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-	0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68,
-	0xFF, 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09,
-	0x57, 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2,
-	0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF,
-	0x8B, 0x01, 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A,
-	0x2D, 0x9A, 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF,
-	0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42,
-	0xFE, 0x74, 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04,
-	0x94, 0xFC, 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01,
-	0x48, 0xFC, 0x28, 0x07, 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97,
-	0xF1, 0xBE, 0x06, 0xB0, 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00,
-	0xFE, 0xFF, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D,
-	0x01, 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9,
-	0xF8, 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC,
-	0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24, 0x8F, 0x3A, 0x82, 0xF2, 0xE1,
-	0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6, 0xFF, 0x10, 0x00, 0x00, 0x00,
-	0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
-	0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
-	0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57, 0xFC, 0x85, 0x06,
-	0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4, 0x8C, 0x04, 0x2C,
-	0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04, 0x00, 0x06, 0x00,
-	0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03, 0xC7,
-	0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D, 0xFC,
-	0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32,
-	0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A, 0xF6,
-	0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF, 0xFE,
-	0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x05, 0x00,
-	0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
-	0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x56,
-	0xFF, 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D,
-	0x26, 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89,
-	0x00, 0xBA, 0xFF, 0x11, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF,
-	0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60,
-	0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF,
-	0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40,
-	0x01, 0xD0, 0xFD, 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48,
-	0x62, 0x00, 0x3F, 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98,
-	0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01,
-	0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80,
-	0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00,
-	0xFD, 0xFF, 0x1B, 0x00, 0x93, 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD,
-	0x01, 0xDC, 0xFD, 0x3C, 0x01, 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB,
-	0x1F, 0x03, 0xEA, 0xFD, 0x34, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43, 0xFF, 0xD6, 0x01, 0x39, 0xFC,
-	0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, 0x85, 0x36, 0xCC, 0xF1, 0x7F,
-	0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
-	0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35, 0xFF, 0xA9, 0x00, 0x4D,
-	0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C, 0x18, 0xF9, 0x66, 0x04,
-	0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06,
-	0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96,
-	0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01, 0x00, 0x0B, 0x00,
-	0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B, 0x02, 0xF0,
-	0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05, 0xC1, 0xFC,
-	0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35,
-	0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4,
-	0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66,
-	0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0x05, 0x00, 0xF4, 0xFF,
-	0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
-	0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
-	0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x47,
-	0xFF, 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12,
-	0x5C, 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51,
-	0x00, 0xD0, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF,
-	0x09, 0x01, 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64,
-	0x23, 0xD2, 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71,
-	0x01, 0x65, 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47,
-	0x03, 0xFD, 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE,
-	0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01,
-	0xC4, 0xFC, 0xA4, 0x06, 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6,
-	0xF1, 0x2A, 0x07, 0x40, 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C,
-	0xFE, 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02,
-	0x5E, 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C,
-	0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0xBA, 0x01, 0x5B, 0xFC,
-	0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E, 0x26, 0x32, 0x80, 0xF1, 0xEA,
-	0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
-	0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
-	0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
-	0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32, 0xFC, 0x1E, 0x07,
-	0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2, 0x32, 0x06, 0x18,
-	0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
-	0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01, 0x8B,
-	0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15, 0xFD,
-	0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8, 0xF3,
-	0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD, 0xC4,
-	0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0xE1, 0xFF,
-	0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
-	0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
-	0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D,
-	0xFF, 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17,
-	0x02, 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B,
-	0x00, 0xE4, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF,
-	0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B,
-	0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C,
-	0x01, 0x05, 0xFD, 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46,
-	0x0D, 0xFA, 0x58, 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4,
-	0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01,
-	0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61,
-	0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D,
-	0xFD, 0xB9, 0x03, 0x7B, 0xFA, 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE,
-	0x03, 0xFF, 0x5F, 0x01, 0xD4, 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16,
-	0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A, 0xFF, 0x8E, 0x01, 0x99, 0xFC,
-	0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, 0x82, 0x2D, 0x96, 0xF1, 0x21,
-	0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-	0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49, 0xFE, 0x67, 0x02, 0x13,
-	0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04, 0x7A, 0xFC, 0xB6, 0x02,
-	0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07,
-	0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5,
-	0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x15, 0x00,
-	0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92, 0xFF, 0x94,
-	0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04, 0x77, 0xFD,
-	0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2,
-	0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17,
-	0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xCC, 0xFF,
-	0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
-	0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
-	0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37,
-	0xFF, 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C,
-	0x1F, 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA,
-	0xFF, 0xF7, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00,
-	0x54, 0x00, 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56,
-	0x19, 0x1E, 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF,
-	0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE,
-	0x01, 0xB4, 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44,
-	0x86, 0xF7, 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9,
-	0xFF, 0x0A, 0x00, 0x01, 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00,
-	0xAE, 0xFD, 0x52, 0x05, 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47,
-	0xF3, 0xD8, 0x06, 0x3C, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36,
-	0xFD, 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB,
-	0x91, 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11,
-	0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88, 0xFF, 0x55, 0x01, 0xF2, 0xFC,
-	0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37, 0xAA, 0x28, 0x05, 0xF2, 0x27,
-	0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
-	0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
-	0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFD,
-	0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75, 0xFC, 0x03, 0x07,
-	0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1, 0x0A, 0x07, 0x6E,
-	0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x1A, 0x00,
-	0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD, 0x05,
-	0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4, 0xFD,
-	0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33,
-	0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3, 0xF1,
-	0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC, 0x5C,
-	0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
-	0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
-	0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
-	0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37,
-	0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21,
-	0xC0, 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD,
-	0xFF, 0x07, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00,
-	0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68,
-	0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF,
-	0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
-	0x01, 0x73, 0xFC, 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41,
-	0x71, 0xF5, 0xEB, 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED,
-	0xFF, 0x06, 0x00, 0x04, 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00,
-	0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C,
-	0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD,
-	0xFC, 0x48, 0x05, 0x30, 0xF7, 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8,
-	0x01, 0x02, 0xB2, 0xFF, 0xBD, 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C,
-	0x00, 0x00, 0x00, 0x0E, 0x00, 0xAC, 0xFF, 0x0E, 0x01, 0x66, 0xFD,
-	0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, 0xB0, 0x23, 0xC4, 0xF2, 0xFF,
-	0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E, 0x01, 0x6B, 0xFD, 0x1D,
-	0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47, 0x33, 0xFD, 0xC1, 0xFF,
-	0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD, 0xFF, 0x14, 0x00, 0xFE,
-	0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06,
-	0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42,
-	0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1, 0x02, 0x47,
-	0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD, 0x4D, 0x02,
-	0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E,
-	0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1,
-	0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94,
-	0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
-	0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
-	0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
-	0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C,
-	0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26,
-	0xF2, 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96,
-	0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00,
-	0x7A, 0xFF, 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0,
-	0x0F, 0x20, 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF,
-	0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-	0x01, 0x48, 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E,
-	0xCF, 0xF3, 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF,
-	0xFF, 0x03, 0x00, 0x08, 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00,
-	0xFA, 0xFE, 0x3A, 0x03, 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6,
-	0xF5, 0xE6, 0x05, 0x97, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00,
-	0xFE, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93,
-	0xFC, 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6,
-	0x4D, 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08,
-	0x00, 0x03, 0x00, 0xFE, 0xFF, 0xD7, 0xFF, 0xBA, 0x00, 0xF4, 0xFD,
-	0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E, 0xA7, 0x1E, 0xCA, 0xF3, 0xAC,
-	0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-	0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
-	0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
-	0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0xFF,
-	0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25, 0xFD, 0x1E, 0x06,
-	0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2, 0x1A, 0x07, 0x31,
-	0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03, 0x94,
-	0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C, 0x01,
-	0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26,
-	0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84, 0xF1,
-	0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC, 0xBE,
-	0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
-	0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
-	0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
-	0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49,
-	0xFF, 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B,
-	0xC3, 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76,
-	0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00,
-	0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E,
-	0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF,
-	0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-	0x01, 0x33, 0xFC, 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B,
-	0x9E, 0xF2, 0xCB, 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E,
-	0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF,
-	0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48,
-	0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00,
-	0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C,
-	0xFC, 0x78, 0x06, 0x5A, 0xF4, 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4,
-	0x6D, 0x04, 0x3F, 0xFE, 0x8E, 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04,
-	0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x5A, 0x00, 0x9A, 0xFE,
-	0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, 0xA1, 0x19, 0x09, 0xF5, 0x33,
-	0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-	0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC, 0x01, 0xB8, 0xFC, 0x9A,
-	0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44, 0xA9, 0xF7, 0xA2, 0x02,
-	0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8, 0xFF, 0x0A, 0x00, 0x01,
-	0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05,
-	0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B,
-	0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E, 0x04, 0xE6,
-	0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00, 0x90, 0x00,
-	0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFE, 0xFF, 0x1C,
-	0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1,
-	0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8,
-	0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00,
-	0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
-	0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
-	0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C,
-	0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30,
-	0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C,
-	0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00,
-	0x8E, 0xFE, 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1,
-	0x06, 0x7B, 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF,
-	0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8,
-	0x01, 0x37, 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37,
-	0xDC, 0xF1, 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C,
-	0x00, 0xFE, 0xFF, 0x11, 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF,
-	0x90, 0x00, 0x7A, 0x00, 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6,
-	0xF8, 0x7E, 0x04, 0x3C, 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00,
-	0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B,
-	0xFC, 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3,
-	0x5F, 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01,
-	0x00, 0x0A, 0x00, 0xD8, 0xFF, 0x3A, 0x00, 0xF1, 0xFF, 0x54, 0xFF,
-	0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44, 0xB1, 0x14, 0x77, 0xF6, 0x9A,
-	0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
-	0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
-	0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
-	0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x04,
-	0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F, 0xFE, 0x6D, 0x04,
-	0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4, 0x78, 0x06, 0x5C,
-	0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
-	0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05, 0x48,
-	0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE, 0xFF,
-	0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0E,
-	0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E, 0xF2,
-	0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC, 0xE5,
-	0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00,
-	0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
-	0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
-	0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76,
-	0xFF, 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34,
-	0x89, 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49,
-	0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF,
-	0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2,
-	0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01,
-	0x8A, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE,
-	0x01, 0x56, 0xFC, 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32,
-	0x84, 0xF1, 0xE0, 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26,
-	0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE,
-	0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94,
-	0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00,
-	0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31,
-	0xFC, 0x1A, 0x07, 0x56, 0xF2, 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2,
-	0x1E, 0x06, 0x25, 0xFD, 0x35, 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF,
-	0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71, 0x00, 0x81, 0xFF, 0x1F, 0x00,
-	0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, 0xE7, 0x0F, 0x08, 0xF8, 0xE6,
-	0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
-	0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x4A, 0xFC, 0xAC,
-	0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E, 0xE4, 0xF3, 0xE5, 0x04,
-	0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0x08,
-	0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03,
-	0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93,
-	0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFE, 0xFF,
-	0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6, 0x05, 0xC6,
-	0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03, 0xFA, 0xFE,
-	0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFF,
-	0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3,
-	0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00,
-	0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
-	0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
-	0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96,
-	0xFF, 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38,
-	0xA0, 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C,
-	0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF,
-	0x52, 0x01, 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C,
-	0x48, 0x26, 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00,
-	0xA0, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94,
-	0x01, 0x90, 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E,
-	0x8E, 0xF1, 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E,
-	0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE,
-	0x4D, 0x02, 0x45, 0xFD, 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47,
-	0xFC, 0xD1, 0x02, 0x12, 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00,
-	0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42,
-	0xFC, 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1,
-	0xAB, 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
-	0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA, 0x00, 0x0C, 0xFF, 0xF7, 0x00,
-	0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47, 0x51, 0x0B, 0xAF, 0xF9, 0x1D,
-	0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
-	0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
-	0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x0C,
-	0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2, 0xFF, 0x01, 0x02,
-	0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7, 0x48, 0x05, 0xDD,
-	0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
-	0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06, 0x6C,
-	0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49, 0xFE,
-	0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xED,
-	0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71, 0xF5,
-	0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC, 0xD7,
-	0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00,
-	0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
-	0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
-	0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x07, 0x00, 0xBD,
-	0xFF, 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C,
-	0x9E, 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF,
-	0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69,
-	0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00,
-	0xB6, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C,
-	0x01, 0xE6, 0xFC, 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29,
-	0xF3, 0xF1, 0x29, 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33,
-	0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01,
-	0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05,
-	0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF,
-	0x1A, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E,
-	0xFC, 0x0A, 0x07, 0x7E, 0xF1, 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1,
-	0x03, 0x07, 0x75, 0xFC, 0xA7, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD,
-	0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3, 0x00, 0x95, 0xFE, 0xD5, 0x01,
-	0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, 0x00, 0x07, 0x61, 0xFB, 0x46,
-	0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, 0xFF, 0x23, 0x00, 0x00, 0x00,
-	0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA, 0x01, 0x36, 0xFC, 0x27,
-	0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37, 0xE4, 0xF1, 0x67, 0x06,
-	0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x11,
-	0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00,
-	0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36,
-	0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8, 0x06, 0x47,
-	0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05, 0xAE, 0xFD,
-	0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD9,
-	0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7,
-	0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE,
-	0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00,
-	0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
-	0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
-	0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF7, 0xFF, 0xEA,
-	0xFF, 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40,
-	0x94, 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37,
-	0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-	0xA9, 0x01, 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8,
-	0x45, 0x1C, 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00,
-	0xCC, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17,
-	0x01, 0x57, 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24,
-	0xAA, 0xF2, 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01,
-	0x77, 0xFD, 0x04, 0x04, 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94,
-	0xFD, 0x92, 0xFF, 0x10, 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF,
-	0x15, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5,
-	0xFC, 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1,
-	0x29, 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x1B, 0x01, 0x20, 0xFE,
-	0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04, 0xF4, 0x48, 0xFF, 0x02, 0x13,
-	0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07, 0x01, 0x88, 0xFF, 0x1D, 0x00,
-	0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
-	0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
-	0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16,
-	0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F, 0x01, 0x03, 0xFF,
-	0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA, 0xB9, 0x03, 0x9D,
-	0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07, 0x61,
-	0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C, 0xFD,
-	0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC4,
-	0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D, 0xFA,
-	0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD, 0x9C,
-	0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
-	0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
-	0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE4, 0xFF, 0x1B,
-	0x00, 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43,
-	0x96, 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D,
-	0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF,
-	0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77,
-	0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00,
-	0xE1, 0xFF, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4,
-	0x00, 0xE2, 0xFD, 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F,
-	0xA8, 0xF3, 0xB8, 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01,
-	0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B,
-	0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF,
-	0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18,
-	0xFD, 0x32, 0x06, 0x1F, 0xF2, 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2,
-	0x1E, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x4F, 0x01, 0xB0, 0xFD,
-	0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, 0x86, 0x48, 0x5A, 0xFF, 0xBA,
-	0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, 0x00, 0x9E, 0xFF, 0x17, 0x00,
-	0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97, 0x01, 0x8C, 0xFC, 0xEA,
-	0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E, 0x8B, 0xF1, 0x1B, 0x07,
-	0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C,
-	0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD,
-	0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C,
-	0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xC6,
-	0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06, 0xC4, 0xFC,
-	0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAE,
-	0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD,
-	0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71,
-	0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
-	0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
-	0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51,
-	0x00, 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45,
-	0xB2, 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47,
-	0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF,
-	0xDD, 0x01, 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB,
-	0x40, 0xD0, 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF,
-	0xF4, 0xFF, 0x05, 0x00, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66,
-	0x00, 0x85, 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A,
-	0xE1, 0xF4, 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35,
-	0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01,
-	0xC1, 0xFC, 0x86, 0x05, 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0,
-	0xF7, 0x7B, 0x02, 0x6B, 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF,
-	0x0B, 0x00, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96,
-	0xFD, 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3,
-	0xE6, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x2B, 0x00, 0x5A, 0xFF, 0x7E, 0x01, 0x48, 0xFD,
-	0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C, 0x7C, 0x47, 0x19, 0xFC, 0x4D,
-	0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96, 0x00, 0xB5, 0xFF, 0x12, 0x00,
-	0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
-	0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
-	0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA, 0xFD, 0x1F, 0x03,
-	0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01, 0xDC, 0xFD, 0xFD,
-	0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B, 0x00, 0xFD, 0xFF,
-	0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07, 0x80,
-	0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78, 0xFC,
-	0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x98,
-	0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62, 0x00,
-	0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD, 0x40,
-	0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
-	0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
-	0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89,
-	0x00, 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47,
-	0xFC, 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56,
-	0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61,
-	0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF,
-	0x05, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0x3D, 0xFF, 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15,
-	0x4A, 0xF6, 0xAD, 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01,
-	0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7,
-	0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF,
-	0x06, 0x00, 0x04, 0x00, 0xF8, 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C,
-	0xFE, 0x8C, 0x04, 0x6D, 0xF4, 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4,
-	0x85, 0x06, 0x57, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, 0xFF, 0xA7, 0x01, 0xEC, 0xFC,
-	0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, 0xD7, 0x45, 0x43, 0xF9, 0xC3,
-	0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, 0x00, 0xCB, 0xFF, 0x0D, 0x00,
-	0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B, 0x01, 0x50, 0xFD, 0xE1,
-	0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24, 0x9D, 0xF2, 0x09, 0x07,
-	0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03,
-	0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D,
-	0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15, 0x00, 0xFE, 0xFF,
-	0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE, 0x06, 0x97,
-	0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07, 0x48, 0xFC,
-	0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F,
-	0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC,
-	0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42,
-	0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
-	0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
-	0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2,
-	0x00, 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48,
-	0x81, 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68,
-	0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF,
-	0xE2, 0x01, 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5,
-	0x39, 0x4D, 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF,
-	0x13, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E,
-	0xFF, 0x06, 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10,
-	0xD7, 0xF7, 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01,
-	0x4E, 0xFC, 0xA0, 0x06, 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10,
-	0xF4, 0xC8, 0x04, 0x07, 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF,
-	0x03, 0x00, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9,
-	0xFE, 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5,
-	0x00, 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01, 0x9F, 0xFC,
-	0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16, 0x9E, 0x43, 0xDD, 0xF6, 0x15,
-	0x03, 0x10, 0xFF, 0x17, 0x00, 0x28, 0x00, 0xDF, 0xFF, 0x09, 0x00,
-	0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
-	0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
-	0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-	0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B, 0xFD, 0xC4, 0x04,
-	0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA, 0x01, 0x01, 0x44,
-	0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
-	0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06, 0x14,
-	0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33, 0xFC,
-	0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25,
-	0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1, 0xFA,
-	0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01, 0xB8,
-	0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-	0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
-	0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
-	0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA,
-	0x00, 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48,
-	0x50, 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C,
-	0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF,
-	0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86,
-	0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF,
-	0x20, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19,
-	0xFF, 0xDD, 0x00, 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B,
-	0x7C, 0xF9, 0x35, 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01,
-	0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC,
-	0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00,
-	0x00, 0x00, 0x0C, 0x00, 0xD1, 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A,
-	0xFF, 0x2A, 0x02, 0x83, 0xF8, 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7,
-	0x5D, 0x05, 0xD3, 0xFC, 0xB1, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF,
-	0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x64, 0xFC,
-	0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, 0xD9, 0x40, 0xEA, 0xF4, 0x3E,
-	0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, 0xFF, 0xF3, 0xFF, 0x05, 0x00,
-	0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C, 0x00, 0x7B, 0xFE, 0x0C,
-	0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A, 0xCD, 0xF4, 0x4B, 0x06,
-	0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF,
-	0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05,
-	0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77,
-	0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0x01, 0x00,
-	0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84, 0x05, 0xFD,
-	0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06, 0x37, 0xFC,
-	0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A,
-	0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9,
-	0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E,
-	0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-	0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
-	0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
-	0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78,
-	0xFF, 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06,
-	0xDB, 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1,
-	0x00, 0x91, 0xFF, 0x1B, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF,
-	0xB1, 0x01, 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15,
-	0x31, 0x7C, 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF,
-	0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3,
-	0xFE, 0xBB, 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07,
-	0x2E, 0xFB, 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01,
-	0x34, 0xFC, 0x25, 0x07, 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7,
-	0xF1, 0x56, 0x06, 0xFE, 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00,
-	0xFF, 0xFF, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A,
-	0x00, 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8,
-	0xA1, 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
-	0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3F, 0xFC,
-	0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20, 0x96, 0x3D, 0x69, 0xF3, 0x38,
-	0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7, 0xFF, 0x04, 0x00, 0x02, 0x00,
-	0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
-	0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
-	0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81, 0xFC, 0x1A, 0x06,
-	0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5, 0xA6, 0x03, 0xB9,
-	0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0x04, 0x00,
-	0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04, 0x55,
-	0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55, 0xFC,
-	0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F,
-	0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F, 0xF7,
-	0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF, 0xA2,
-	0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00,
-	0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
-	0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
-	0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64,
-	0xFF, 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A,
-	0x2C, 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8,
-	0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF,
-	0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62,
-	0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF,
-	0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14,
-	0x01, 0x2D, 0xFE, 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48,
-	0x73, 0x03, 0xE0, 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86,
-	0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01,
-	0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C,
-	0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00,
-	0xFD, 0xFF, 0x16, 0x00, 0xA5, 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45,
-	0x01, 0x33, 0xFF, 0x5A, 0xFE, 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA,
-	0xD2, 0x03, 0x90, 0xFD, 0x5E, 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC,
-	0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, 0xDF, 0x39, 0x5A, 0xF2, 0x00,
-	0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, 0xFF, 0x13, 0x00, 0x00, 0x00,
-	0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95, 0xFF, 0xFA, 0xFF, 0x83,
-	0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10, 0xBF, 0xF7, 0x07, 0x05,
-	0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06,
-	0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10,
-	0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0x07, 0x00,
-	0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83, 0x03, 0x20,
-	0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06, 0x88, 0xFC,
-	0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33,
-	0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6,
-	0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11,
-	0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00,
-	0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
-	0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x53,
-	0xFF, 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E,
-	0xE1, 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F,
-	0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF,
-	0x45, 0x01, 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80,
-	0x27, 0x2B, 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF,
-	0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49,
-	0x01, 0xBC, 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48,
-	0xC3, 0xFF, 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C,
-	0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01,
-	0x84, 0xFC, 0xF3, 0x06, 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85,
-	0xF1, 0x16, 0x07, 0x61, 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00,
-	0xFD, 0xFF, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25,
-	0x02, 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB,
-	0xF8, 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD2, 0x01, 0x3D, 0xFC,
-	0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A, 0xC6, 0x35, 0xB7, 0xF1, 0x96,
-	0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D, 0xFF, 0x1F, 0x00, 0xFE, 0xFF,
-	0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
-	0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
-	0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF3, 0x06,
-	0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2, 0x9C, 0x05, 0x7E,
-	0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00,
-	0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02, 0x5E,
-	0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF, 0xFC,
-	0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36,
-	0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6, 0xF4,
-	0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE, 0x77,
-	0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF0, 0xFF,
-	0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
-	0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
-	0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x45,
-	0xFF, 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13,
-	0xFD, 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47,
-	0x00, 0xD3, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF,
-	0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81,
-	0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79,
-	0x01, 0x53, 0xFD, 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47,
-	0x76, 0xFC, 0x1F, 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2,
-	0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01,
-	0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC,
-	0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7,
-	0xFD, 0x05, 0x03, 0xE1, 0xFB, 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01,
-	0xAA, 0xFD, 0x18, 0x02, 0x72, 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B,
-	0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB3, 0x01, 0x64, 0xFC,
-	0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, 0x5A, 0x31, 0x7D, 0xF1, 0xF7,
-	0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF,
-	0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA, 0xFE, 0xAE, 0x01, 0x70,
-	0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07, 0x14, 0xFB, 0x6D, 0x03,
-	0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07,
-	0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04,
-	0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x10, 0x00,
-	0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4, 0x00, 0x0C,
-	0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04, 0x26, 0xFD,
-	0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3,
-	0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4,
-	0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDD, 0xFF,
-	0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
-	0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
-	0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3B,
-	0xFF, 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18,
-	0x89, 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12,
-	0x00, 0xE8, 0xFF, 0x07, 0x00, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF,
-	0xA4, 0x00, 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78,
-	0x1D, 0x10, 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2,
-	0x01, 0xF6, 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46,
-	0x93, 0xF9, 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8,
-	0xFF, 0x0E, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01,
-	0x41, 0xFD, 0xF6, 0x05, 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84,
-	0xF2, 0x0F, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A,
-	0xFD, 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE,
-	0x4B, 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16,
-	0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F, 0xFF, 0x85, 0x01, 0xA6, 0xFC,
-	0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33, 0xAB, 0x2C, 0xA3, 0xF1, 0x26,
-	0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
-	0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
-	0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFD,
-	0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07,
-	0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71,
-	0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7,
-	0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02,
-	0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x02, 0x00, 0x05,
-	0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
-	0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED,
-	0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00,
-	0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x84,
-	0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
-	0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
-	0x01, 0x84, 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00,
-	0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04,
-	0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF,
-	0x27, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8, 0xFF, 0x64, 0x00, 0x9B,
-	0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9, 0x10, 0x46, 0x03, 0x11,
-	0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2, 0x01, 0x4C, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00, 0x42, 0x00,
-	0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76, 0x18, 0x5C,
-	0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00,
-	0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8,
-	0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3,
-	0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD,
-	0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23,
-	0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF,
-	0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
-	0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
-	0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07,
-	0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5,
-	0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0xFD, 0xFF,
-	0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC,
-	0xF2, 0x81, 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD,
-	0xFB, 0x00, 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35,
-	0x00, 0x38, 0xFF, 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4,
-	0xCE, 0x1A, 0x32, 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71,
-	0x00, 0xFB, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00,
-	0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44,
-	0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF,
-	0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
-	0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
-	0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
-	0x00, 0xB1, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
-	0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5,
-	0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00,
-	0x8F, 0xFF, 0x1C, 0x00, 0x18, 0x00, 0x9C, 0xFF, 0xD6, 0x00, 0xB1,
-	0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF, 0x9C, 0x48, 0xFD, 0x07,
-	0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49, 0x01, 0x6E, 0xFF, 0x24,
-	0x00, 0x00, 0x00, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00, 0x65, 0xFF,
-	0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD, 0x0E, 0x6A,
-	0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF, 0x2D, 0x00,
-	0xFF, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B,
-	0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6,
-	0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF,
-	0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE,
-	0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99,
-	0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-	0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
-	0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
-	0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06,
-	0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E,
-	0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-	0x30, 0x00, 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8,
-	0xF1, 0x62, 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC,
-	0x82, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x3A, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2,
-	0xDD, 0x24, 0x54, 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20,
-	0x01, 0xA3, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C,
-	0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00,
-	0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-	0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
-	0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
-	0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF,
-	0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F,
-	0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00,
-	0xBB, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x43,
-	0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB, 0x7E, 0x07, 0xAF, 0x48,
-	0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3, 0xFE, 0xDD, 0x00, 0x99,
-	0xFF, 0x19, 0x00, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00, 0x79, 0xFE,
-	0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07, 0x06, 0xC7,
-	0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF, 0x22, 0x00,
-	0x00, 0x00, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6,
-	0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9,
-	0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00,
-	0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF,
-	0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C,
-	0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF,
-	0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
-	0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
-	0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00,
-	0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05,
-	0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35,
-	0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF,
-	0x20, 0x00, 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1,
-	0xF1, 0x86, 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC,
-	0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2D,
-	0x00, 0x54, 0xFF, 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1,
-	0x9F, 0x2E, 0xE3, 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A,
-	0x01, 0x64, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00,
-	0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36,
-	0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01,
-	0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
-	0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
-	0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
-	0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB,
-	0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00,
-	0xE5, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9E,
-	0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7, 0x75, 0x10, 0x48, 0x46,
-	0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E, 0xFF, 0x6B, 0x00, 0xC6,
-	0xFF, 0x0E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x5B, 0x01,
-	0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57, 0x48, 0x8D,
-	0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00, 0xA4, 0xFF,
-	0x16, 0x00, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74,
-	0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC,
-	0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00,
-	0x00, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01,
-	0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8,
-	0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00,
-	0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
-	0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
-	0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x06,
-	0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03,
-	0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D,
-	0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x02, 0x00,
-	0x05, 0x00, 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56,
-	0xF3, 0x61, 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC,
-	0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x1A,
-	0x00, 0x8A, 0xFF, 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1,
-	0x82, 0x37, 0x60, 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB,
-	0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x29, 0x00,
-	0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF,
-	0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01,
-	0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x43,
-	0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
-	0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
-	0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A,
-	0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF,
-	0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8,
-	0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4, 0x38, 0x1A, 0x8C, 0x41,
-	0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66, 0x00, 0x01, 0x00, 0xEE,
-	0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF, 0xAF, 0x01,
-	0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C, 0x45, 0xA9,
-	0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00, 0xD0, 0xFF,
-	0x0C, 0x00, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65,
-	0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD,
-	0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14,
-	0x00, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE,
-	0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E,
-	0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00,
-	0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
-	0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
-	0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x0F,
-	0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01,
-	0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15,
-	0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x08, 0x00,
-	0xE1, 0xFF, 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD,
-	0xF6, 0x77, 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC,
-	0xC8, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFD,
-	0xFF, 0xD9, 0xFF, 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3,
-	0xFC, 0x3E, 0x5B, 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x14, 0x00,
-	0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A,
-	0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-	0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
-	0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
-	0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
-	0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-	0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81,
-	0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF,
-	0x22, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-	0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2, 0x46, 0x24, 0xC8, 0x3A,
-	0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17, 0x01, 0xA8, 0xFF, 0x0F,
-	0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01,
-	0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F, 0x40, 0x85,
-	0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF, 0xF7, 0xFF,
-	0x04, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4,
-	0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7,
-	0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A,
-	0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD,
-	0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91,
-	0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00,
-	0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
-	0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
-	0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0x1A,
-	0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD,
-	0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4,
-	0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0x12, 0x00,
-	0xB6, 0xFF, 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB,
-	0xFB, 0x69, 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD,
-	0x81, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD7,
-	0xFF, 0x3E, 0x00, 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7,
-	0x99, 0x44, 0x68, 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA,
-	0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF5, 0xFF,
-	0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D,
-	0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01,
-	0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
-	0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
-	0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF,
-	0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40,
-	0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF,
-	0x31, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2E, 0x00, 0x52, 0xFF, 0xBC,
-	0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1, 0x11, 0x2E, 0x6B, 0x32,
-	0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94, 0x01, 0x67, 0xFF, 0x26,
-	0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE0, 0x01,
-	0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2, 0x38, 0x2A,
-	0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF, 0x16, 0x00,
-	0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48,
-	0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3,
-	0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03,
-	0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC,
-	0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D,
-	0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00,
-	0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
-	0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
-	0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0x00,
-	0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03,
-	0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C,
-	0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0x1D, 0x00,
-	0x8A, 0xFF, 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6,
-	0x02, 0xF2, 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE,
-	0x1E, 0x01, 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAC,
-	0xFF, 0xAE, 0x00, 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD,
-	0xFD, 0x47, 0x0E, 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C,
-	0x01, 0x61, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF,
-	0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B,
-	0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01,
-	0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
-	0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
-	0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF,
-	0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52,
-	0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1C, 0x00, 0x86, 0xFF, 0x59,
-	0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1, 0x04, 0x37, 0xF3, 0x28,
-	0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x41, 0xFF, 0x33,
-	0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01,
-	0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E,
-	0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00,
-	0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37,
-	0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1,
-	0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE,
-	0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC,
-	0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F,
-	0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00,
-	0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
-	0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
-	0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0xFF,
-	0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05,
-	0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE,
-	0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00,
-	0x28, 0x00, 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8,
-	0xF9, 0x0E, 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01,
-	0x05, 0xFF, 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x20,
-	0x00, 0x7F, 0xFF, 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC,
-	0x9B, 0x04, 0xF2, 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50,
-	0xFE, 0x04, 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0x17, 0x00, 0xA1, 0xFF,
-	0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70,
-	0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01,
-	0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
-	0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
-	0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
-	0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00,
-	0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B,
-	0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xD4, 0xFF, 0xBF,
-	0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3, 0x98, 0x3E, 0xF3, 0x1E,
-	0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF, 0x39, 0x01,
-	0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0, 0x26, 0x4B,
-	0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF, 0x35, 0x00,
-	0xFD, 0xFF, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90,
-	0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1,
-	0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD,
-	0xFF, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC,
-	0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB,
-	0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF,
-	0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
-	0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
-	0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06,
-	0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49,
-	0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFF, 0xFF,
-	0x32, 0x00, 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E,
-	0xF6, 0x68, 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF,
-	0xEA, 0xFF, 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x2B,
-	0x00, 0x59, 0xFF, 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8,
-	0x2D, 0x0D, 0x69, 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C,
-	0xFF, 0x93, 0x00, 0xB6, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00,
-	0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83,
-	0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE,
-	0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
-	0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
-	0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
-	0xFF, 0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00,
-	0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7,
-	0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF,
-	0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD9, 0xFF, 0x37, 0x00, 0xF7,
-	0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7, 0x53, 0x44, 0xFB, 0x14,
-	0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE, 0x01, 0x42, 0xFF, 0x32,
-	0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF, 0x93, 0x00,
-	0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94, 0x1C, 0x47,
-	0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57,
-	0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2,
-	0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC,
-	0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29,
-	0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
-	0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
-	0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
-	0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07,
-	0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C,
-	0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB,
-	0xF3, 0x5B, 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD,
-	0xB4, 0x00, 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33,
-	0x00, 0x3E, 0xFF, 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5,
-	0xB6, 0x16, 0x77, 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D,
-	0x00, 0x25, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
-	0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59,
-	0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF,
-	0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x25, 0x00, 0x6C,
-	0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
-	0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
-	0x00, 0x9E, 0xFF, 0x17, 0x00, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00,
-	0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13,
-	0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF,
-	0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAE, 0xFF, 0xA7, 0x00, 0x12,
-	0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD, 0xDC, 0x47, 0x95, 0x0B,
-	0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71, 0x01, 0x5F, 0xFF, 0x29,
-	0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00, 0xC3, 0xFF,
-	0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2, 0x12, 0x19,
-	0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF, 0x30, 0x00,
-	0xFF, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85,
-	0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4,
-	0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE,
-	0xFF, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD,
-	0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6,
-	0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
-	0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
-	0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07,
-	0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78,
-	0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-	0x34, 0x00, 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E,
-	0xF2, 0x60, 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC,
-	0x51, 0x01, 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3,
-	0xBA, 0x20, 0x61, 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE,
-	0x00, 0xC5, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C,
-	0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00,
-	0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
-	0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
-	0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
-	0x00, 0xCB, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF,
-	0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D,
-	0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00,
-	0xA9, 0xFF, 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x82, 0xFF, 0x18,
-	0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC, 0x24, 0x04, 0xF5, 0x48,
-	0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42, 0xFE, 0x0B, 0x01, 0x87,
-	0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00, 0xDB, 0xFE,
-	0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81, 0x09, 0x61,
-	0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF, 0x26, 0x00,
-	0x00, 0x00, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06,
-	0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7,
-	0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF,
-	0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE,
-	0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00,
-	0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF,
-	0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
-	0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
-	0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-	0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06,
-	0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33,
-	0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-	0x28, 0x00, 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E,
-	0xF1, 0xE3, 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC,
-	0xB7, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x32,
-	0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1,
-	0xAE, 0x2A, 0x86, 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E,
-	0x01, 0x7B, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18,
-	0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01,
-	0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-	0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
-	0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
-	0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF,
-	0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC,
-	0x44, 0x14, 0xF8, 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00,
-	0xD5, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B, 0xFF, 0x7C,
-	0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9, 0xA4, 0x0C, 0x90, 0x47,
-	0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E, 0xFF, 0x99, 0x00, 0xB3,
-	0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF, 0x31, 0x01,
-	0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB, 0x48, 0x73,
-	0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00, 0x91, 0xFF,
-	0x1B, 0x00, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB,
-	0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB,
-	0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00,
-	0x00, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00,
-	0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1,
-	0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF,
-	0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
-	0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
-	0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x04,
-	0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04,
-	0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55,
-	0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00,
-	0x11, 0x00, 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74,
-	0xF2, 0x54, 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC,
-	0xE4, 0x01, 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x23,
-	0x00, 0x71, 0xFF, 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1,
-	0xFD, 0x33, 0x62, 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7,
-	0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2,
-	0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01,
-	0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
-	0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
-	0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
-	0xFF, 0x13, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E,
-	0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF,
-	0xFB, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC5,
-	0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6, 0x22, 0x16, 0xC3, 0x43,
-	0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11, 0x00, 0x2B, 0x00, 0xDE,
-	0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x90, 0x01,
-	0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1, 0x46, 0xE1,
-	0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00, 0xBE, 0xFF,
-	0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC,
-	0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF,
-	0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18,
-	0x00, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02,
-	0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8,
-	0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00,
-	0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
-	0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
-	0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x0B,
-	0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02,
-	0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF,
-	0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x05, 0x00,
-	0xF0, 0xFF, 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F,
-	0xF5, 0x32, 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC,
-	0xDA, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
-	0x00, 0xB6, 0xFF, 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2,
-	0x1C, 0x3C, 0x81, 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1E, 0x00,
-	0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06,
-	0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
-	0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
-	0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
-	0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
-	0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF,
-	0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE,
-	0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF,
-	0x19, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6,
-	0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3, 0x22, 0x20, 0xCA, 0x3D,
-	0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4, 0x00, 0xCA, 0xFF, 0x03,
-	0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01,
-	0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89, 0x42, 0x02,
-	0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00, 0xE8, 0xFF,
-	0x07, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6,
-	0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9,
-	0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E,
-	0x00, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD,
-	0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B,
-	0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00,
-	0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
-	0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
-	0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00,
-	0x00, 0xF4, 0xFF, 0x1A, 0x00, 0xFF, 0x00, 0x07, 0x03, 0x16, 0x06,
-	0x7C, 0x09, 0x2A, 0x0C, 0x2E, 0x0D, 0x2A, 0x0C, 0x7C, 0x09, 0x16,
-	0x06, 0x07, 0x03, 0xFF, 0x00, 0x1A, 0x00, 0xF4, 0xFF, 0xF2, 0xFF,
-	0xA0, 0xFF, 0x71, 0xFF, 0x71, 0x00, 0x86, 0x03, 0x73, 0x08, 0x88,
-	0x0D, 0x78, 0x10, 0xC9, 0x0F, 0xD5, 0x0B, 0x8B, 0x06, 0x28, 0x02,
-	0xDF, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDC,
-	0xFF, 0x80, 0xFF, 0x9A, 0xFF, 0x46, 0x01, 0x1E, 0x05, 0x5A, 0x0A,
-	0xED, 0x0E, 0xAA, 0x10, 0xAF, 0x0E, 0xFD, 0x09, 0xCB, 0x04, 0x18,
-	0x01, 0x8E, 0xFF, 0x85, 0xFF, 0xE1, 0xFF, 0xFC, 0xFF, 0xBD, 0xFF,
-	0x6D, 0xFF, 0xF6, 0xFF, 0x65, 0x02, 0xE5, 0x06, 0x2B, 0x0C, 0xF3,
-	0x0F, 0x60, 0x10, 0x3B, 0x0D, 0x16, 0x08, 0x3F, 0x03, 0x50, 0x00,
-	0x6E, 0xFF, 0xA7, 0xFF, 0xF5, 0xFF, 0xEF, 0xFF, 0x9A, 0xFF, 0x75,
-	0xFF, 0x91, 0x00, 0xC9, 0x03, 0xC8, 0x08, 0xCC, 0x0D, 0x89, 0x10,
-	0x9F, 0x0F, 0x85, 0x0B, 0x3B, 0x06, 0xF4, 0x01, 0xCD, 0xFF, 0x72,
-	0xFF, 0xC9, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0x7B, 0xFF,
-	0xA5, 0xFF, 0x73, 0x01, 0x6A, 0x05, 0xAD, 0x0A, 0x21, 0x0F, 0xA6,
-	0x10, 0x74, 0x0E, 0xA9, 0x09, 0x83, 0x04, 0xF0, 0x00, 0x85, 0xFF,
-	0x8B, 0xFF, 0xE5, 0xFF, 0xFA, 0xFF, 0xB7, 0xFF, 0x6C, 0xFF, 0x0C,
-	0x00, 0x9D, 0x02, 0x37, 0x07, 0x78, 0x0C, 0x15, 0x10, 0x47, 0x10,
-	0xF3, 0x0C, 0xC2, 0x07, 0x01, 0x03, 0x35, 0x00, 0x6D, 0xFF, 0xAD,
-	0xFF, 0xF7, 0xFF, 0xEB, 0xFF, 0x94, 0xFF, 0x7A, 0xFF, 0xB3, 0x00,
-	0x0D, 0x04, 0x1C, 0x09, 0x0D, 0x0E, 0x97, 0x10, 0x73, 0x0F, 0x35,
-	0x0B, 0xEB, 0x05, 0xC1, 0x01, 0xBD, 0xFF, 0x75, 0xFF, 0xCE, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x77, 0xFF, 0xB3, 0xFF, 0xA1,
-	0x01, 0xB7, 0x05, 0xFF, 0x0A, 0x53, 0x0F, 0x9E, 0x10, 0x37, 0x0E,
-	0x55, 0x09, 0x3B, 0x04, 0xCB, 0x00, 0x7E, 0xFF, 0x90, 0xFF, 0xE9,
-	0xFF, 0xF8, 0xFF, 0xB1, 0xFF, 0x6C, 0xFF, 0x24, 0x00, 0xD8, 0x02,
-	0x8A, 0x07, 0xC2, 0x0C, 0x34, 0x10, 0x2A, 0x10, 0xAA, 0x0C, 0x6F,
-	0x07, 0xC4, 0x02, 0x1C, 0x00, 0x6C, 0xFF, 0xB3, 0xFF, 0xF9, 0xFF,
-	0xE8, 0xFF, 0x8E, 0xFF, 0x80, 0xFF, 0xD7, 0x00, 0x53, 0x04, 0x71,
-	0x09, 0x4C, 0x0E, 0xA1, 0x10, 0x43, 0x0F, 0xE3, 0x0A, 0x9D, 0x05,
-	0x91, 0x01, 0xAE, 0xFF, 0x79, 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF,
-	0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC2, 0xFF, 0xD2, 0x01, 0x06, 0x06,
-	0x50, 0x0B, 0x82, 0x0F, 0x93, 0x10, 0xF8, 0x0D, 0x00, 0x09, 0xF6,
-	0x03, 0xA7, 0x00, 0x78, 0xFF, 0x96, 0xFF, 0xEC, 0xFF, 0xF6, 0xFF,
-	0xAB, 0xFF, 0x6D, 0xFF, 0x3E, 0x00, 0x15, 0x03, 0xDE, 0x07, 0x0B,
-	0x0D, 0x50, 0x10, 0x0A, 0x10, 0x5E, 0x0C, 0x1C, 0x07, 0x8A, 0x02,
-	0x04, 0x00, 0x6C, 0xFF, 0xB9, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF, 0x89,
-	0xFF, 0x88, 0xFF, 0xFD, 0x00, 0x9B, 0x04, 0xC5, 0x09, 0x88, 0x0E,
-	0xA8, 0x10, 0x10, 0x0F, 0x91, 0x0A, 0x50, 0x05, 0x64, 0x01, 0xA1,
-	0xFF, 0x7D, 0xFF, 0xD9, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF,
-	0x71, 0xFF, 0xD3, 0xFF, 0x05, 0x02, 0x55, 0x06, 0xA0, 0x0B, 0xAD,
-	0x0F, 0x84, 0x10, 0xB6, 0x0D, 0xAC, 0x08, 0xB3, 0x03, 0x86, 0x00,
-	0x74, 0xFF, 0x9C, 0xFF, 0xF0, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF, 0x6F,
-	0xFF, 0x5A, 0x00, 0x54, 0x03, 0x32, 0x08, 0x52, 0x0D, 0x68, 0x10,
-	0xE6, 0x0F, 0x11, 0x0C, 0xCA, 0x06, 0x52, 0x02, 0xEF, 0xFF, 0x6E,
-	0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xDF, 0xFF, 0x84, 0xFF, 0x91, 0xFF,
-	0x25, 0x01, 0xE4, 0x04, 0x19, 0x0A, 0xC2, 0x0E, 0xAA, 0x10, 0xDA,
-	0x0E, 0x3E, 0x0A, 0x05, 0x05, 0x38, 0x01, 0x96, 0xFF, 0x81, 0xFF,
-	0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE6,
-	0xFF, 0x3A, 0x02, 0xA6, 0x06, 0xEF, 0x0B, 0xD6, 0x0F, 0x71, 0x10,
-	0x71, 0x0D, 0x57, 0x08, 0x71, 0x03, 0x67, 0x00, 0x70, 0xFF, 0xA2,
-	0xFF, 0xF3, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x78, 0x00,
-	0x95, 0x03, 0x86, 0x08, 0x98, 0x0D, 0x7C, 0x10, 0xC0, 0x0F, 0xC3,
-	0x0B, 0x79, 0x06, 0x1C, 0x02, 0xDB, 0xFF, 0x70, 0xFF, 0xC5, 0xFF,
-	0xFE, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9C, 0xFF, 0x50,
-	0x01, 0x2F, 0x05, 0x6C, 0x0A, 0xF9, 0x0E, 0xA9, 0x10, 0xA2, 0x0E,
-	0xEA, 0x09, 0xBB, 0x04, 0x0F, 0x01, 0x8C, 0xFF, 0x87, 0xFF, 0xE2,
-	0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xFA, 0xFF, 0x71, 0x02,
-	0xF7, 0x06, 0x3C, 0x0C, 0xFB, 0x0F, 0x5B, 0x10, 0x2B, 0x0D, 0x03,
-	0x08, 0x31, 0x03, 0x4A, 0x00, 0x6E, 0xFF, 0xA8, 0xFF, 0xF5, 0xFF,
-	0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x98, 0x00, 0xD8, 0x03, 0xDB,
-	0x08, 0xDB, 0x0D, 0x8D, 0x10, 0x96, 0x0F, 0x73, 0x0B, 0x29, 0x06,
-	0xE8, 0x01, 0xC9, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF, 0x00,
-	0x00, 0xD6, 0xFF, 0x7A, 0xFF, 0xA8, 0xFF, 0x7D, 0x01, 0x7B, 0x05,
-	0xBF, 0x0A, 0x2D, 0x0F, 0xA5, 0x10, 0x67, 0x0E, 0x96, 0x09, 0x73,
-	0x04, 0xE7, 0x00, 0x84, 0xFF, 0x8C, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF,
-	0xB6, 0xFF, 0x6C, 0xFF, 0x11, 0x00, 0xAA, 0x02, 0x4A, 0x07, 0x88,
-	0x0C, 0x1C, 0x10, 0x41, 0x10, 0xE3, 0x0C, 0xAF, 0x07, 0xF3, 0x02,
-	0x2F, 0x00, 0x6C, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEA, 0xFF, 0x93,
-	0xFF, 0x7B, 0xFF, 0xBB, 0x00, 0x1C, 0x04, 0x2F, 0x09, 0x1B, 0x0E,
-	0x9A, 0x10, 0x68, 0x0F, 0x23, 0x0B, 0xDA, 0x05, 0xB7, 0x01, 0xB9,
-	0xFF, 0x76, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1, 0xFF,
-	0x76, 0xFF, 0xB6, 0xFF, 0xAC, 0x01, 0xC8, 0x05, 0x11, 0x0B, 0x5E,
-	0x0F, 0x9C, 0x10, 0x29, 0x0E, 0x42, 0x09, 0x2C, 0x04, 0xC2, 0x00,
-	0x7D, 0xFF, 0x92, 0xFF, 0xEA, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF, 0x6C,
-	0xFF, 0x29, 0x00, 0xE6, 0x02, 0x9D, 0x07, 0xD3, 0x0C, 0x3B, 0x10,
-	0x23, 0x10, 0x99, 0x0C, 0x5C, 0x07, 0xB7, 0x02, 0x16, 0x00, 0x6C,
-	0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8D, 0xFF, 0x82, 0xFF,
-	0xDF, 0x00, 0x63, 0x04, 0x84, 0x09, 0x59, 0x0E, 0xA3, 0x10, 0x38,
-	0x0F, 0xD1, 0x0A, 0x8C, 0x05, 0x87, 0x01, 0xAB, 0xFF, 0x79, 0xFF,
-	0xD5, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC6,
-	0xFF, 0xDD, 0x01, 0x17, 0x06, 0x62, 0x0B, 0x8C, 0x0F, 0x90, 0x10,
-	0xE9, 0x0D, 0xED, 0x08, 0xE7, 0x03, 0xA0, 0x00, 0x77, 0xFF, 0x97,
-	0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xA9, 0xFF, 0x6D, 0xFF, 0x44, 0x00,
-	0x23, 0x03, 0xF1, 0x07, 0x1B, 0x0D, 0x55, 0x10, 0x02, 0x10, 0x4D,
-	0x0C, 0x0A, 0x07, 0x7E, 0x02, 0xFF, 0xFF, 0x6D, 0xFF, 0xBA, 0xFF,
-	0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x8A, 0xFF, 0x06, 0x01, 0xAB,
-	0x04, 0xD8, 0x09, 0x95, 0x0E, 0xA9, 0x10, 0x05, 0x0F, 0x7F, 0x0A,
-	0x40, 0x05, 0x5A, 0x01, 0x9F, 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00,
-	0x00, 0xFE, 0xFF, 0xC6, 0xFF, 0x70, 0xFF, 0xD7, 0xFF, 0x10, 0x02,
-	0x67, 0x06, 0xB1, 0x0B, 0xB7, 0x0F, 0x80, 0x10, 0xA7, 0x0D, 0x99,
-	0x08, 0xA4, 0x03, 0x7F, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0, 0xFF,
-	0xF3, 0xFF, 0xA3, 0xFF, 0x70, 0xFF, 0x60, 0x00, 0x62, 0x03, 0x45,
-	0x08, 0x62, 0x0D, 0x6C, 0x10, 0xDE, 0x0F, 0x00, 0x0C, 0xB8, 0x06,
-	0x46, 0x02, 0xEA, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFD, 0xFF, 0x00,
-	0x00, 0xDE, 0xFF, 0x83, 0xFF, 0x94, 0xFF, 0x2F, 0x01, 0xF4, 0x04,
-	0x2B, 0x0A, 0xCE, 0x0E, 0xAA, 0x10, 0xCE, 0x0E, 0x2B, 0x0A, 0xF4,
-	0x04, 0x2F, 0x01, 0x94, 0xFF, 0x83, 0xFF, 0xDE, 0xFF, 0xFD, 0xFF,
-	0xC0, 0xFF, 0x6E, 0xFF, 0xEA, 0xFF, 0x46, 0x02, 0xB8, 0x06, 0x00,
-	0x0C, 0xDE, 0x0F, 0x6C, 0x10, 0x62, 0x0D, 0x45, 0x08, 0x62, 0x03,
-	0x60, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D,
-	0xFF, 0x73, 0xFF, 0x7F, 0x00, 0xA4, 0x03, 0x99, 0x08, 0xA7, 0x0D,
-	0x80, 0x10, 0xB7, 0x0F, 0xB1, 0x0B, 0x67, 0x06, 0x10, 0x02, 0xD7,
-	0xFF, 0x70, 0xFF, 0xC6, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA, 0xFF,
-	0x7E, 0xFF, 0x9F, 0xFF, 0x5A, 0x01, 0x40, 0x05, 0x7F, 0x0A, 0x05,
-	0x0F, 0xA9, 0x10, 0x95, 0x0E, 0xD8, 0x09, 0xAB, 0x04, 0x06, 0x01,
-	0x8A, 0xFF, 0x88, 0xFF, 0xE3, 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D,
-	0xFF, 0xFF, 0xFF, 0x7E, 0x02, 0x0A, 0x07, 0x4D, 0x0C, 0x02, 0x10,
-	0x55, 0x10, 0x1B, 0x0D, 0xF1, 0x07, 0x23, 0x03, 0x44, 0x00, 0x6D,
-	0xFF, 0xA9, 0xFF, 0xF6, 0xFF, 0xED, 0xFF, 0x97, 0xFF, 0x77, 0xFF,
-	0xA0, 0x00, 0xE7, 0x03, 0xED, 0x08, 0xE9, 0x0D, 0x90, 0x10, 0x8C,
-	0x0F, 0x62, 0x0B, 0x17, 0x06, 0xDD, 0x01, 0xC6, 0xFF, 0x73, 0xFF,
-	0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x79, 0xFF, 0xAB,
-	0xFF, 0x87, 0x01, 0x8C, 0x05, 0xD1, 0x0A, 0x38, 0x0F, 0xA3, 0x10,
-	0x59, 0x0E, 0x84, 0x09, 0x63, 0x04, 0xDF, 0x00, 0x82, 0xFF, 0x8D,
-	0xFF, 0xE7, 0xFF, 0xF9, 0xFF, 0xB4, 0xFF, 0x6C, 0xFF, 0x16, 0x00,
-	0xB7, 0x02, 0x5C, 0x07, 0x99, 0x0C, 0x23, 0x10, 0x3B, 0x10, 0xD3,
-	0x0C, 0x9D, 0x07, 0xE6, 0x02, 0x29, 0x00, 0x6C, 0xFF, 0xB0, 0xFF,
-	0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7D, 0xFF, 0xC2, 0x00, 0x2C,
-	0x04, 0x42, 0x09, 0x29, 0x0E, 0x9C, 0x10, 0x5E, 0x0F, 0x11, 0x0B,
-	0xC8, 0x05, 0xAC, 0x01, 0xB6, 0xFF, 0x76, 0xFF, 0xD1, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB9, 0xFF, 0xB7, 0x01,
-	0xDA, 0x05, 0x23, 0x0B, 0x68, 0x0F, 0x9A, 0x10, 0x1B, 0x0E, 0x2F,
-	0x09, 0x1C, 0x04, 0xBB, 0x00, 0x7B, 0xFF, 0x93, 0xFF, 0xEA, 0xFF,
-	0xF7, 0xFF, 0xAE, 0xFF, 0x6C, 0xFF, 0x2F, 0x00, 0xF3, 0x02, 0xAF,
-	0x07, 0xE3, 0x0C, 0x41, 0x10, 0x1C, 0x10, 0x88, 0x0C, 0x4A, 0x07,
-	0xAA, 0x02, 0x11, 0x00, 0x6C, 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE6,
-	0xFF, 0x8C, 0xFF, 0x84, 0xFF, 0xE7, 0x00, 0x73, 0x04, 0x96, 0x09,
-	0x67, 0x0E, 0xA5, 0x10, 0x2D, 0x0F, 0xBF, 0x0A, 0x7B, 0x05, 0x7D,
-	0x01, 0xA8, 0xFF, 0x7A, 0xFF, 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
-	0xCA, 0xFF, 0x72, 0xFF, 0xC9, 0xFF, 0xE8, 0x01, 0x29, 0x06, 0x73,
-	0x0B, 0x96, 0x0F, 0x8D, 0x10, 0xDB, 0x0D, 0xDB, 0x08, 0xD8, 0x03,
-	0x98, 0x00, 0x76, 0xFF, 0x99, 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA8,
-	0xFF, 0x6E, 0xFF, 0x4A, 0x00, 0x31, 0x03, 0x03, 0x08, 0x2B, 0x0D,
-	0x5B, 0x10, 0xFB, 0x0F, 0x3C, 0x0C, 0xF7, 0x06, 0x71, 0x02, 0xFA,
-	0xFF, 0x6D, 0xFF, 0xBC, 0xFF, 0xFC, 0xFF, 0xE2, 0xFF, 0x87, 0xFF,
-	0x8C, 0xFF, 0x0F, 0x01, 0xBB, 0x04, 0xEA, 0x09, 0xA2, 0x0E, 0xA9,
-	0x10, 0xF9, 0x0E, 0x6C, 0x0A, 0x2F, 0x05, 0x50, 0x01, 0x9C, 0xFF,
-	0x7F, 0xFF, 0xDB, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF, 0x70,
-	0xFF, 0xDB, 0xFF, 0x1C, 0x02, 0x79, 0x06, 0xC3, 0x0B, 0xC0, 0x0F,
-	0x7C, 0x10, 0x98, 0x0D, 0x86, 0x08, 0x95, 0x03, 0x78, 0x00, 0x72,
-	0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA2, 0xFF, 0x70, 0xFF,
-	0x67, 0x00, 0x71, 0x03, 0x57, 0x08, 0x71, 0x0D, 0x71, 0x10, 0xD6,
-	0x0F, 0xEF, 0x0B, 0xA6, 0x06, 0x3A, 0x02, 0xE6, 0xFF, 0x6E, 0xFF,
-	0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x96,
-	0xFF, 0x38, 0x01, 0x05, 0x05, 0x3E, 0x0A, 0xDA, 0x0E, 0xAA, 0x10,
-	0xC2, 0x0E, 0x19, 0x0A, 0xE4, 0x04, 0x25, 0x01, 0x91, 0xFF, 0x84,
-	0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xBF, 0xFF, 0x6E, 0xFF, 0xEF, 0xFF,
-	0x52, 0x02, 0xCA, 0x06, 0x11, 0x0C, 0xE6, 0x0F, 0x68, 0x10, 0x52,
-	0x0D, 0x32, 0x08, 0x54, 0x03, 0x5A, 0x00, 0x6F, 0xFF, 0xA5, 0xFF,
-	0xF4, 0xFF, 0xF0, 0xFF, 0x9C, 0xFF, 0x74, 0xFF, 0x86, 0x00, 0xB3,
-	0x03, 0xAC, 0x08, 0xB6, 0x0D, 0x84, 0x10, 0xAD, 0x0F, 0xA0, 0x0B,
-	0x55, 0x06, 0x05, 0x02, 0xD3, 0xFF, 0x71, 0xFF, 0xC7, 0xFF, 0xFE,
-	0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA1, 0xFF, 0x64, 0x01,
-	0x50, 0x05, 0x91, 0x0A, 0x10, 0x0F, 0xA8, 0x10, 0x88, 0x0E, 0xC5,
-	0x09, 0x9B, 0x04, 0xFD, 0x00, 0x88, 0xFF, 0x89, 0xFF, 0xE4, 0xFF,
-	0xFB, 0xFF, 0xB9, 0xFF, 0x6C, 0xFF, 0x04, 0x00, 0x8A, 0x02, 0x1C,
-	0x07, 0x5E, 0x0C, 0x0A, 0x10, 0x50, 0x10, 0x0B, 0x0D, 0xDE, 0x07,
-	0x15, 0x03, 0x3E, 0x00, 0x6D, 0xFF, 0xAB, 0xFF, 0xF6, 0xFF, 0xEC,
-	0xFF, 0x96, 0xFF, 0x78, 0xFF, 0xA7, 0x00, 0xF6, 0x03, 0x00, 0x09,
-	0xF8, 0x0D, 0x93, 0x10, 0x82, 0x0F, 0x50, 0x0B, 0x06, 0x06, 0xD2,
-	0x01, 0xC2, 0xFF, 0x74, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
-	0xD4, 0xFF, 0x79, 0xFF, 0xAE, 0xFF, 0x91, 0x01, 0x9D, 0x05, 0xE3,
-	0x0A, 0x43, 0x0F, 0xA1, 0x10, 0x4C, 0x0E, 0x71, 0x09, 0x53, 0x04,
-	0xD7, 0x00, 0x80, 0xFF, 0x8E, 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB3,
-	0xFF, 0x6C, 0xFF, 0x1C, 0x00, 0xC4, 0x02, 0x6F, 0x07, 0xAA, 0x0C,
-	0x2A, 0x10, 0x34, 0x10, 0xC2, 0x0C, 0x8A, 0x07, 0xD8, 0x02, 0x24,
-	0x00, 0x6C, 0xFF, 0xB1, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x90, 0xFF,
-	0x7E, 0xFF, 0xCB, 0x00, 0x3B, 0x04, 0x55, 0x09, 0x37, 0x0E, 0x9E,
-	0x10, 0x53, 0x0F, 0xFF, 0x0A, 0xB7, 0x05, 0xA1, 0x01, 0xB3, 0xFF,
-	0x77, 0xFF, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x75,
-	0xFF, 0xBD, 0xFF, 0xC1, 0x01, 0xEB, 0x05, 0x35, 0x0B, 0x73, 0x0F,
-	0x97, 0x10, 0x0D, 0x0E, 0x1C, 0x09, 0x0D, 0x04, 0xB3, 0x00, 0x7A,
-	0xFF, 0x94, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAD, 0xFF, 0x6D, 0xFF,
-	0x35, 0x00, 0x01, 0x03, 0xC2, 0x07, 0xF3, 0x0C, 0x47, 0x10, 0x15,
-	0x10, 0x78, 0x0C, 0x37, 0x07, 0x9D, 0x02, 0x0C, 0x00, 0x6C, 0xFF,
-	0xB7, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF, 0xF0,
-	0x00, 0x83, 0x04, 0xA9, 0x09, 0x74, 0x0E, 0xA6, 0x10, 0x21, 0x0F,
-	0xAD, 0x0A, 0x6A, 0x05, 0x73, 0x01, 0xA5, 0xFF, 0x7B, 0xFF, 0xD7,
-	0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC9, 0xFF, 0x72, 0xFF, 0xCD, 0xFF,
-	0xF4, 0x01, 0x3B, 0x06, 0x85, 0x0B, 0x9F, 0x0F, 0x89, 0x10, 0xCC,
-	0x0D, 0xC8, 0x08, 0xC9, 0x03, 0x91, 0x00, 0x75, 0xFF, 0x9A, 0xFF,
-	0xEF, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x50, 0x00, 0x3F,
-	0x03, 0x16, 0x08, 0x3B, 0x0D, 0x60, 0x10, 0xF3, 0x0F, 0x2B, 0x0C,
-	0xE5, 0x06, 0x65, 0x02, 0xF6, 0xFF, 0x6D, 0xFF, 0xBD, 0xFF, 0xFC,
-	0xFF, 0xE1, 0xFF, 0x85, 0xFF, 0x8E, 0xFF, 0x18, 0x01, 0xCB, 0x04,
-	0xFD, 0x09, 0xAF, 0x0E, 0xAA, 0x10, 0xED, 0x0E, 0x5A, 0x0A, 0x1E,
-	0x05, 0x46, 0x01, 0x9A, 0xFF, 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00,
-	0xFD, 0xFF, 0xC3, 0xFF, 0x6F, 0xFF, 0xDF, 0xFF, 0x28, 0x02, 0x8B,
-	0x06, 0xD5, 0x0B, 0xC9, 0x0F, 0x78, 0x10, 0x88, 0x0D, 0x73, 0x08,
-	0x86, 0x03, 0x71, 0x00, 0x71, 0xFF, 0xA0, 0xFF, 0xF2, 0xFF, 0xF2,
-	0xFF, 0xA1, 0xFF, 0x71, 0xFF, 0x6E, 0x00, 0x7F, 0x03, 0x6A, 0x08,
-	0x81, 0x0D, 0x76, 0x10, 0xCD, 0x0F, 0xDD, 0x0B, 0x94, 0x06, 0x2E,
-	0x02, 0xE1, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
-	0xDC, 0xFF, 0x80, 0xFF, 0x98, 0xFF, 0x42, 0x01, 0x16, 0x05, 0x50,
-	0x0A, 0xE7, 0x0E, 0xAA, 0x10, 0xB5, 0x0E, 0x06, 0x0A, 0xD3, 0x04,
-	0x1C, 0x01, 0x8F, 0xFF, 0x85, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF, 0xBE,
-	0xFF, 0x6D, 0xFF, 0xF3, 0xFF, 0x5E, 0x02, 0xDC, 0x06, 0x23, 0x0C,
-	0xEF, 0x0F, 0x63, 0x10, 0x43, 0x0D, 0x1F, 0x08, 0x46, 0x03, 0x53,
-	0x00, 0x6E, 0xFF, 0xA6, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B, 0xFF,
-	0x75, 0xFF, 0x8D, 0x00, 0xC1, 0x03, 0xBE, 0x08, 0xC4, 0x0D, 0x88,
-	0x10, 0xA4, 0x0F, 0x8E, 0x0B, 0x43, 0x06, 0xF9, 0x01, 0xCF, 0xFF,
-	0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF, 0x7C,
-	0xFF, 0xA4, 0xFF, 0x6E, 0x01, 0x61, 0x05, 0xA3, 0x0A, 0x1C, 0x0F,
-	0xA7, 0x10, 0x7B, 0x0E, 0xB2, 0x09, 0x8B, 0x04, 0xF4, 0x00, 0x86,
-	0xFF, 0x8A, 0xFF, 0xE4, 0xFF, 0xFA, 0xFF, 0xB8, 0xFF, 0x6C, 0xFF,
-	0x09, 0x00, 0x97, 0x02, 0x2E, 0x07, 0x6F, 0x0C, 0x11, 0x10, 0x4A,
-	0x10, 0xFB, 0x0C, 0xCB, 0x07, 0x07, 0x03, 0x38, 0x00, 0x6D, 0xFF,
-	0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF, 0xAF,
-	0x00, 0x05, 0x04, 0x13, 0x09, 0x06, 0x0E, 0x96, 0x10, 0x78, 0x0F,
-	0x3E, 0x0B, 0xF4, 0x05, 0xC7, 0x01, 0xBF, 0xFF, 0x74, 0xFF, 0xCE,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x78, 0xFF, 0xB1, 0xFF,
-	0x9C, 0x01, 0xAE, 0x05, 0xF6, 0x0A, 0x4E, 0x0F, 0x9F, 0x10, 0x3E,
-	0x0E, 0x5E, 0x09, 0x43, 0x04, 0xCF, 0x00, 0x7F, 0xFF, 0x90, 0xFF,
-	0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x21, 0x00, 0xD2,
-	0x02, 0x81, 0x07, 0xBA, 0x0C, 0x31, 0x10, 0x2E, 0x10, 0xB2, 0x0C,
-	0x78, 0x07, 0xCB, 0x02, 0x1E, 0x00, 0x6C, 0xFF, 0xB2, 0xFF, 0xF9,
-	0xFF, 0xE8, 0xFF, 0x8F, 0xFF, 0x80, 0xFF, 0xD3, 0x00, 0x4B, 0x04,
-	0x67, 0x09, 0x45, 0x0E, 0xA0, 0x10, 0x48, 0x0F, 0xEC, 0x0A, 0xA6,
-	0x05, 0x97, 0x01, 0xB0, 0xFF, 0x78, 0xFF, 0xD3, 0xFF, 0x00, 0x00,
-	0xFF, 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC0, 0xFF, 0xCC, 0x01, 0xFD,
-	0x05, 0x47, 0x0B, 0x7D, 0x0F, 0x94, 0x10, 0xFF, 0x0D, 0x0A, 0x09,
-	0xFE, 0x03, 0xAB, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF, 0xF7,
-	0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x3B, 0x00, 0x0E, 0x03, 0xD5, 0x07,
-	0x03, 0x0D, 0x4D, 0x10, 0x0E, 0x10, 0x67, 0x0C, 0x25, 0x07, 0x91,
-	0x02, 0x07, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF,
-	0x89, 0xFF, 0x87, 0xFF, 0xF9, 0x00, 0x93, 0x04, 0xBC, 0x09, 0x82,
-	0x0E, 0xA7, 0x10, 0x16, 0x0F, 0x9A, 0x0A, 0x59, 0x05, 0x69, 0x01,
-	0xA3, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC8,
-	0xFF, 0x71, 0xFF, 0xD1, 0xFF, 0xFF, 0x01, 0x4C, 0x06, 0x97, 0x0B,
-	0xA9, 0x0F, 0x86, 0x10, 0xBD, 0x0D, 0xB5, 0x08, 0xBA, 0x03, 0x8A,
-	0x00, 0x74, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF,
-	0x6F, 0xFF, 0x57, 0x00, 0x4D, 0x03, 0x29, 0x08, 0x4B, 0x0D, 0x65,
-	0x10, 0xEB, 0x0F, 0x1A, 0x0C, 0xD3, 0x06, 0x58, 0x02, 0xF1, 0xFF,
-	0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x84, 0xFF, 0x90,
-	0xFF, 0x21, 0x01, 0xDC, 0x04, 0x10, 0x0A, 0xBB, 0x0E, 0xAA, 0x10,
-	0xE1, 0x0E, 0x47, 0x0A, 0x0D, 0x05, 0x3D, 0x01, 0x97, 0xFF, 0x81,
-	0xFF, 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC2, 0xFF, 0x6F, 0xFF,
-	0xE4, 0xFF, 0x34, 0x02, 0x9D, 0x06, 0xE6, 0x0B, 0xD1, 0x0F, 0x73,
-	0x10, 0x79, 0x0D, 0x61, 0x08, 0x78, 0x03, 0x6A, 0x00, 0x70, 0xFF,
-	0xA1, 0xFF, 0xF2, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x74,
-	0x00, 0x8E, 0x03, 0x7D, 0x08, 0x90, 0x0D, 0x7A, 0x10, 0xC4, 0x0F,
-	0xCC, 0x0B, 0x82, 0x06, 0x22, 0x02, 0xDD, 0xFF, 0x6F, 0xFF, 0xC4,
-	0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9B, 0xFF,
-	0x4B, 0x01, 0x26, 0x05, 0x63, 0x0A, 0xF3, 0x0E, 0xAA, 0x10, 0xA8,
-	0x0E, 0xF4, 0x09, 0xC3, 0x04, 0x13, 0x01, 0x8D, 0xFF, 0x86, 0xFF,
-	0xE1, 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xF8, 0xFF, 0x6B,
-	0x02, 0xEE, 0x06, 0x34, 0x0C, 0xF7, 0x0F, 0x5D, 0x10, 0x33, 0x0D,
-	0x0D, 0x08, 0x38, 0x03, 0x4D, 0x00, 0x6E, 0xFF, 0xA7, 0xFF, 0xF5,
-	0xFF, 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x94, 0x00, 0xD0, 0x03,
-	0xD1, 0x08, 0xD3, 0x0D, 0x8B, 0x10, 0x9A, 0x0F, 0x7C, 0x0B, 0x32,
-	0x06, 0xEE, 0x01, 0xCB, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF,
-	0x00, 0x00, 0xD6, 0xFF, 0x7B, 0xFF, 0xA7, 0xFF, 0x78, 0x01, 0x72,
-	0x05, 0xB6, 0x0A, 0x27, 0x0F, 0xA5, 0x10, 0x6E, 0x0E, 0xA0, 0x09,
-	0x7B, 0x04, 0xEC, 0x00, 0x85, 0xFF, 0x8B, 0xFF, 0xE5, 0xFF, 0xFA,
-	0xFF, 0xB6, 0xFF, 0x6C, 0xFF, 0x0E, 0x00, 0xA4, 0x02, 0x41, 0x07,
-	0x80, 0x0C, 0x19, 0x10, 0x44, 0x10, 0xEB, 0x0C, 0xB9, 0x07, 0xFA,
-	0x02, 0x32, 0x00, 0x6D, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEB, 0xFF,
-	0x93, 0xFF, 0x7B, 0xFF, 0xB7, 0x00, 0x15, 0x04, 0x26, 0x09, 0x14,
-	0x0E, 0x98, 0x10, 0x6D, 0x0F, 0x2C, 0x0B, 0xE3, 0x05, 0xBC, 0x01,
-	0xBB, 0xFF, 0x75, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1,
-	0xFF, 0x77, 0xFF, 0xB5, 0xFF, 0xA6, 0x01, 0xC0, 0x05, 0x08, 0x0B,
-	0x58, 0x0F, 0x9D, 0x10, 0x30, 0x0E, 0x4B, 0x09, 0x34, 0x04, 0xC6,
-	0x00, 0x7D, 0xFF, 0x91, 0xFF, 0xE9, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF,
-	0x6C, 0xFF, 0x27, 0x00, 0xDF, 0x02, 0x94, 0x07, 0xCA, 0x0C, 0x37,
-	0x10, 0x27, 0x10, 0xA1, 0x0C, 0x65, 0x07, 0xBE, 0x02, 0x19, 0x00,
-	0x6C, 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8E, 0xFF, 0x81,
-	0xFF, 0xDB, 0x00, 0x5B, 0x04, 0x7A, 0x09, 0x53, 0x0E, 0xA2, 0x10,
-	0x3D, 0x0F, 0xDA, 0x0A, 0x95, 0x05, 0x8C, 0x01, 0xAD, 0xFF, 0x79,
-	0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCC, 0xFF, 0x73, 0xFF,
-	0xC4, 0xFF, 0xD7, 0x01, 0x0E, 0x06, 0x59, 0x0B, 0x87, 0x0F, 0x91,
-	0x10, 0xF0, 0x0D, 0xF7, 0x08, 0xEF, 0x03, 0xA3, 0x00, 0x78, 0xFF,
-	0x97, 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xAA, 0xFF, 0x6D, 0xFF, 0x41,
-	0x00, 0x1C, 0x03, 0xE7, 0x07, 0x13, 0x0D, 0x52, 0x10, 0x06, 0x10,
-	0x56, 0x0C, 0x13, 0x07, 0x84, 0x02, 0x02, 0x00, 0x6D, 0xFF, 0xBA,
-	0xFF, 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x89, 0xFF, 0x01, 0x01,
-	0xA3, 0x04, 0xCE, 0x09, 0x8F, 0x0E, 0xA8, 0x10, 0x0A, 0x0F, 0x88,
-	0x0A, 0x48, 0x05, 0x5F, 0x01, 0xA0, 0xFF, 0x7D, 0xFF, 0xD9, 0xFF,
-	0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF, 0x70, 0xFF, 0xD5, 0xFF, 0x0B,
-	0x02, 0x5E, 0x06, 0xA9, 0x0B, 0xB2, 0x0F, 0x82, 0x10, 0xAE, 0x0D,
-	0xA2, 0x08, 0xAB, 0x03, 0x82, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0,
-	0xFF, 0xF3, 0xFF, 0xA4, 0xFF, 0x6F, 0xFF, 0x5D, 0x00, 0x5B, 0x03,
-	0x3B, 0x08, 0x5A, 0x0D, 0x6A, 0x10, 0xE2, 0x0F, 0x09, 0x0C, 0xC1,
-	0x06, 0x4C, 0x02, 0xEC, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFC, 0xFF,
-	0xDF, 0xFF, 0x83, 0xFF, 0x93, 0xFF, 0x2A, 0x01, 0xEC, 0x04, 0x22,
-	0x0A, 0xC8, 0x0E, 0xAB, 0x10, 0xD4, 0x0E, 0x35, 0x0A, 0xFD, 0x04,
-	0x33, 0x01, 0x95, 0xFF, 0x82, 0xFF, 0xDE, 0xFF, 0x00, 0x00, 0xFD,
-	0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE8, 0xFF, 0x40, 0x02, 0xAF, 0x06,
-	0xF7, 0x0B, 0xDA, 0x0F, 0x6F, 0x10, 0x6A, 0x0D, 0x4E, 0x08, 0x6A,
-	0x03, 0x64, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF1, 0xFF,
-	0x9E, 0xFF, 0x72, 0xFF, 0x7B, 0x00, 0x9C, 0x03, 0x90, 0x08, 0x9F,
-	0x0D, 0x7E, 0x10, 0xBB, 0x0F, 0xBA, 0x0B, 0x70, 0x06, 0x16, 0x02,
-	0xD9, 0xFF, 0x70, 0xFF, 0xC5, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA,
-	0xFF, 0x7E, 0xFF, 0x9D, 0xFF, 0x55, 0x01, 0x37, 0x05, 0x75, 0x0A,
-	0xFF, 0x0E, 0xA9, 0x10, 0x9C, 0x0E, 0xE1, 0x09, 0xB3, 0x04, 0x0A,
-	0x01, 0x8B, 0xFF, 0x87, 0xFF, 0xE2, 0xFF, 0xFB, 0xFF, 0xBB, 0xFF,
-	0x6D, 0xFF, 0xFD, 0xFF, 0x77, 0x02, 0x01, 0x07, 0x45, 0x0C, 0xFF,
-	0x0F, 0x58, 0x10, 0x23, 0x0D, 0xFA, 0x07, 0x2A, 0x03, 0x47, 0x00,
-	0x6E, 0xFF, 0xA9, 0xFF, 0xF5, 0xFF, 0xED, 0xFF, 0x98, 0xFF, 0x77,
-	0xFF, 0x9C, 0x00, 0xDF, 0x03, 0xE4, 0x08, 0xE2, 0x0D, 0x8E, 0x10,
-	0x91, 0x0F, 0x6B, 0x0B, 0x20, 0x06, 0xE3, 0x01, 0xC8, 0xFF, 0x73,
-	0xFF, 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x7A, 0xFF,
-	0xAA, 0xFF, 0x82, 0x01, 0x83, 0x05, 0xC8, 0x0A, 0x32, 0x0F, 0xA4,
-	0x10, 0x60, 0x0E, 0x8D, 0x09, 0x6B, 0x04, 0xE3, 0x00, 0x83, 0xFF,
-	0x8D, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF, 0xB5, 0xFF, 0x6C, 0xFF, 0x14,
-	0x00, 0xB1, 0x02, 0x53, 0x07, 0x91, 0x0C, 0x20, 0x10, 0x3E, 0x10,
-	0xDB, 0x0C, 0xA6, 0x07, 0xEC, 0x02, 0x2C, 0x00, 0x6C, 0xFF, 0xAF,
-	0xFF, 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7C, 0xFF, 0xBE, 0x00,
-	0x24, 0x04, 0x38, 0x09, 0x22, 0x0E, 0x9B, 0x10, 0x63, 0x0F, 0x1A,
-	0x0B, 0xD1, 0x05, 0xB1, 0x01, 0xB8, 0xFF, 0x76, 0xFF, 0xD0, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB8, 0xFF, 0xB1,
-	0x01, 0xD1, 0x05, 0x1A, 0x0B, 0x63, 0x0F, 0x9B, 0x10, 0x22, 0x0E,
-	0x38, 0x09, 0x24, 0x04, 0xBE, 0x00, 0x7C, 0xFF, 0x92, 0xFF, 0xEA,
-	0xFF, 0xF8, 0xFF, 0xAF, 0xFF, 0x6C, 0xFF, 0x2C, 0x00, 0xEC, 0x02,
-	0xA6, 0x07, 0xDB, 0x0C, 0x3E, 0x10, 0x20, 0x10, 0x91, 0x0C, 0x53,
-	0x07, 0xB1, 0x02, 0x14, 0x00, 0x6C, 0xFF, 0xB5, 0xFF, 0xFA, 0xFF,
-	0xE6, 0xFF, 0x8D, 0xFF, 0x83, 0xFF, 0xE3, 0x00, 0x6B, 0x04, 0x8D,
-	0x09, 0x60, 0x0E, 0xA4, 0x10, 0x32, 0x0F, 0xC8, 0x0A, 0x83, 0x05,
-	0x82, 0x01, 0xAA, 0xFF, 0x7A, 0xFF, 0xD5, 0xFF, 0x00, 0x00, 0xFF,
-	0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC8, 0xFF, 0xE3, 0x01, 0x20, 0x06,
-	0x6B, 0x0B, 0x91, 0x0F, 0x8E, 0x10, 0xE2, 0x0D, 0xE4, 0x08, 0xDF,
-	0x03, 0x9C, 0x00, 0x77, 0xFF, 0x98, 0xFF, 0xED, 0xFF, 0xF5, 0xFF,
-	0xA9, 0xFF, 0x6E, 0xFF, 0x47, 0x00, 0x2A, 0x03, 0xFA, 0x07, 0x23,
-	0x0D, 0x58, 0x10, 0xFF, 0x0F, 0x45, 0x0C, 0x01, 0x07, 0x77, 0x02,
-	0xFD, 0xFF, 0x6D, 0xFF, 0xBB, 0xFF, 0xFB, 0xFF, 0xE2, 0xFF, 0x87,
-	0xFF, 0x8B, 0xFF, 0x0A, 0x01, 0xB3, 0x04, 0xE1, 0x09, 0x9C, 0x0E,
-	0xA9, 0x10, 0xFF, 0x0E, 0x75, 0x0A, 0x37, 0x05, 0x55, 0x01, 0x9D,
-	0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF,
-	0x70, 0xFF, 0xD9, 0xFF, 0x16, 0x02, 0x70, 0x06, 0xBA, 0x0B, 0xBB,
-	0x0F, 0x7E, 0x10, 0x9F, 0x0D, 0x90, 0x08, 0x9C, 0x03, 0x7B, 0x00,
-	0x72, 0xFF, 0x9E, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA3, 0xFF, 0x70,
-	0xFF, 0x64, 0x00, 0x6A, 0x03, 0x4E, 0x08, 0x6A, 0x0D, 0x6F, 0x10,
-	0xDA, 0x0F, 0xF7, 0x0B, 0xAF, 0x06, 0x40, 0x02, 0xE8, 0xFF, 0x6E,
-	0xFF, 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDE, 0xFF, 0x82, 0xFF,
-	0x95, 0xFF, 0x33, 0x01, 0xFD, 0x04, 0x35, 0x0A, 0xD4, 0x0E, 0xAB,
-	0x10, 0xC8, 0x0E, 0x22, 0x0A, 0xEC, 0x04, 0x2A, 0x01, 0x93, 0xFF,
-	0x83, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xC0, 0xFF, 0x6E, 0xFF, 0xEC,
-	0xFF, 0x4C, 0x02, 0xC1, 0x06, 0x09, 0x0C, 0xE2, 0x0F, 0x6A, 0x10,
-	0x5A, 0x0D, 0x3B, 0x08, 0x5B, 0x03, 0x5D, 0x00, 0x6F, 0xFF, 0xA4,
-	0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D, 0xFF, 0x73, 0xFF, 0x82, 0x00,
-	0xAB, 0x03, 0xA2, 0x08, 0xAE, 0x0D, 0x82, 0x10, 0xB2, 0x0F, 0xA9,
-	0x0B, 0x5E, 0x06, 0x0B, 0x02, 0xD5, 0xFF, 0x70, 0xFF, 0xC7, 0xFF,
-	0xFE, 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA0, 0xFF, 0x5F,
-	0x01, 0x48, 0x05, 0x88, 0x0A, 0x0A, 0x0F, 0xA8, 0x10, 0x8F, 0x0E,
-	0xCE, 0x09, 0xA3, 0x04, 0x01, 0x01, 0x89, 0xFF, 0x88, 0xFF, 0xE3,
-	0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D, 0xFF, 0x02, 0x00, 0x84, 0x02,
-	0x13, 0x07, 0x56, 0x0C, 0x06, 0x10, 0x52, 0x10, 0x13, 0x0D, 0xE7,
-	0x07, 0x1C, 0x03, 0x41, 0x00, 0x6D, 0xFF, 0xAA, 0xFF, 0xF6, 0xFF,
-	0xED, 0xFF, 0x97, 0xFF, 0x78, 0xFF, 0xA3, 0x00, 0xEF, 0x03, 0xF7,
-	0x08, 0xF0, 0x0D, 0x91, 0x10, 0x87, 0x0F, 0x59, 0x0B, 0x0E, 0x06,
-	0xD7, 0x01, 0xC4, 0xFF, 0x73, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0x00,
-	0x00, 0xD4, 0xFF, 0x79, 0xFF, 0xAD, 0xFF, 0x8C, 0x01, 0x95, 0x05,
-	0xDA, 0x0A, 0x3D, 0x0F, 0xA2, 0x10, 0x53, 0x0E, 0x7A, 0x09, 0x5B,
-	0x04, 0xDB, 0x00, 0x81, 0xFF, 0x8E, 0xFF, 0xE7, 0xFF, 0xF9, 0xFF,
-	0xB4, 0xFF, 0x6C, 0xFF, 0x19, 0x00, 0xBE, 0x02, 0x65, 0x07, 0xA1,
-	0x0C, 0x27, 0x10, 0x37, 0x10, 0xCA, 0x0C, 0x94, 0x07, 0xDF, 0x02,
-	0x27, 0x00, 0x6C, 0xFF, 0xB0, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x91,
-	0xFF, 0x7D, 0xFF, 0xC6, 0x00, 0x34, 0x04, 0x4B, 0x09, 0x30, 0x0E,
-	0x9D, 0x10, 0x58, 0x0F, 0x08, 0x0B, 0xC0, 0x05, 0xA6, 0x01, 0xB5,
-	0xFF, 0x77, 0xFF, 0xD1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF,
-	0x75, 0xFF, 0xBB, 0xFF, 0xBC, 0x01, 0xE3, 0x05, 0x2C, 0x0B, 0x6D,
-	0x0F, 0x98, 0x10, 0x14, 0x0E, 0x26, 0x09, 0x15, 0x04, 0xB7, 0x00,
-	0x7B, 0xFF, 0x93, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAE, 0xFF, 0x6D,
-	0xFF, 0x32, 0x00, 0xFA, 0x02, 0xB9, 0x07, 0xEB, 0x0C, 0x44, 0x10,
-	0x19, 0x10, 0x80, 0x0C, 0x41, 0x07, 0xA4, 0x02, 0x0E, 0x00, 0x6C,
-	0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF,
-	0xEC, 0x00, 0x7B, 0x04, 0xA0, 0x09, 0x6E, 0x0E, 0xA5, 0x10, 0x27,
-	0x0F, 0xB6, 0x0A, 0x72, 0x05, 0x78, 0x01, 0xA7, 0xFF, 0x7B, 0xFF,
-	0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xCA, 0xFF, 0x72, 0xFF, 0xCB,
-	0xFF, 0xEE, 0x01, 0x32, 0x06, 0x7C, 0x0B, 0x9A, 0x0F, 0x8B, 0x10,
-	0xD3, 0x0D, 0xD1, 0x08, 0xD0, 0x03, 0x94, 0x00, 0x76, 0xFF, 0x99,
-	0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x4D, 0x00,
-	0x38, 0x03, 0x0D, 0x08, 0x33, 0x0D, 0x5D, 0x10, 0xF7, 0x0F, 0x34,
-	0x0C, 0xEE, 0x06, 0x6B, 0x02, 0xF8, 0xFF, 0x6D, 0xFF, 0xBC, 0xFF,
-	0xFC, 0xFF, 0xE1, 0xFF, 0x86, 0xFF, 0x8D, 0xFF, 0x13, 0x01, 0xC3,
-	0x04, 0xF4, 0x09, 0xA8, 0x0E, 0xAA, 0x10, 0xF3, 0x0E, 0x63, 0x0A,
-	0x26, 0x05, 0x4B, 0x01, 0x9B, 0xFF, 0x7F, 0xFF, 0xDB, 0xFF, 0x00,
-	0x00, 0xFD, 0xFF, 0xC4, 0xFF, 0x6F, 0xFF, 0xDD, 0xFF, 0x22, 0x02,
-	0x82, 0x06, 0xCC, 0x0B, 0xC4, 0x0F, 0x7A, 0x10, 0x90, 0x0D, 0x7D,
-	0x08, 0x8E, 0x03, 0x74, 0x00, 0x72, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF,
-	0xF2, 0xFF, 0xA1, 0xFF, 0x70, 0xFF, 0x6A, 0x00, 0x78, 0x03, 0x61,
-	0x08, 0x79, 0x0D, 0x73, 0x10, 0xD1, 0x0F, 0xE6, 0x0B, 0x9D, 0x06,
-	0x34, 0x02, 0xE4, 0xFF, 0x6F, 0xFF, 0xC2, 0xFF, 0xFD, 0xFF, 0x00,
-	0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x97, 0xFF, 0x3D, 0x01, 0x0D, 0x05,
-	0x47, 0x0A, 0xE1, 0x0E, 0xAA, 0x10, 0xBB, 0x0E, 0x10, 0x0A, 0xDC,
-	0x04, 0x21, 0x01, 0x90, 0xFF, 0x84, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF,
-	0xBE, 0xFF, 0x6D, 0xFF, 0xF1, 0xFF, 0x58, 0x02, 0xD3, 0x06, 0x1A,
-	0x0C, 0xEB, 0x0F, 0x65, 0x10, 0x4B, 0x0D, 0x29, 0x08, 0x4D, 0x03,
-	0x57, 0x00, 0x6F, 0xFF, 0xA5, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B,
-	0xFF, 0x74, 0xFF, 0x8A, 0x00, 0xBA, 0x03, 0xB5, 0x08, 0xBD, 0x0D,
-	0x86, 0x10, 0xA9, 0x0F, 0x97, 0x0B, 0x4C, 0x06, 0xFF, 0x01, 0xD1,
-	0xFF, 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF,
-	0x7C, 0xFF, 0xA3, 0xFF, 0x69, 0x01, 0x59, 0x05, 0x9A, 0x0A, 0x16,
-	0x0F, 0xA7, 0x10, 0x82, 0x0E, 0xBC, 0x09, 0x93, 0x04, 0xF9, 0x00,
-	0x87, 0xFF, 0x89, 0xFF, 0xE4, 0xFF, 0xFB, 0xFF, 0xB8, 0xFF, 0x6C,
-	0xFF, 0x07, 0x00, 0x91, 0x02, 0x25, 0x07, 0x67, 0x0C, 0x0E, 0x10,
-	0x4D, 0x10, 0x03, 0x0D, 0xD5, 0x07, 0x0E, 0x03, 0x3B, 0x00, 0x6D,
-	0xFF, 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF,
-	0xAB, 0x00, 0xFE, 0x03, 0x0A, 0x09, 0xFF, 0x0D, 0x94, 0x10, 0x7D,
-	0x0F, 0x47, 0x0B, 0xFD, 0x05, 0xCC, 0x01, 0xC0, 0xFF, 0x74, 0xFF,
-	0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD3, 0xFF, 0x78, 0xFF, 0xB0,
-	0xFF, 0x97, 0x01, 0xA6, 0x05, 0xEC, 0x0A, 0x48, 0x0F, 0xA0, 0x10,
-	0x45, 0x0E, 0x67, 0x09, 0x4B, 0x04, 0xD3, 0x00, 0x80, 0xFF, 0x8F,
-	0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x1E, 0x00,
-	0xCB, 0x02, 0x78, 0x07, 0xB2, 0x0C, 0x2E, 0x10, 0x31, 0x10, 0xBA,
-	0x0C, 0x81, 0x07, 0xD2, 0x02, 0x21, 0x00, 0x6C, 0xFF, 0xB2, 0xFF,
-	0xF9, 0xFF, 0xE8, 0xFF, 0x90, 0xFF, 0x7F, 0xFF, 0xCF, 0x00, 0x43,
-	0x04, 0x5E, 0x09, 0x3E, 0x0E, 0x9F, 0x10, 0x4E, 0x0F, 0xF6, 0x0A,
-	0xAE, 0x05, 0x9C, 0x01, 0xB1, 0xFF, 0x78, 0xFF, 0xD2, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x74, 0xFF, 0xBF, 0xFF, 0xC7, 0x01,
-	0xF4, 0x05, 0x3E, 0x0B, 0x78, 0x0F, 0x96, 0x10, 0x06, 0x0E, 0x13,
-	0x09, 0x05, 0x04, 0xAF, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF,
-	0xF7, 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x38, 0x00, 0x07, 0x03, 0xCB,
-	0x07, 0xFB, 0x0C, 0x4A, 0x10, 0x11, 0x10, 0x6F, 0x0C, 0x2E, 0x07,
-	0x97, 0x02, 0x09, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFA, 0xFF, 0xE4,
-	0xFF, 0x8A, 0xFF, 0x86, 0xFF, 0xF4, 0x00, 0x8B, 0x04, 0xB2, 0x09,
-	0x7B, 0x0E, 0xA7, 0x10, 0x1C, 0x0F, 0xA3, 0x0A, 0x61, 0x05, 0x6E,
-	0x01, 0xA4, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
-	0xC8, 0xFF, 0x71, 0xFF, 0xCF, 0xFF, 0xF9, 0x01, 0x43, 0x06, 0x8E,
-	0x0B, 0xA4, 0x0F, 0x88, 0x10, 0xC4, 0x0D, 0xBE, 0x08, 0xC1, 0x03,
-	0x8D, 0x00, 0x75, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA6,
-	0xFF, 0x6E, 0xFF, 0x53, 0x00, 0x46, 0x03, 0x1F, 0x08, 0x43, 0x0D,
-	0x63, 0x10, 0xEF, 0x0F, 0x23, 0x0C, 0xDC, 0x06, 0x5E, 0x02, 0xF3,
-	0xFF, 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x85, 0xFF,
-	0x8F, 0xFF, 0x1C, 0x01, 0xD3, 0x04, 0x06, 0x0A, 0xB5, 0x0E, 0xAA,
-	0x10, 0xE7, 0x0E, 0x50, 0x0A, 0x16, 0x05, 0x42, 0x01, 0x98, 0xFF,
-	0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC3, 0xFF, 0x6F,
-	0xFF, 0xE1, 0xFF, 0x2E, 0x02, 0x94, 0x06, 0xDD, 0x0B, 0xCD, 0x0F,
-	0x76, 0x10, 0x81, 0x0D, 0x6A, 0x08, 0x7F, 0x03, 0x6E, 0x00, 0x71,
-	0xFF, 0xA1, 0xFF, 0xF2, 0xFF, 0x00, 0x00, 0x15, 0x00, 0xD1, 0xFF,
-	0x8B, 0xFE, 0xBC, 0xFD, 0xE1, 0x00, 0x84, 0x09, 0xB0, 0x13, 0x47,
-	0x18, 0xB0, 0x13, 0x84, 0x09, 0xE1, 0x00, 0xBC, 0xFD, 0x8B, 0xFE,
-	0xD1, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xDA, 0x00, 0x30,
-	0x00, 0x5D, 0xFC, 0xB3, 0xFC, 0x35, 0x0A, 0xC2, 0x1C, 0x24, 0x20,
-	0x48, 0x10, 0x5D, 0xFF, 0x74, 0xFB, 0x3A, 0xFF, 0xFB, 0x00, 0x42,
-	0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2C, 0x00, 0xF3, 0x00, 0xAD, 0xFF,
-	0xC5, 0xFB, 0x11, 0xFE, 0xAF, 0x0D, 0xEF, 0x1E, 0x68, 0x1E, 0xBC,
-	0x0C, 0xA7, 0xFD, 0xEA, 0xFB, 0xD3, 0xFF, 0xEE, 0x00, 0x24, 0x00,
-	0xFA, 0xFF, 0xF7, 0xFF, 0x4C, 0x00, 0xFB, 0x00, 0x0C, 0xFF, 0x5F,
-	0xFB, 0xE8, 0xFF, 0x3D, 0x11, 0x7E, 0x20, 0x13, 0x1C, 0x4C, 0x09,
-	0x6A, 0xFC, 0x8C, 0xFC, 0x4E, 0x00, 0xD1, 0x00, 0x0E, 0x00, 0xFD,
-	0xFF, 0xF7, 0xFF, 0x72, 0x00, 0xEC, 0x00, 0x55, 0xFE, 0x3D, 0xFB,
-	0x37, 0x02, 0xBE, 0x14, 0x5D, 0x21, 0x40, 0x19, 0x18, 0x06, 0xA2,
-	0xFB, 0x47, 0xFD, 0xA7, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0xFC, 0xFF, 0x9B, 0x00, 0xC0, 0x00, 0x92, 0xFD, 0x73,
-	0xFB, 0xF2, 0x04, 0x0E, 0x18, 0x81, 0x21, 0x0C, 0x16, 0x37, 0x03,
-	0x47, 0xFB, 0x0B, 0xFE, 0xDF, 0x00, 0x82, 0x00, 0xF9, 0xFF, 0xFE,
-	0xFF, 0x08, 0x00, 0xC3, 0x00, 0x74, 0x00, 0xD2, 0xFC, 0x10, 0xFC,
-	0x08, 0x08, 0x0A, 0x1B, 0xE9, 0x20, 0x9A, 0x12, 0xBE, 0x00, 0x49,
-	0xFB, 0xC8, 0xFE, 0xF9, 0x00, 0x5A, 0x00, 0xF7, 0xFF, 0xFC, 0xFF,
-	0x1B, 0x00, 0xE4, 0x00, 0x06, 0x00, 0x24, 0xFC, 0x1E, 0xFD, 0x65,
-	0x0B, 0x94, 0x1D, 0x9D, 0x1F, 0x0D, 0x0F, 0xB8, 0xFE, 0x96, 0xFB,
-	0x72, 0xFF, 0xF9, 0x00, 0x37, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x36,
-	0x00, 0xF8, 0x00, 0x78, 0xFF, 0x9B, 0xFB, 0xA6, 0xFE, 0xE9, 0x0E,
-	0x8D, 0x1F, 0xAA, 0x1D, 0x87, 0x0B, 0x2B, 0xFD, 0x1E, 0xFC, 0x02,
-	0x00, 0xE5, 0x00, 0x1C, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x58, 0x00,
-	0xF9, 0x00, 0xCF, 0xFE, 0x4A, 0xFB, 0xA7, 0x00, 0x77, 0x12, 0xE0,
-	0x20, 0x26, 0x1B, 0x28, 0x08, 0x18, 0xFC, 0xCB, 0xFC, 0x71, 0x00,
-	0xC5, 0x00, 0x08, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x80, 0x00, 0xE1,
-	0x00, 0x13, 0xFE, 0x45, 0xFB, 0x1D, 0x03, 0xEB, 0x15, 0x7F, 0x21,
-	0x2D, 0x18, 0x0E, 0x05, 0x77, 0xFB, 0x8B, 0xFD, 0xBE, 0x00, 0x9D,
-	0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA9, 0x00,
-	0xAA, 0x00, 0x4F, 0xFD, 0x9D, 0xFB, 0xFA, 0x05, 0x22, 0x19, 0x62,
-	0x21, 0xE0, 0x14, 0x50, 0x02, 0x3E, 0xFB, 0x4E, 0xFE, 0xEB, 0x00,
-	0x73, 0x00, 0xF7, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xD0, 0x00, 0x52,
-	0x00, 0x93, 0xFC, 0x60, 0xFC, 0x2C, 0x09, 0xFA, 0x1B, 0x8A, 0x20,
-	0x60, 0x11, 0xFD, 0xFF, 0x5C, 0xFB, 0x06, 0xFF, 0xFB, 0x00, 0x4D,
-	0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x23, 0x00, 0xED, 0x00, 0xD9, 0xFF,
-	0xEF, 0xFB, 0x98, 0xFD, 0x99, 0x0C, 0x54, 0x1E, 0x02, 0x1F, 0xD2,
-	0x0D, 0x20, 0xFE, 0xC0, 0xFB, 0xA7, 0xFF, 0xF4, 0x00, 0x2D, 0x00,
-	0xF9, 0xFF, 0xF8, 0xFF, 0x41, 0x00, 0xFB, 0x00, 0x41, 0xFF, 0x78,
-	0xFB, 0x4A, 0xFF, 0x25, 0x10, 0x16, 0x20, 0xDA, 0x1C, 0x56, 0x0A,
-	0xBE, 0xFC, 0x56, 0xFC, 0x2C, 0x00, 0xDB, 0x00, 0x14, 0x00, 0xFD,
-	0xFF, 0xF7, 0xFF, 0x66, 0x00, 0xF4, 0x00, 0x8F, 0xFE, 0x3F, 0xFB,
-	0x75, 0x01, 0xAE, 0x13, 0x2C, 0x21, 0x2A, 0x1A, 0x0D, 0x07, 0xD4,
-	0xFB, 0x0C, 0xFD, 0x8F, 0x00, 0xB7, 0x00, 0x03, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0xFA, 0xFF, 0x8E, 0x00, 0xD1, 0x00, 0xCF, 0xFD, 0x58,
-	0xFB, 0x10, 0x04, 0x10, 0x17, 0x8A, 0x21, 0x10, 0x17, 0x10, 0x04,
-	0x58, 0xFB, 0xCF, 0xFD, 0xD1, 0x00, 0x8E, 0x00, 0xFA, 0xFF, 0xFF,
-	0xFF, 0x03, 0x00, 0xB7, 0x00, 0x8F, 0x00, 0x0C, 0xFD, 0xD4, 0xFB,
-	0x0D, 0x07, 0x2A, 0x1A, 0x2C, 0x21, 0xAE, 0x13, 0x75, 0x01, 0x3F,
-	0xFB, 0x8F, 0xFE, 0xF4, 0x00, 0x66, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
-	0x14, 0x00, 0xDB, 0x00, 0x2C, 0x00, 0x56, 0xFC, 0xBE, 0xFC, 0x56,
-	0x0A, 0xDA, 0x1C, 0x16, 0x20, 0x25, 0x10, 0x4A, 0xFF, 0x78, 0xFB,
-	0x41, 0xFF, 0xFB, 0x00, 0x41, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2D,
-	0x00, 0xF4, 0x00, 0xA7, 0xFF, 0xC0, 0xFB, 0x20, 0xFE, 0xD2, 0x0D,
-	0x02, 0x1F, 0x54, 0x1E, 0x99, 0x0C, 0x98, 0xFD, 0xEF, 0xFB, 0xD9,
-	0xFF, 0xED, 0x00, 0x23, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4D, 0x00,
-	0xFB, 0x00, 0x06, 0xFF, 0x5C, 0xFB, 0xFD, 0xFF, 0x60, 0x11, 0x8A,
-	0x20, 0xFA, 0x1B, 0x2C, 0x09, 0x60, 0xFC, 0x93, 0xFC, 0x52, 0x00,
-	0xD0, 0x00, 0x0D, 0x00, 0xFE, 0xFF, 0xF7, 0xFF, 0x73, 0x00, 0xEB,
-	0x00, 0x4E, 0xFE, 0x3E, 0xFB, 0x50, 0x02, 0xE0, 0x14, 0x62, 0x21,
-	0x22, 0x19, 0xFA, 0x05, 0x9D, 0xFB, 0x4F, 0xFD, 0xAA, 0x00, 0xA9,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x9D, 0x00,
-	0xBE, 0x00, 0x8B, 0xFD, 0x77, 0xFB, 0x0E, 0x05, 0x2D, 0x18, 0x7F,
-	0x21, 0xEB, 0x15, 0x1D, 0x03, 0x45, 0xFB, 0x13, 0xFE, 0xE1, 0x00,
-	0x80, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x08, 0x00, 0xC5, 0x00, 0x71,
-	0x00, 0xCB, 0xFC, 0x18, 0xFC, 0x28, 0x08, 0x26, 0x1B, 0xE0, 0x20,
-	0x77, 0x12, 0xA7, 0x00, 0x4A, 0xFB, 0xCF, 0xFE, 0xF9, 0x00, 0x58,
-	0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1C, 0x00, 0xE5, 0x00, 0x02, 0x00,
-	0x1E, 0xFC, 0x2B, 0xFD, 0x87, 0x0B, 0xAA, 0x1D, 0x8D, 0x1F, 0xE9,
-	0x0E, 0xA6, 0xFE, 0x9B, 0xFB, 0x78, 0xFF, 0xF8, 0x00, 0x36, 0x00,
-	0xF9, 0xFF, 0xF8, 0xFF, 0x37, 0x00, 0xF9, 0x00, 0x72, 0xFF, 0x96,
-	0xFB, 0xB8, 0xFE, 0x0D, 0x0F, 0x9D, 0x1F, 0x94, 0x1D, 0x65, 0x0B,
-	0x1E, 0xFD, 0x24, 0xFC, 0x06, 0x00, 0xE4, 0x00, 0x1B, 0x00, 0xFC,
-	0xFF, 0xF7, 0xFF, 0x5A, 0x00, 0xF9, 0x00, 0xC8, 0xFE, 0x49, 0xFB,
-	0xBE, 0x00, 0x9A, 0x12, 0xE9, 0x20, 0x0A, 0x1B, 0x08, 0x08, 0x10,
-	0xFC, 0xD2, 0xFC, 0x74, 0x00, 0xC3, 0x00, 0x08, 0x00, 0xFE, 0xFF,
-	0xF9, 0xFF, 0x82, 0x00, 0xDF, 0x00, 0x0B, 0xFE, 0x47, 0xFB, 0x37,
-	0x03, 0x0C, 0x16, 0x81, 0x21, 0x0E, 0x18, 0xF2, 0x04, 0x73, 0xFB,
-	0x92, 0xFD, 0xC0, 0x00, 0x9B, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0xAB, 0x00, 0xA7, 0x00, 0x47, 0xFD, 0xA2, 0xFB,
-	0x18, 0x06, 0x40, 0x19, 0x5D, 0x21, 0xBE, 0x14, 0x37, 0x02, 0x3D,
-	0xFB, 0x55, 0xFE, 0xEC, 0x00, 0x72, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
-	0x0E, 0x00, 0xD1, 0x00, 0x4E, 0x00, 0x8C, 0xFC, 0x6A, 0xFC, 0x4C,
-	0x09, 0x13, 0x1C, 0x7E, 0x20, 0x3D, 0x11, 0xE8, 0xFF, 0x5F, 0xFB,
-	0x0C, 0xFF, 0xFB, 0x00, 0x4C, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x24,
-	0x00, 0xEE, 0x00, 0xD3, 0xFF, 0xEA, 0xFB, 0xA7, 0xFD, 0xBC, 0x0C,
-	0x68, 0x1E, 0xEF, 0x1E, 0xAF, 0x0D, 0x11, 0xFE, 0xC5, 0xFB, 0xAD,
-	0xFF, 0xF3, 0x00, 0x2C, 0x00, 0xFA, 0xFF, 0xF8, 0xFF, 0x42, 0x00,
-	0xFB, 0x00, 0x3A, 0xFF, 0x74, 0xFB, 0x5D, 0xFF, 0x48, 0x10, 0x24,
-	0x20, 0xC2, 0x1C, 0x35, 0x0A, 0xB3, 0xFC, 0x5D, 0xFC, 0x30, 0x00,
-	0xDA, 0x00, 0x13, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x67, 0x00, 0xF3,
-	0x00, 0x88, 0xFE, 0x3E, 0xFB, 0x8C, 0x01, 0xD0, 0x13, 0x33, 0x21,
-	0x0D, 0x1A, 0xEE, 0x06, 0xCD, 0xFB, 0x13, 0xFD, 0x92, 0x00, 0xB6,
-	0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFA, 0xFF, 0x90, 0x00,
-	0xCF, 0x00, 0xC7, 0xFD, 0x5B, 0xFB, 0x2B, 0x04, 0x31, 0x17, 0x8A,
-	0x21, 0xF0, 0x16, 0xF4, 0x03, 0x56, 0xFB, 0xD6, 0xFD, 0xD3, 0x00,
-	0x8D, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0xB9, 0x00, 0x8C,
-	0x00, 0x05, 0xFD, 0xDB, 0xFB, 0x2C, 0x07, 0x47, 0x1A, 0x25, 0x21,
-	0x8B, 0x13, 0x5D, 0x01, 0x40, 0xFB, 0x97, 0xFE, 0xF5, 0x00, 0x64,
-	0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x15, 0x00, 0xDC, 0x00, 0x27, 0x00,
-	0x50, 0xFC, 0xCA, 0xFC, 0x78, 0x0A, 0xF2, 0x1C, 0x07, 0x20, 0x02,
-	0x10, 0x37, 0xFF, 0x7B, 0xFB, 0x47, 0xFF, 0xFB, 0x00, 0x40, 0x00,
-	0xF8, 0xFF, 0xF9, 0xFF, 0x2E, 0x00, 0xF5, 0x00, 0xA2, 0xFF, 0xBB,
-	0xFB, 0x31, 0xFE, 0xF5, 0x0D, 0x14, 0x1F, 0x3F, 0x1E, 0x77, 0x0C,
-	0x8A, 0xFD, 0xF5, 0xFB, 0xDE, 0xFF, 0xEC, 0x00, 0x22, 0x00, 0xFB,
-	0xFF, 0xF7, 0xFF, 0x4E, 0x00, 0xFB, 0x00, 0xFF, 0xFE, 0x59, 0xFB,
-	0x11, 0x00, 0x83, 0x11, 0x96, 0x20, 0xE0, 0x1B, 0x0B, 0x09, 0x56,
-	0xFC, 0x99, 0xFC, 0x56, 0x00, 0xCE, 0x00, 0x0D, 0x00, 0xFE, 0xFF,
-	0xF8, 0xFF, 0x75, 0x00, 0xEA, 0x00, 0x47, 0xFE, 0x3E, 0xFB, 0x69,
-	0x02, 0x02, 0x15, 0x66, 0x21, 0x04, 0x19, 0xDC, 0x05, 0x98, 0xFB,
-	0x56, 0xFD, 0xAD, 0x00, 0xA8, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x9E, 0x00, 0xBC, 0x00, 0x83, 0xFD, 0x7B, 0xFB,
-	0x2B, 0x05, 0x4C, 0x18, 0x7C, 0x21, 0xCA, 0x15, 0x03, 0x03, 0x44,
-	0xFB, 0x1A, 0xFE, 0xE2, 0x00, 0x7E, 0x00, 0xF8, 0xFF, 0xFE, 0xFF,
-	0x09, 0x00, 0xC6, 0x00, 0x6D, 0x00, 0xC3, 0xFC, 0x20, 0xFC, 0x49,
-	0x08, 0x41, 0x1B, 0xD6, 0x20, 0x54, 0x12, 0x92, 0x00, 0x4C, 0xFB,
-	0xD6, 0xFE, 0xFA, 0x00, 0x57, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1D,
-	0x00, 0xE6, 0x00, 0xFD, 0xFF, 0x18, 0xFC, 0x38, 0xFD, 0xA9, 0x0B,
-	0xC0, 0x1D, 0x7C, 0x1F, 0xC6, 0x0E, 0x95, 0xFE, 0x9F, 0xFB, 0x7E,
-	0xFF, 0xF8, 0x00, 0x35, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x38, 0x00,
-	0xF9, 0x00, 0x6C, 0xFF, 0x92, 0xFB, 0xC9, 0xFE, 0x2F, 0x0F, 0xAD,
-	0x1F, 0x7D, 0x1D, 0x42, 0x0B, 0x12, 0xFD, 0x2A, 0xFC, 0x0B, 0x00,
-	0xE3, 0x00, 0x1A, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5B, 0x00, 0xF8,
-	0x00, 0xC1, 0xFE, 0x47, 0xFB, 0xD4, 0x00, 0xBC, 0x12, 0xF3, 0x20,
-	0xEF, 0x1A, 0xE9, 0x07, 0x08, 0xFC, 0xD9, 0xFC, 0x78, 0x00, 0xC2,
-	0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x83, 0x00, 0xDD, 0x00,
-	0x04, 0xFE, 0x49, 0xFB, 0x52, 0x03, 0x2D, 0x16, 0x83, 0x21, 0xEF,
-	0x17, 0xD5, 0x04, 0x6F, 0xFB, 0x9A, 0xFD, 0xC3, 0x00, 0x9A, 0x00,
-	0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xAD, 0x00, 0xA4,
-	0x00, 0x40, 0xFD, 0xA8, 0xFB, 0x36, 0x06, 0x5E, 0x19, 0x58, 0x21,
-	0x9C, 0x14, 0x1E, 0x02, 0x3D, 0xFB, 0x5D, 0xFE, 0xED, 0x00, 0x70,
-	0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F, 0x00, 0xD2, 0x00, 0x4A, 0x00,
-	0x85, 0xFC, 0x74, 0xFC, 0x6D, 0x09, 0x2D, 0x1C, 0x72, 0x20, 0x1A,
-	0x11, 0xD4, 0xFF, 0x61, 0xFB, 0x13, 0xFF, 0xFC, 0x00, 0x4A, 0x00,
-	0xF7, 0xFF, 0xFA, 0xFF, 0x25, 0x00, 0xEF, 0x00, 0xCE, 0xFF, 0xE4,
-	0xFB, 0xB5, 0xFD, 0xDE, 0x0C, 0x7C, 0x1E, 0xDD, 0x1E, 0x8C, 0x0D,
-	0x01, 0xFE, 0xCA, 0xFB, 0xB3, 0xFF, 0xF3, 0x00, 0x2B, 0x00, 0xFA,
-	0xFF, 0xF8, 0xFF, 0x44, 0x00, 0xFB, 0x00, 0x34, 0xFF, 0x71, 0xFB,
-	0x71, 0xFF, 0x6B, 0x10, 0x32, 0x20, 0xA9, 0x1C, 0x13, 0x0A, 0xA8,
-	0xFC, 0x63, 0xFC, 0x35, 0x00, 0xD9, 0x00, 0x12, 0x00, 0xFD, 0xFF,
-	0xF7, 0xFF, 0x69, 0x00, 0xF2, 0x00, 0x81, 0xFE, 0x3E, 0xFB, 0xA4,
-	0x01, 0xF2, 0x13, 0x3A, 0x21, 0xF0, 0x19, 0xCF, 0x06, 0xC7, 0xFB,
-	0x1B, 0xFD, 0x96, 0x00, 0xB4, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0xFB, 0xFF, 0x92, 0x00, 0xCD, 0x00, 0xC0, 0xFD, 0x5E, 0xFB,
-	0x47, 0x04, 0x51, 0x17, 0x8A, 0x21, 0xD0, 0x16, 0xD9, 0x03, 0x53,
-	0xFB, 0xDE, 0xFD, 0xD5, 0x00, 0x8B, 0x00, 0xFA, 0xFF, 0xFF, 0xFF,
-	0x04, 0x00, 0xBA, 0x00, 0x89, 0x00, 0xFD, 0xFC, 0xE2, 0xFB, 0x4B,
-	0x07, 0x63, 0x1A, 0x1D, 0x21, 0x69, 0x13, 0x46, 0x01, 0x41, 0xFB,
-	0x9E, 0xFE, 0xF5, 0x00, 0x63, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x16,
-	0x00, 0xDD, 0x00, 0x23, 0x00, 0x49, 0xFC, 0xD5, 0xFC, 0x99, 0x0A,
-	0x09, 0x1D, 0xF9, 0x1F, 0xDF, 0x0F, 0x24, 0xFF, 0x7F, 0xFB, 0x4D,
-	0xFF, 0xFB, 0x00, 0x3F, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2F, 0x00,
-	0xF5, 0x00, 0x9C, 0xFF, 0xB6, 0xFB, 0x41, 0xFE, 0x17, 0x0E, 0x26,
-	0x1F, 0x2B, 0x1E, 0x54, 0x0C, 0x7C, 0xFD, 0xFA, 0xFB, 0xE3, 0xFF,
-	0xEB, 0x00, 0x21, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x50, 0x00, 0xFB,
-	0x00, 0xF8, 0xFE, 0x57, 0xFB, 0x26, 0x00, 0xA6, 0x11, 0xA1, 0x20,
-	0xC6, 0x1B, 0xEA, 0x08, 0x4D, 0xFC, 0xA0, 0xFC, 0x5A, 0x00, 0xCD,
-	0x00, 0x0C, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0xE9, 0x00,
-	0x3F, 0xFE, 0x3F, 0xFB, 0x82, 0x02, 0x23, 0x15, 0x6B, 0x21, 0xE5,
-	0x18, 0xBE, 0x05, 0x93, 0xFB, 0x5E, 0xFD, 0xAF, 0x00, 0xA6, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xA0, 0x00, 0xB9,
-	0x00, 0x7C, 0xFD, 0x80, 0xFB, 0x48, 0x05, 0x6B, 0x18, 0x79, 0x21,
-	0xA9, 0x15, 0xE9, 0x02, 0x43, 0xFB, 0x21, 0xFE, 0xE3, 0x00, 0x7D,
-	0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x09, 0x00, 0xC7, 0x00, 0x69, 0x00,
-	0xBC, 0xFC, 0x29, 0xFC, 0x69, 0x08, 0x5C, 0x1B, 0xCC, 0x20, 0x32,
-	0x12, 0x7C, 0x00, 0x4E, 0xFB, 0xDD, 0xFE, 0xFA, 0x00, 0x56, 0x00,
-	0xF7, 0xFF, 0xFB, 0xFF, 0x1D, 0x00, 0xE7, 0x00, 0xF8, 0xFF, 0x12,
-	0xFC, 0x45, 0xFD, 0xCB, 0x0B, 0xD6, 0x1D, 0x6C, 0x1F, 0xA3, 0x0E,
-	0x84, 0xFE, 0xA4, 0xFB, 0x84, 0xFF, 0xF7, 0x00, 0x34, 0x00, 0xF9,
-	0xFF, 0xF8, 0xFF, 0x3A, 0x00, 0xFA, 0x00, 0x66, 0xFF, 0x8E, 0xFB,
-	0xDB, 0xFE, 0x53, 0x0F, 0xBD, 0x1F, 0x66, 0x1D, 0x21, 0x0B, 0x05,
-	0xFD, 0x30, 0xFC, 0x10, 0x00, 0xE2, 0x00, 0x19, 0x00, 0xFC, 0xFF,
-	0xF7, 0xFF, 0x5D, 0x00, 0xF8, 0x00, 0xBA, 0xFE, 0x46, 0xFB, 0xEA,
-	0x00, 0xDF, 0x12, 0xFC, 0x20, 0xD3, 0x1A, 0xC9, 0x07, 0x00, 0xFC,
-	0xE0, 0xFC, 0x7B, 0x00, 0xC0, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9,
-	0xFF, 0x85, 0x00, 0xDC, 0x00, 0xFC, 0xFD, 0x4A, 0xFB, 0x6C, 0x03,
-	0x4E, 0x16, 0x85, 0x21, 0xCF, 0x17, 0xB8, 0x04, 0x6C, 0xFB, 0xA2,
-	0xFD, 0xC5, 0x00, 0x98, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
-	0x01, 0x00, 0xAE, 0x00, 0xA1, 0x00, 0x38, 0xFD, 0xAE, 0xFB, 0x54,
-	0x06, 0x7C, 0x19, 0x53, 0x21, 0x7B, 0x14, 0x05, 0x02, 0x3D, 0xFB,
-	0x64, 0xFE, 0xEE, 0x00, 0x6F, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F,
-	0x00, 0xD4, 0x00, 0x46, 0x00, 0x7E, 0xFC, 0x7E, 0xFC, 0x8E, 0x09,
-	0x46, 0x1C, 0x66, 0x20, 0xF7, 0x10, 0xC0, 0xFF, 0x64, 0xFB, 0x1A,
-	0xFF, 0xFC, 0x00, 0x49, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x26, 0x00,
-	0xF0, 0x00, 0xC9, 0xFF, 0xDF, 0xFB, 0xC4, 0xFD, 0x01, 0x0D, 0x90,
-	0x1E, 0xCA, 0x1E, 0x69, 0x0D, 0xF1, 0xFD, 0xCF, 0xFB, 0xB8, 0xFF,
-	0xF2, 0x00, 0x29, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x45, 0x00, 0xFC,
-	0x00, 0x2D, 0xFF, 0x6D, 0xFB, 0x84, 0xFF, 0x8E, 0x10, 0x3F, 0x20,
-	0x91, 0x1C, 0xF2, 0x09, 0x9D, 0xFC, 0x6A, 0xFC, 0x39, 0x00, 0xD7,
-	0x00, 0x12, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6A, 0x00, 0xF1, 0x00,
-	0x7A, 0xFE, 0x3D, 0xFB, 0xBC, 0x01, 0x14, 0x14, 0x41, 0x21, 0xD4,
-	0x19, 0xB0, 0x06, 0xC0, 0xFB, 0x22, 0xFD, 0x99, 0x00, 0xB3, 0x00,
-	0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x93, 0x00, 0xCB,
-	0x00, 0xB8, 0xFD, 0x61, 0xFB, 0x63, 0x04, 0x71, 0x17, 0x89, 0x21,
-	0xB0, 0x16, 0xBD, 0x03, 0x51, 0xFB, 0xE6, 0xFD, 0xD7, 0x00, 0x8A,
-	0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0xBC, 0x00, 0x86, 0x00,
-	0xF6, 0xFC, 0xE9, 0xFB, 0x6A, 0x07, 0x80, 0x1A, 0x15, 0x21, 0x47,
-	0x13, 0x2F, 0x01, 0x42, 0xFB, 0xA5, 0xFE, 0xF6, 0x00, 0x61, 0x00,
-	0xF7, 0xFF, 0xFC, 0xFF, 0x16, 0x00, 0xDF, 0x00, 0x1E, 0x00, 0x43,
-	0xFC, 0xE1, 0xFC, 0xBB, 0x0A, 0x21, 0x1D, 0xEA, 0x1F, 0xBC, 0x0F,
-	0x12, 0xFF, 0x82, 0xFB, 0x54, 0xFF, 0xFA, 0x00, 0x3D, 0x00, 0xF8,
-	0xFF, 0xF9, 0xFF, 0x30, 0x00, 0xF6, 0x00, 0x96, 0xFF, 0xB1, 0xFB,
-	0x51, 0xFE, 0x3A, 0x0E, 0x38, 0x1F, 0x16, 0x1E, 0x32, 0x0C, 0x6E,
-	0xFD, 0x00, 0xFC, 0xE8, 0xFF, 0xEA, 0x00, 0x20, 0x00, 0xFB, 0xFF,
-	0xF7, 0xFF, 0x51, 0x00, 0xFB, 0x00, 0xF1, 0xFE, 0x54, 0xFB, 0x3B,
-	0x00, 0xC9, 0x11, 0xAD, 0x20, 0xAC, 0x1B, 0xCA, 0x08, 0x44, 0xFC,
-	0xA7, 0xFC, 0x5E, 0x00, 0xCC, 0x00, 0x0B, 0x00, 0xFE, 0xFF, 0xF8,
-	0xFF, 0x78, 0x00, 0xE7, 0x00, 0x38, 0xFE, 0x40, 0xFB, 0x9B, 0x02,
-	0x45, 0x15, 0x6F, 0x21, 0xC7, 0x18, 0xA1, 0x05, 0x8E, 0xFB, 0x65,
-	0xFD, 0xB2, 0x00, 0xA5, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00,
-	0xFE, 0xFF, 0xA2, 0x00, 0xB7, 0x00, 0x74, 0xFD, 0x84, 0xFB, 0x66,
-	0x05, 0x8A, 0x18, 0x76, 0x21, 0x87, 0x15, 0xCF, 0x02, 0x41, 0xFB,
-	0x29, 0xFE, 0xE5, 0x00, 0x7B, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0A,
-	0x00, 0xC9, 0x00, 0x66, 0x00, 0xB5, 0xFC, 0x32, 0xFC, 0x89, 0x08,
-	0x77, 0x1B, 0xC2, 0x20, 0x0F, 0x12, 0x66, 0x00, 0x50, 0xFB, 0xE4,
-	0xFE, 0xFA, 0x00, 0x54, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1E, 0x00,
-	0xE8, 0x00, 0xF3, 0xFF, 0x0C, 0xFC, 0x53, 0xFD, 0xED, 0x0B, 0xEB,
-	0x1D, 0x5A, 0x1F, 0x80, 0x0E, 0x73, 0xFE, 0xA8, 0xFB, 0x8A, 0xFF,
-	0xF7, 0x00, 0x32, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3B, 0x00, 0xFA,
-	0x00, 0x60, 0xFF, 0x8A, 0xFB, 0xED, 0xFE, 0x76, 0x0F, 0xCC, 0x1F,
-	0x4F, 0x1D, 0xFF, 0x0A, 0xF9, 0xFC, 0x36, 0xFC, 0x15, 0x00, 0xE1,
-	0x00, 0x18, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5E, 0x00, 0xF7, 0x00,
-	0xB3, 0xFE, 0x44, 0xFB, 0x01, 0x01, 0x02, 0x13, 0x04, 0x21, 0xB8,
-	0x1A, 0xA9, 0x07, 0xF8, 0xFB, 0xE7, 0xFC, 0x7F, 0x00, 0xBF, 0x00,
-	0x06, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x86, 0x00, 0xDA, 0x00, 0xF5,
-	0xFD, 0x4C, 0xFB, 0x87, 0x03, 0x6E, 0x16, 0x86, 0x21, 0xB0, 0x17,
-	0x9C, 0x04, 0x68, 0xFB, 0xA9, 0xFD, 0xC7, 0x00, 0x96, 0x00, 0xFB,
-	0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xB0, 0x00, 0x9F, 0x00,
-	0x31, 0xFD, 0xB4, 0xFB, 0x73, 0x06, 0x99, 0x19, 0x4D, 0x21, 0x59,
-	0x14, 0xED, 0x01, 0x3D, 0xFB, 0x6B, 0xFE, 0xEF, 0x00, 0x6D, 0x00,
-	0xF7, 0xFF, 0xFD, 0xFF, 0x10, 0x00, 0xD5, 0x00, 0x42, 0x00, 0x77,
-	0xFC, 0x88, 0xFC, 0xAF, 0x09, 0x5F, 0x1C, 0x59, 0x20, 0xD4, 0x10,
-	0xAC, 0xFF, 0x67, 0xFB, 0x20, 0xFF, 0xFC, 0x00, 0x48, 0x00, 0xF7,
-	0xFF, 0xFA, 0xFF, 0x27, 0x00, 0xF0, 0x00, 0xC3, 0xFF, 0xD9, 0xFB,
-	0xD3, 0xFD, 0x24, 0x0D, 0xA3, 0x1E, 0xB7, 0x1E, 0x46, 0x0D, 0xE2,
-	0xFD, 0xD4, 0xFB, 0xBE, 0xFF, 0xF1, 0x00, 0x28, 0x00, 0xFA, 0xFF,
-	0xF7, 0xFF, 0x46, 0x00, 0xFC, 0x00, 0x27, 0xFF, 0x6A, 0xFB, 0x98,
-	0xFF, 0xB1, 0x10, 0x4C, 0x20, 0x78, 0x1C, 0xD1, 0x09, 0x93, 0xFC,
-	0x71, 0xFC, 0x3D, 0x00, 0xD6, 0x00, 0x11, 0x00, 0xFD, 0xFF, 0xF7,
-	0xFF, 0x6C, 0x00, 0xF0, 0x00, 0x72, 0xFE, 0x3D, 0xFB, 0xD4, 0x01,
-	0x36, 0x14, 0x47, 0x21, 0xB6, 0x19, 0x91, 0x06, 0xBA, 0xFB, 0x29,
-	0xFD, 0x9C, 0x00, 0xB1, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0xFB, 0xFF, 0x95, 0x00, 0xC9, 0x00, 0xB1, 0xFD, 0x65, 0xFB, 0x80,
-	0x04, 0x90, 0x17, 0x88, 0x21, 0x8F, 0x16, 0xA2, 0x03, 0x4E, 0xFB,
-	0xED, 0xFD, 0xD9, 0x00, 0x88, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x05,
-	0x00, 0xBD, 0x00, 0x82, 0x00, 0xEF, 0xFC, 0xF0, 0xFB, 0x8A, 0x07,
-	0x9C, 0x1A, 0x0D, 0x21, 0x24, 0x13, 0x18, 0x01, 0x43, 0xFB, 0xAC,
-	0xFE, 0xF7, 0x00, 0x60, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x17, 0x00,
-	0xE0, 0x00, 0x1A, 0x00, 0x3D, 0xFC, 0xED, 0xFC, 0xDD, 0x0A, 0x38,
-	0x1D, 0xDB, 0x1F, 0x99, 0x0F, 0xFF, 0xFE, 0x86, 0xFB, 0x5A, 0xFF,
-	0xFA, 0x00, 0x3C, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x31, 0x00, 0xF6,
-	0x00, 0x90, 0xFF, 0xAD, 0xFB, 0x62, 0xFE, 0x5D, 0x0E, 0x49, 0x1F,
-	0x01, 0x1E, 0x10, 0x0C, 0x60, 0xFD, 0x06, 0xFC, 0xEE, 0xFF, 0xE9,
-	0x00, 0x1F, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x53, 0x00, 0xFB, 0x00,
-	0xEB, 0xFE, 0x52, 0xFB, 0x51, 0x00, 0xEC, 0x11, 0xB7, 0x20, 0x91,
-	0x1B, 0xA9, 0x08, 0x3B, 0xFC, 0xAE, 0xFC, 0x62, 0x00, 0xCA, 0x00,
-	0x0B, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7A, 0x00, 0xE6, 0x00, 0x30,
-	0xFE, 0x40, 0xFB, 0xB5, 0x02, 0x66, 0x15, 0x73, 0x21, 0xA9, 0x18,
-	0x83, 0x05, 0x89, 0xFB, 0x6D, 0xFD, 0xB4, 0x00, 0xA3, 0x00, 0xFE,
-	0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xA3, 0x00, 0xB4, 0x00,
-	0x6D, 0xFD, 0x89, 0xFB, 0x83, 0x05, 0xA9, 0x18, 0x73, 0x21, 0x66,
-	0x15, 0xB5, 0x02, 0x40, 0xFB, 0x30, 0xFE, 0xE6, 0x00, 0x7A, 0x00,
-	0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00, 0xCA, 0x00, 0x62, 0x00, 0xAE,
-	0xFC, 0x3B, 0xFC, 0xA9, 0x08, 0x91, 0x1B, 0xB7, 0x20, 0xEC, 0x11,
-	0x51, 0x00, 0x52, 0xFB, 0xEB, 0xFE, 0xFB, 0x00, 0x53, 0x00, 0xF7,
-	0xFF, 0xFB, 0xFF, 0x1F, 0x00, 0xE9, 0x00, 0xEE, 0xFF, 0x06, 0xFC,
-	0x60, 0xFD, 0x10, 0x0C, 0x01, 0x1E, 0x49, 0x1F, 0x5D, 0x0E, 0x62,
-	0xFE, 0xAD, 0xFB, 0x90, 0xFF, 0xF6, 0x00, 0x31, 0x00, 0xF9, 0xFF,
-	0xF8, 0xFF, 0x3C, 0x00, 0xFA, 0x00, 0x5A, 0xFF, 0x86, 0xFB, 0xFF,
-	0xFE, 0x99, 0x0F, 0xDB, 0x1F, 0x38, 0x1D, 0xDD, 0x0A, 0xED, 0xFC,
-	0x3D, 0xFC, 0x1A, 0x00, 0xE0, 0x00, 0x17, 0x00, 0xFC, 0xFF, 0xF7,
-	0xFF, 0x60, 0x00, 0xF7, 0x00, 0xAC, 0xFE, 0x43, 0xFB, 0x18, 0x01,
-	0x24, 0x13, 0x0D, 0x21, 0x9C, 0x1A, 0x8A, 0x07, 0xF0, 0xFB, 0xEF,
-	0xFC, 0x82, 0x00, 0xBD, 0x00, 0x05, 0x00, 0xFF, 0xFF, 0xF9, 0xFF,
-	0x88, 0x00, 0xD9, 0x00, 0xED, 0xFD, 0x4E, 0xFB, 0xA2, 0x03, 0x8F,
-	0x16, 0x88, 0x21, 0x90, 0x17, 0x80, 0x04, 0x65, 0xFB, 0xB1, 0xFD,
-	0xC9, 0x00, 0x95, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02,
-	0x00, 0xB1, 0x00, 0x9C, 0x00, 0x29, 0xFD, 0xBA, 0xFB, 0x91, 0x06,
-	0xB6, 0x19, 0x47, 0x21, 0x36, 0x14, 0xD4, 0x01, 0x3D, 0xFB, 0x72,
-	0xFE, 0xF0, 0x00, 0x6C, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x11, 0x00,
-	0xD6, 0x00, 0x3D, 0x00, 0x71, 0xFC, 0x93, 0xFC, 0xD1, 0x09, 0x78,
-	0x1C, 0x4C, 0x20, 0xB1, 0x10, 0x98, 0xFF, 0x6A, 0xFB, 0x27, 0xFF,
-	0xFC, 0x00, 0x46, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x28, 0x00, 0xF1,
-	0x00, 0xBE, 0xFF, 0xD4, 0xFB, 0xE2, 0xFD, 0x46, 0x0D, 0xB7, 0x1E,
-	0xA3, 0x1E, 0x24, 0x0D, 0xD3, 0xFD, 0xD9, 0xFB, 0xC3, 0xFF, 0xF0,
-	0x00, 0x27, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x48, 0x00, 0xFC, 0x00,
-	0x20, 0xFF, 0x67, 0xFB, 0xAC, 0xFF, 0xD4, 0x10, 0x59, 0x20, 0x5F,
-	0x1C, 0xAF, 0x09, 0x88, 0xFC, 0x77, 0xFC, 0x42, 0x00, 0xD5, 0x00,
-	0x10, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6D, 0x00, 0xEF, 0x00, 0x6B,
-	0xFE, 0x3D, 0xFB, 0xED, 0x01, 0x59, 0x14, 0x4D, 0x21, 0x99, 0x19,
-	0x73, 0x06, 0xB4, 0xFB, 0x31, 0xFD, 0x9F, 0x00, 0xB0, 0x00, 0x01,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x96, 0x00, 0xC7, 0x00,
-	0xA9, 0xFD, 0x68, 0xFB, 0x9C, 0x04, 0xB0, 0x17, 0x86, 0x21, 0x6E,
-	0x16, 0x87, 0x03, 0x4C, 0xFB, 0xF5, 0xFD, 0xDA, 0x00, 0x86, 0x00,
-	0xF9, 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0xBF, 0x00, 0x7F, 0x00, 0xE7,
-	0xFC, 0xF8, 0xFB, 0xA9, 0x07, 0xB8, 0x1A, 0x04, 0x21, 0x02, 0x13,
-	0x01, 0x01, 0x44, 0xFB, 0xB3, 0xFE, 0xF7, 0x00, 0x5E, 0x00, 0xF7,
-	0xFF, 0xFC, 0xFF, 0x18, 0x00, 0xE1, 0x00, 0x15, 0x00, 0x36, 0xFC,
-	0xF9, 0xFC, 0xFF, 0x0A, 0x4F, 0x1D, 0xCC, 0x1F, 0x76, 0x0F, 0xED,
-	0xFE, 0x8A, 0xFB, 0x60, 0xFF, 0xFA, 0x00, 0x3B, 0x00, 0xF8, 0xFF,
-	0xF9, 0xFF, 0x32, 0x00, 0xF7, 0x00, 0x8A, 0xFF, 0xA8, 0xFB, 0x73,
-	0xFE, 0x80, 0x0E, 0x5A, 0x1F, 0xEB, 0x1D, 0xED, 0x0B, 0x53, 0xFD,
-	0x0C, 0xFC, 0xF3, 0xFF, 0xE8, 0x00, 0x1E, 0x00, 0xFB, 0xFF, 0xF7,
-	0xFF, 0x54, 0x00, 0xFA, 0x00, 0xE4, 0xFE, 0x50, 0xFB, 0x66, 0x00,
-	0x0F, 0x12, 0xC2, 0x20, 0x77, 0x1B, 0x89, 0x08, 0x32, 0xFC, 0xB5,
-	0xFC, 0x66, 0x00, 0xC9, 0x00, 0x0A, 0x00, 0xFE, 0xFF, 0xF8, 0xFF,
-	0x7B, 0x00, 0xE5, 0x00, 0x29, 0xFE, 0x41, 0xFB, 0xCF, 0x02, 0x87,
-	0x15, 0x76, 0x21, 0x8A, 0x18, 0x66, 0x05, 0x84, 0xFB, 0x74, 0xFD,
-	0xB7, 0x00, 0xA2, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE,
-	0xFF, 0xA5, 0x00, 0xB2, 0x00, 0x65, 0xFD, 0x8E, 0xFB, 0xA1, 0x05,
-	0xC7, 0x18, 0x6F, 0x21, 0x45, 0x15, 0x9B, 0x02, 0x40, 0xFB, 0x38,
-	0xFE, 0xE7, 0x00, 0x78, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00,
-	0xCC, 0x00, 0x5E, 0x00, 0xA7, 0xFC, 0x44, 0xFC, 0xCA, 0x08, 0xAC,
-	0x1B, 0xAD, 0x20, 0xC9, 0x11, 0x3B, 0x00, 0x54, 0xFB, 0xF1, 0xFE,
-	0xFB, 0x00, 0x51, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x20, 0x00, 0xEA,
-	0x00, 0xE8, 0xFF, 0x00, 0xFC, 0x6E, 0xFD, 0x32, 0x0C, 0x16, 0x1E,
-	0x38, 0x1F, 0x3A, 0x0E, 0x51, 0xFE, 0xB1, 0xFB, 0x96, 0xFF, 0xF6,
-	0x00, 0x30, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3D, 0x00, 0xFA, 0x00,
-	0x54, 0xFF, 0x82, 0xFB, 0x12, 0xFF, 0xBC, 0x0F, 0xEA, 0x1F, 0x21,
-	0x1D, 0xBB, 0x0A, 0xE1, 0xFC, 0x43, 0xFC, 0x1E, 0x00, 0xDF, 0x00,
-	0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x61, 0x00, 0xF6, 0x00, 0xA5,
-	0xFE, 0x42, 0xFB, 0x2F, 0x01, 0x47, 0x13, 0x15, 0x21, 0x80, 0x1A,
-	0x6A, 0x07, 0xE9, 0xFB, 0xF6, 0xFC, 0x86, 0x00, 0xBC, 0x00, 0x05,
-	0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8A, 0x00, 0xD7, 0x00, 0xE6, 0xFD,
-	0x51, 0xFB, 0xBD, 0x03, 0xB0, 0x16, 0x89, 0x21, 0x71, 0x17, 0x63,
-	0x04, 0x61, 0xFB, 0xB8, 0xFD, 0xCB, 0x00, 0x93, 0x00, 0xFB, 0xFF,
-	0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0xB3, 0x00, 0x99, 0x00, 0x22,
-	0xFD, 0xC0, 0xFB, 0xB0, 0x06, 0xD4, 0x19, 0x41, 0x21, 0x14, 0x14,
-	0xBC, 0x01, 0x3D, 0xFB, 0x7A, 0xFE, 0xF1, 0x00, 0x6A, 0x00, 0xF7,
-	0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD7, 0x00, 0x39, 0x00, 0x6A, 0xFC,
-	0x9D, 0xFC, 0xF2, 0x09, 0x91, 0x1C, 0x3F, 0x20, 0x8E, 0x10, 0x84,
-	0xFF, 0x6D, 0xFB, 0x2D, 0xFF, 0xFC, 0x00, 0x45, 0x00, 0xF7, 0xFF,
-	0xFA, 0xFF, 0x29, 0x00, 0xF2, 0x00, 0xB8, 0xFF, 0xCF, 0xFB, 0xF1,
-	0xFD, 0x69, 0x0D, 0xCA, 0x1E, 0x90, 0x1E, 0x01, 0x0D, 0xC4, 0xFD,
-	0xDF, 0xFB, 0xC9, 0xFF, 0xF0, 0x00, 0x26, 0x00, 0xFA, 0xFF, 0xF7,
-	0xFF, 0x49, 0x00, 0xFC, 0x00, 0x1A, 0xFF, 0x64, 0xFB, 0xC0, 0xFF,
-	0xF7, 0x10, 0x66, 0x20, 0x46, 0x1C, 0x8E, 0x09, 0x7E, 0xFC, 0x7E,
-	0xFC, 0x46, 0x00, 0xD4, 0x00, 0x0F, 0x00, 0xFD, 0xFF, 0xF7, 0xFF,
-	0x6F, 0x00, 0xEE, 0x00, 0x64, 0xFE, 0x3D, 0xFB, 0x05, 0x02, 0x7B,
-	0x14, 0x53, 0x21, 0x7C, 0x19, 0x54, 0x06, 0xAE, 0xFB, 0x38, 0xFD,
-	0xA1, 0x00, 0xAE, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFC,
-	0xFF, 0x98, 0x00, 0xC5, 0x00, 0xA2, 0xFD, 0x6C, 0xFB, 0xB8, 0x04,
-	0xCF, 0x17, 0x85, 0x21, 0x4E, 0x16, 0x6C, 0x03, 0x4A, 0xFB, 0xFC,
-	0xFD, 0xDC, 0x00, 0x85, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x07, 0x00,
-	0xC0, 0x00, 0x7B, 0x00, 0xE0, 0xFC, 0x00, 0xFC, 0xC9, 0x07, 0xD3,
-	0x1A, 0xFC, 0x20, 0xDF, 0x12, 0xEA, 0x00, 0x46, 0xFB, 0xBA, 0xFE,
-	0xF8, 0x00, 0x5D, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x19, 0x00, 0xE2,
-	0x00, 0x10, 0x00, 0x30, 0xFC, 0x05, 0xFD, 0x21, 0x0B, 0x66, 0x1D,
-	0xBD, 0x1F, 0x53, 0x0F, 0xDB, 0xFE, 0x8E, 0xFB, 0x66, 0xFF, 0xFA,
-	0x00, 0x3A, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x34, 0x00, 0xF7, 0x00,
-	0x84, 0xFF, 0xA4, 0xFB, 0x84, 0xFE, 0xA3, 0x0E, 0x6C, 0x1F, 0xD6,
-	0x1D, 0xCB, 0x0B, 0x45, 0xFD, 0x12, 0xFC, 0xF8, 0xFF, 0xE7, 0x00,
-	0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x56, 0x00, 0xFA, 0x00, 0xDD,
-	0xFE, 0x4E, 0xFB, 0x7C, 0x00, 0x32, 0x12, 0xCC, 0x20, 0x5C, 0x1B,
-	0x69, 0x08, 0x29, 0xFC, 0xBC, 0xFC, 0x69, 0x00, 0xC7, 0x00, 0x09,
-	0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7D, 0x00, 0xE3, 0x00, 0x21, 0xFE,
-	0x43, 0xFB, 0xE9, 0x02, 0xA9, 0x15, 0x79, 0x21, 0x6B, 0x18, 0x48,
-	0x05, 0x80, 0xFB, 0x7C, 0xFD, 0xB9, 0x00, 0xA0, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x00, 0xAF, 0x00, 0x5E,
-	0xFD, 0x93, 0xFB, 0xBE, 0x05, 0xE5, 0x18, 0x6B, 0x21, 0x23, 0x15,
-	0x82, 0x02, 0x3F, 0xFB, 0x3F, 0xFE, 0xE9, 0x00, 0x77, 0x00, 0xF8,
-	0xFF, 0xFE, 0xFF, 0x0C, 0x00, 0xCD, 0x00, 0x5A, 0x00, 0xA0, 0xFC,
-	0x4D, 0xFC, 0xEA, 0x08, 0xC6, 0x1B, 0xA1, 0x20, 0xA6, 0x11, 0x26,
-	0x00, 0x57, 0xFB, 0xF8, 0xFE, 0xFB, 0x00, 0x50, 0x00, 0xF7, 0xFF,
-	0xFB, 0xFF, 0x21, 0x00, 0xEB, 0x00, 0xE3, 0xFF, 0xFA, 0xFB, 0x7C,
-	0xFD, 0x54, 0x0C, 0x2B, 0x1E, 0x26, 0x1F, 0x17, 0x0E, 0x41, 0xFE,
-	0xB6, 0xFB, 0x9C, 0xFF, 0xF5, 0x00, 0x2F, 0x00, 0xF9, 0xFF, 0xF8,
-	0xFF, 0x3F, 0x00, 0xFB, 0x00, 0x4D, 0xFF, 0x7F, 0xFB, 0x24, 0xFF,
-	0xDF, 0x0F, 0xF9, 0x1F, 0x09, 0x1D, 0x99, 0x0A, 0xD5, 0xFC, 0x49,
-	0xFC, 0x23, 0x00, 0xDD, 0x00, 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF,
-	0x63, 0x00, 0xF5, 0x00, 0x9E, 0xFE, 0x41, 0xFB, 0x46, 0x01, 0x69,
-	0x13, 0x1D, 0x21, 0x63, 0x1A, 0x4B, 0x07, 0xE2, 0xFB, 0xFD, 0xFC,
-	0x89, 0x00, 0xBA, 0x00, 0x04, 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8B,
-	0x00, 0xD5, 0x00, 0xDE, 0xFD, 0x53, 0xFB, 0xD9, 0x03, 0xD0, 0x16,
-	0x8A, 0x21, 0x51, 0x17, 0x47, 0x04, 0x5E, 0xFB, 0xC0, 0xFD, 0xCD,
-	0x00, 0x92, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00,
-	0xB4, 0x00, 0x96, 0x00, 0x1B, 0xFD, 0xC7, 0xFB, 0xCF, 0x06, 0xF0,
-	0x19, 0x3A, 0x21, 0xF2, 0x13, 0xA4, 0x01, 0x3E, 0xFB, 0x81, 0xFE,
-	0xF2, 0x00, 0x69, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD9,
-	0x00, 0x35, 0x00, 0x63, 0xFC, 0xA8, 0xFC, 0x13, 0x0A, 0xA9, 0x1C,
-	0x32, 0x20, 0x6B, 0x10, 0x71, 0xFF, 0x71, 0xFB, 0x34, 0xFF, 0xFB,
-	0x00, 0x44, 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2B, 0x00, 0xF3, 0x00,
-	0xB3, 0xFF, 0xCA, 0xFB, 0x01, 0xFE, 0x8C, 0x0D, 0xDD, 0x1E, 0x7C,
-	0x1E, 0xDE, 0x0C, 0xB5, 0xFD, 0xE4, 0xFB, 0xCE, 0xFF, 0xEF, 0x00,
-	0x25, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4A, 0x00, 0xFC, 0x00, 0x13,
-	0xFF, 0x61, 0xFB, 0xD4, 0xFF, 0x1A, 0x11, 0x72, 0x20, 0x2D, 0x1C,
-	0x6D, 0x09, 0x74, 0xFC, 0x85, 0xFC, 0x4A, 0x00, 0xD2, 0x00, 0x0F,
-	0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x70, 0x00, 0xED, 0x00, 0x5D, 0xFE,
-	0x3D, 0xFB, 0x1E, 0x02, 0x9C, 0x14, 0x58, 0x21, 0x5E, 0x19, 0x36,
-	0x06, 0xA8, 0xFB, 0x40, 0xFD, 0xA4, 0x00, 0xAD, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0xFC, 0xFF, 0x9A, 0x00, 0xC3, 0x00, 0x9A,
-	0xFD, 0x6F, 0xFB, 0xD5, 0x04, 0xEF, 0x17, 0x83, 0x21, 0x2D, 0x16,
-	0x52, 0x03, 0x49, 0xFB, 0x04, 0xFE, 0xDD, 0x00, 0x83, 0x00, 0xF9,
-	0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xC2, 0x00, 0x78, 0x00, 0xD9, 0xFC,
-	0x08, 0xFC, 0xE9, 0x07, 0xEF, 0x1A, 0xF3, 0x20, 0xBC, 0x12, 0xD4,
-	0x00, 0x47, 0xFB, 0xC1, 0xFE, 0xF8, 0x00, 0x5B, 0x00, 0xF7, 0xFF,
-	0xFC, 0xFF, 0x1A, 0x00, 0xE3, 0x00, 0x0B, 0x00, 0x2A, 0xFC, 0x12,
-	0xFD, 0x42, 0x0B, 0x7D, 0x1D, 0xAD, 0x1F, 0x2F, 0x0F, 0xC9, 0xFE,
-	0x92, 0xFB, 0x6C, 0xFF, 0xF9, 0x00, 0x38, 0x00, 0xF8, 0xFF, 0xF9,
-	0xFF, 0x35, 0x00, 0xF8, 0x00, 0x7E, 0xFF, 0x9F, 0xFB, 0x95, 0xFE,
-	0xC6, 0x0E, 0x7C, 0x1F, 0xC0, 0x1D, 0xA9, 0x0B, 0x38, 0xFD, 0x18,
-	0xFC, 0xFD, 0xFF, 0xE6, 0x00, 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF,
-	0x57, 0x00, 0xFA, 0x00, 0xD6, 0xFE, 0x4C, 0xFB, 0x92, 0x00, 0x54,
-	0x12, 0xD6, 0x20, 0x41, 0x1B, 0x49, 0x08, 0x20, 0xFC, 0xC3, 0xFC,
-	0x6D, 0x00, 0xC6, 0x00, 0x09, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7E,
-	0x00, 0xE2, 0x00, 0x1A, 0xFE, 0x44, 0xFB, 0x03, 0x03, 0xCA, 0x15,
-	0x7C, 0x21, 0x4C, 0x18, 0x2B, 0x05, 0x7B, 0xFB, 0x83, 0xFD, 0xBC,
-	0x00, 0x9E, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0xA8, 0x00, 0xAD, 0x00, 0x56, 0xFD, 0x98, 0xFB, 0xDC, 0x05, 0x04,
-	0x19, 0x66, 0x21, 0x02, 0x15, 0x69, 0x02, 0x3E, 0xFB, 0x47, 0xFE,
-	0xEA, 0x00, 0x75, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xCE,
-	0x00, 0x56, 0x00, 0x99, 0xFC, 0x56, 0xFC, 0x0B, 0x09, 0xE0, 0x1B,
-	0x96, 0x20, 0x83, 0x11, 0x11, 0x00, 0x59, 0xFB, 0xFF, 0xFE, 0xFB,
-	0x00, 0x4E, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x22, 0x00, 0xEC, 0x00,
-	0xDE, 0xFF, 0xF5, 0xFB, 0x8A, 0xFD, 0x77, 0x0C, 0x3F, 0x1E, 0x14,
-	0x1F, 0xF5, 0x0D, 0x31, 0xFE, 0xBB, 0xFB, 0xA2, 0xFF, 0xF5, 0x00,
-	0x2E, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x40, 0x00, 0xFB, 0x00, 0x47,
-	0xFF, 0x7B, 0xFB, 0x37, 0xFF, 0x02, 0x10, 0x07, 0x20, 0xF2, 0x1C,
-	0x78, 0x0A, 0xCA, 0xFC, 0x50, 0xFC, 0x27, 0x00, 0xDC, 0x00, 0x15,
-	0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x64, 0x00, 0xF5, 0x00, 0x97, 0xFE,
-	0x40, 0xFB, 0x5D, 0x01, 0x8B, 0x13, 0x25, 0x21, 0x47, 0x1A, 0x2C,
-	0x07, 0xDB, 0xFB, 0x05, 0xFD, 0x8C, 0x00, 0xB9, 0x00, 0x04, 0x00,
-	0xFF, 0xFF, 0xFA, 0xFF, 0x8D, 0x00, 0xD3, 0x00, 0xD6, 0xFD, 0x56,
-	0xFB, 0xF4, 0x03, 0xF0, 0x16, 0x8A, 0x21, 0x31, 0x17, 0x2B, 0x04,
-	0x5B, 0xFB, 0xC7, 0xFD, 0xCF, 0x00, 0x90, 0x00, 0xFA, 0xFF, 0x00,
-	0x00, 0xFF, 0xFF, 0x03, 0x00, 0xB6, 0x00, 0x92, 0x00, 0x13, 0xFD,
-	0xCD, 0xFB, 0xEE, 0x06, 0x0D, 0x1A, 0x33, 0x21, 0xD0, 0x13, 0x8C,
-	0x01, 0x3E, 0xFB, 0x88, 0xFE, 0xF3, 0x00, 0x67, 0x00, 0xF7, 0xFF,
-	0x06, 0x00, 0x1D, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0xA1, 0x02, 0xA6,
-	0xF8, 0x56, 0x02, 0xA5, 0x28, 0xA5, 0x28, 0x56, 0x02, 0xA6, 0xF8,
-	0xA1, 0x02, 0xFE, 0x00, 0x03, 0xFF, 0x1D, 0x00, 0x06, 0x00, 0x00,
-	0x00, 0x21, 0x00, 0xA6, 0xFF, 0x3F, 0xFF, 0x0B, 0x03, 0x42, 0xFE,
-	0x3E, 0xF8, 0x7F, 0x15, 0xAC, 0x30, 0x7F, 0x15, 0x3E, 0xF8, 0x42,
-	0xFE, 0x0B, 0x03, 0x3F, 0xFF, 0xA6, 0xFF, 0x21, 0x00, 0x00, 0x00,
-	0xFA, 0xFF, 0xCE, 0xFF, 0x14, 0x01, 0x00, 0xFD, 0x35, 0x06, 0xD5,
-	0xF4, 0xDA, 0x15, 0x92, 0x40, 0xAE, 0xFE, 0xF3, 0xFC, 0x68, 0x03,
-	0x86, 0xFD, 0x51, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEC,
-	0xFF, 0xF9, 0xFF, 0xC6, 0x00, 0x55, 0xFD, 0x35, 0x06, 0x90, 0xF3,
-	0xE5, 0x1C, 0x6B, 0x3D, 0x71, 0xFA, 0x34, 0xFF, 0x46, 0x02, 0xFF,
-	0xFD, 0x2D, 0x01, 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDB, 0xFF,
-	0x2D, 0x00, 0x60, 0x00, 0xE1, 0xFD, 0xCE, 0x05, 0xED, 0xF2, 0xF3,
-	0x23, 0x20, 0x39, 0x22, 0xF7, 0x44, 0x01, 0x1F, 0x01, 0x89, 0xFE,
-	0xFB, 0x00, 0x9C, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC9, 0xFF, 0x68,
-	0x00, 0xE5, 0xFF, 0xA0, 0xFE, 0xFB, 0x04, 0x0C, 0xF3, 0xC5, 0x2A,
-	0xD8, 0x33, 0xC9, 0xF4, 0x0B, 0x03, 0x05, 0x00, 0x1A, 0xFF, 0xC1,
-	0x00, 0xAD, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB5, 0xFF, 0xA5, 0x00,
-	0x5C, 0xFF, 0x8C, 0xFF, 0xBF, 0x03, 0x06, 0xF4, 0x22, 0x31, 0xC8,
-	0x2D, 0x63, 0xF3, 0x76, 0x04, 0x08, 0xFF, 0xA7, 0xFF, 0x84, 0x00,
-	0xC0, 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA4, 0xFF, 0xE1, 0x00, 0xCB,
-	0xFE, 0x9B, 0x00, 0x21, 0x02, 0xEE, 0xF5, 0xCD, 0x36, 0x24, 0x27,
-	0xE1, 0xF2, 0x7A, 0x05, 0x33, 0xFE, 0x2A, 0x00, 0x47, 0x00, 0xD3,
-	0xFF, 0x04, 0x00, 0x0F, 0x00, 0x95, 0xFF, 0x17, 0x01, 0x3D, 0xFE,
-	0xBD, 0x01, 0x30, 0x00, 0xCC, 0xF8, 0x92, 0x3B, 0x2A, 0x20, 0x2E,
-	0xF3, 0x12, 0x06, 0x8F, 0xFD, 0x9A, 0x00, 0x10, 0x00, 0xE5, 0xFF,
-	0x02, 0x00, 0x10, 0x00, 0x8C, 0xFF, 0x42, 0x01, 0xBB, 0xFD, 0xE4,
-	0x02, 0x01, 0xFE, 0x9C, 0xFC, 0x45, 0x3F, 0x16, 0x19, 0x2D, 0xF4,
-	0x41, 0x06, 0x21, 0xFD, 0xF3, 0x00, 0xE0, 0xFF, 0xF4, 0xFF, 0x01,
-	0x00, 0x10, 0x00, 0x8B, 0xFF, 0x5D, 0x01, 0x4F, 0xFD, 0xFB, 0x03,
-	0xB2, 0xFB, 0x53, 0x01, 0xC2, 0x41, 0x24, 0x12, 0xBA, 0xF5, 0x0F,
-	0x06, 0xE9, 0xFC, 0x33, 0x01, 0xBB, 0xFF, 0x00, 0x00, 0x00, 0x00,
-	0x0D, 0x00, 0x93, 0xFF, 0x63, 0x01, 0x04, 0xFD, 0xEF, 0x04, 0x62,
-	0xF9, 0xD7, 0x06, 0xF2, 0x42, 0x8D, 0x0B, 0xB0, 0xF7, 0x87, 0x05,
-	0xE6, 0xFC, 0x58, 0x01, 0xA0, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x07, 0x00, 0xA5, 0xFF, 0x52, 0x01, 0xE2, 0xFC, 0xAD, 0x05,
-	0x35, 0xF7, 0x08, 0x0D, 0xCB, 0x42, 0x81, 0x05, 0xE8, 0xF9, 0xBB,
-	0x04, 0x12, 0xFD, 0x64, 0x01, 0x90, 0xFF, 0x0E, 0x00, 0x00, 0x00,
-	0xFE, 0xFF, 0xC2, 0xFF, 0x27, 0x01, 0xF1, 0xFC, 0x22, 0x06, 0x54,
-	0xF5, 0xB8, 0x13, 0x4A, 0x41, 0x29, 0x00, 0x3C, 0xFC, 0xBD, 0x03,
-	0x66, 0xFD, 0x58, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF1,
-	0xFF, 0xEB, 0xFF, 0xE1, 0x00, 0x35, 0xFD, 0x40, 0x06, 0xE4, 0xF3,
-	0xB7, 0x1A, 0x85, 0x3E, 0xA6, 0xFB, 0x86, 0xFE, 0xA0, 0x02, 0xD7,
-	0xFD, 0x39, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xE1, 0xFF,
-	0x1C, 0x00, 0x82, 0x00, 0xB0, 0xFD, 0xF9, 0x05, 0x0C, 0xF3, 0xCB,
-	0x21, 0x8F, 0x3A, 0x0D, 0xF8, 0xA9, 0x00, 0x79, 0x01, 0x5D, 0xFE,
-	0x0B, 0x01, 0x98, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCE, 0xFF, 0x55,
-	0x00, 0x0D, 0x00, 0x60, 0xFE, 0x48, 0x05, 0xEC, 0xF2, 0xB6, 0x28,
-	0x91, 0x35, 0x68, 0xF5, 0x88, 0x02, 0x5A, 0x00, 0xED, 0xFE, 0xD4,
-	0x00, 0xA8, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0x92, 0x00,
-	0x87, 0xFF, 0x3F, 0xFF, 0x2B, 0x04, 0xA1, 0xF3, 0x3D, 0x2F, 0xB8,
-	0x2F, 0xB8, 0xF3, 0x11, 0x04, 0x52, 0xFF, 0x7C, 0xFF, 0x97, 0x00,
-	0xBA, 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA9, 0xFF, 0xCF, 0x00, 0xF8,
-	0xFE, 0x44, 0x00, 0xAA, 0x02, 0x3E, 0xF5, 0x24, 0x35, 0x3B, 0x29,
-	0xF2, 0xF2, 0x35, 0x05, 0x70, 0xFE, 0x03, 0x00, 0x5A, 0x00, 0xCD,
-	0xFF, 0x05, 0x00, 0x0E, 0x00, 0x99, 0xFF, 0x07, 0x01, 0x68, 0xFE,
-	0x63, 0x01, 0xD0, 0x00, 0xD0, 0xF7, 0x35, 0x3A, 0x55, 0x22, 0x02,
-	0xF3, 0xEF, 0x05, 0xBC, 0xFD, 0x7A, 0x00, 0x20, 0x00, 0xDF, 0xFF,
-	0x03, 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x36, 0x01, 0xE1, 0xFD, 0x8A,
-	0x02, 0xB2, 0xFE, 0x56, 0xFB, 0x40, 0x3E, 0x42, 0x1B, 0xCE, 0xF3,
-	0x3E, 0x06, 0x3D, 0xFD, 0xDB, 0x00, 0xEE, 0xFF, 0xF0, 0xFF, 0x01,
-	0x00, 0x11, 0x00, 0x8A, 0xFF, 0x57, 0x01, 0x6D, 0xFD, 0xA8, 0x03,
-	0x69, 0xFC, 0xC8, 0xFF, 0x20, 0x41, 0x40, 0x14, 0x33, 0xF5, 0x28,
-	0x06, 0xF5, 0xFC, 0x22, 0x01, 0xC5, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
-	0x0F, 0x00, 0x8F, 0xFF, 0x64, 0x01, 0x17, 0xFD, 0xA9, 0x04, 0x16,
-	0xFA, 0x10, 0x05, 0xB8, 0x42, 0x87, 0x0D, 0x0D, 0xF7, 0xB9, 0x05,
-	0xE2, 0xFC, 0x50, 0x01, 0xA7, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x0A, 0x00, 0x9E, 0xFF, 0x5A, 0x01, 0xE8, 0xFC, 0x7A, 0x05,
-	0xDA, 0xF7, 0x10, 0x0B, 0xFB, 0x42, 0x4B, 0x07, 0x35, 0xF9, 0x00,
-	0x05, 0x00, 0xFD, 0x63, 0x01, 0x94, 0xFF, 0x0D, 0x00, 0x00, 0x00,
-	0x01, 0x00, 0xB8, 0xFF, 0x37, 0x01, 0xE7, 0xFC, 0x07, 0x06, 0xDE,
-	0xF5, 0x9F, 0x11, 0xE4, 0x41, 0xB8, 0x01, 0x84, 0xFB, 0x0F, 0x04,
-	0x48, 0xFD, 0x5E, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF5,
-	0xFF, 0xDD, 0xFF, 0xF9, 0x00, 0x1B, 0xFD, 0x41, 0x06, 0x47, 0xF4,
-	0x8B, 0x18, 0x81, 0x3F, 0xF1, 0xFC, 0xD5, 0xFD, 0xFA, 0x02, 0xB2,
-	0xFD, 0x45, 0x01, 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE6, 0xFF,
-	0x0C, 0x00, 0xA2, 0x00, 0x85, 0xFD, 0x1A, 0x06, 0x3C, 0xF3, 0x9F,
-	0x1F, 0xE6, 0x3B, 0x0E, 0xF9, 0x07, 0x00, 0xD4, 0x01, 0x33, 0xFE,
-	0x1B, 0x01, 0x94, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x43,
-	0x00, 0x33, 0x00, 0x25, 0xFE, 0x89, 0x05, 0xE0, 0xF2, 0x9C, 0x26,
-	0x33, 0x37, 0x1E, 0xF6, 0xFD, 0x01, 0xB0, 0x00, 0xC0, 0xFE, 0xE6,
-	0x00, 0xA2, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC1, 0xFF, 0x7F, 0x00,
-	0xB2, 0xFF, 0xF6, 0xFE, 0x8E, 0x04, 0x51, 0xF3, 0x49, 0x2D, 0x98,
-	0x31, 0x23, 0xF4, 0xA2, 0x03, 0xA0, 0xFF, 0x51, 0xFF, 0xAA, 0x00,
-	0xB4, 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAE, 0xFF, 0xBD, 0x00, 0x25,
-	0xFF, 0xF1, 0xFF, 0x2B, 0x03, 0xA5, 0xF4, 0x68, 0x33, 0x48, 0x2B,
-	0x17, 0xF3, 0xE7, 0x04, 0xB1, 0xFE, 0xDB, 0xFF, 0x6C, 0x00, 0xC7,
-	0xFF, 0x06, 0x00, 0x0D, 0x00, 0x9E, 0xFF, 0xF7, 0x00, 0x94, 0xFE,
-	0x09, 0x01, 0x6A, 0x01, 0xEB, 0xF6, 0xC1, 0x38, 0x7D, 0x24, 0xE8,
-	0xF2, 0xC1, 0x05, 0xEE, 0xFD, 0x57, 0x00, 0x31, 0x00, 0xDA, 0xFF,
-	0x03, 0x00, 0x10, 0x00, 0x91, 0xFF, 0x29, 0x01, 0x09, 0xFE, 0x2F,
-	0x02, 0x5F, 0xFF, 0x27, 0xFA, 0x20, 0x3D, 0x70, 0x1D, 0x7D, 0xF3,
-	0x31, 0x06, 0x5E, 0xFD, 0xBF, 0x00, 0xFD, 0xFF, 0xEB, 0xFF, 0x02,
-	0x00, 0x11, 0x00, 0x8B, 0xFF, 0x4E, 0x01, 0x8E, 0xFD, 0x52, 0x03,
-	0x20, 0xFD, 0x52, 0xFE, 0x60, 0x40, 0x63, 0x16, 0xB7, 0xF4, 0x39,
-	0x06, 0x05, 0xFD, 0x0F, 0x01, 0xD1, 0xFF, 0xF9, 0xFF, 0x00, 0x00,
-	0x10, 0x00, 0x8D, 0xFF, 0x62, 0x01, 0x2E, 0xFD, 0x5E, 0x04, 0xCC,
-	0xFA, 0x5B, 0x03, 0x5E, 0x42, 0x8E, 0x0F, 0x71, 0xF6, 0xE4, 0x05,
-	0xE2, 0xFC, 0x45, 0x01, 0xAF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x0B, 0x00, 0x99, 0xFF, 0x60, 0x01, 0xF2, 0xFC, 0x40, 0x05,
-	0x85, 0xF8, 0x26, 0x09, 0x0C, 0x43, 0x26, 0x09, 0x85, 0xF8, 0x40,
-	0x05, 0xF2, 0xFC, 0x60, 0x01, 0x99, 0xFF, 0x0B, 0x00, 0x00, 0x00,
-	0x04, 0x00, 0xAF, 0xFF, 0x45, 0x01, 0xE2, 0xFC, 0xE4, 0x05, 0x71,
-	0xF6, 0x8E, 0x0F, 0x5E, 0x42, 0x5B, 0x03, 0xCC, 0xFA, 0x5E, 0x04,
-	0x2E, 0xFD, 0x62, 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xF9,
-	0xFF, 0xD1, 0xFF, 0x0F, 0x01, 0x05, 0xFD, 0x39, 0x06, 0xB7, 0xF4,
-	0x63, 0x16, 0x60, 0x40, 0x52, 0xFE, 0x20, 0xFD, 0x52, 0x03, 0x8E,
-	0xFD, 0x4E, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEB, 0xFF,
-	0xFD, 0xFF, 0xBF, 0x00, 0x5E, 0xFD, 0x31, 0x06, 0x7D, 0xF3, 0x70,
-	0x1D, 0x20, 0x3D, 0x27, 0xFA, 0x5F, 0xFF, 0x2F, 0x02, 0x09, 0xFE,
-	0x29, 0x01, 0x91, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDA, 0xFF, 0x31,
-	0x00, 0x57, 0x00, 0xEE, 0xFD, 0xC1, 0x05, 0xE8, 0xF2, 0x7D, 0x24,
-	0xC1, 0x38, 0xEB, 0xF6, 0x6A, 0x01, 0x09, 0x01, 0x94, 0xFE, 0xF7,
-	0x00, 0x9E, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC7, 0xFF, 0x6C, 0x00,
-	0xDB, 0xFF, 0xB1, 0xFE, 0xE7, 0x04, 0x17, 0xF3, 0x48, 0x2B, 0x68,
-	0x33, 0xA5, 0xF4, 0x2B, 0x03, 0xF1, 0xFF, 0x25, 0xFF, 0xBD, 0x00,
-	0xAE, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB4, 0xFF, 0xAA, 0x00, 0x51,
-	0xFF, 0xA0, 0xFF, 0xA2, 0x03, 0x23, 0xF4, 0x98, 0x31, 0x49, 0x2D,
-	0x51, 0xF3, 0x8E, 0x04, 0xF6, 0xFE, 0xB2, 0xFF, 0x7F, 0x00, 0xC1,
-	0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA2, 0xFF, 0xE6, 0x00, 0xC0, 0xFE,
-	0xB0, 0x00, 0xFD, 0x01, 0x1E, 0xF6, 0x33, 0x37, 0x9C, 0x26, 0xE0,
-	0xF2, 0x89, 0x05, 0x25, 0xFE, 0x33, 0x00, 0x43, 0x00, 0xD4, 0xFF,
-	0x04, 0x00, 0x0F, 0x00, 0x94, 0xFF, 0x1B, 0x01, 0x33, 0xFE, 0xD4,
-	0x01, 0x07, 0x00, 0x0E, 0xF9, 0xE6, 0x3B, 0x9F, 0x1F, 0x3C, 0xF3,
-	0x1A, 0x06, 0x85, 0xFD, 0xA2, 0x00, 0x0C, 0x00, 0xE6, 0xFF, 0x02,
-	0x00, 0x11, 0x00, 0x8C, 0xFF, 0x45, 0x01, 0xB2, 0xFD, 0xFA, 0x02,
-	0xD5, 0xFD, 0xF1, 0xFC, 0x81, 0x3F, 0x8B, 0x18, 0x47, 0xF4, 0x41,
-	0x06, 0x1B, 0xFD, 0xF9, 0x00, 0xDD, 0xFF, 0xF5, 0xFF, 0x01, 0x00,
-	0x10, 0x00, 0x8B, 0xFF, 0x5E, 0x01, 0x48, 0xFD, 0x0F, 0x04, 0x84,
-	0xFB, 0xB8, 0x01, 0xE4, 0x41, 0x9F, 0x11, 0xDE, 0xF5, 0x07, 0x06,
-	0xE7, 0xFC, 0x37, 0x01, 0xB8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x0D,
-	0x00, 0x94, 0xFF, 0x63, 0x01, 0x00, 0xFD, 0x00, 0x05, 0x35, 0xF9,
-	0x4B, 0x07, 0xFB, 0x42, 0x10, 0x0B, 0xDA, 0xF7, 0x7A, 0x05, 0xE8,
-	0xFC, 0x5A, 0x01, 0x9E, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x07, 0x00, 0xA7, 0xFF, 0x50, 0x01, 0xE2, 0xFC, 0xB9, 0x05, 0x0D,
-	0xF7, 0x87, 0x0D, 0xB8, 0x42, 0x10, 0x05, 0x16, 0xFA, 0xA9, 0x04,
-	0x17, 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0xC5, 0xFF, 0x22, 0x01, 0xF5, 0xFC, 0x28, 0x06, 0x33, 0xF5,
-	0x40, 0x14, 0x20, 0x41, 0xC8, 0xFF, 0x69, 0xFC, 0xA8, 0x03, 0x6D,
-	0xFD, 0x57, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF0, 0xFF,
-	0xEE, 0xFF, 0xDB, 0x00, 0x3D, 0xFD, 0x3E, 0x06, 0xCE, 0xF3, 0x42,
-	0x1B, 0x40, 0x3E, 0x56, 0xFB, 0xB2, 0xFE, 0x8A, 0x02, 0xE1, 0xFD,
-	0x36, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDF, 0xFF, 0x20,
-	0x00, 0x7A, 0x00, 0xBC, 0xFD, 0xEF, 0x05, 0x02, 0xF3, 0x55, 0x22,
-	0x35, 0x3A, 0xD0, 0xF7, 0xD0, 0x00, 0x63, 0x01, 0x68, 0xFE, 0x07,
-	0x01, 0x99, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCD, 0xFF, 0x5A, 0x00,
-	0x03, 0x00, 0x70, 0xFE, 0x35, 0x05, 0xF2, 0xF2, 0x3B, 0x29, 0x24,
-	0x35, 0x3E, 0xF5, 0xAA, 0x02, 0x44, 0x00, 0xF8, 0xFE, 0xCF, 0x00,
-	0xA9, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBA, 0xFF, 0x97, 0x00, 0x7C,
-	0xFF, 0x52, 0xFF, 0x11, 0x04, 0xB8, 0xF3, 0xB8, 0x2F, 0x3D, 0x2F,
-	0xA1, 0xF3, 0x2B, 0x04, 0x3F, 0xFF, 0x87, 0xFF, 0x92, 0x00, 0xBB,
-	0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA8, 0xFF, 0xD4, 0x00, 0xED, 0xFE,
-	0x5A, 0x00, 0x88, 0x02, 0x68, 0xF5, 0x91, 0x35, 0xB6, 0x28, 0xEC,
-	0xF2, 0x48, 0x05, 0x60, 0xFE, 0x0D, 0x00, 0x55, 0x00, 0xCE, 0xFF,
-	0x05, 0x00, 0x0E, 0x00, 0x98, 0xFF, 0x0B, 0x01, 0x5D, 0xFE, 0x79,
-	0x01, 0xA9, 0x00, 0x0D, 0xF8, 0x8F, 0x3A, 0xCB, 0x21, 0x0C, 0xF3,
-	0xF9, 0x05, 0xB0, 0xFD, 0x82, 0x00, 0x1C, 0x00, 0xE1, 0xFF, 0x03,
-	0x00, 0x10, 0x00, 0x8E, 0xFF, 0x39, 0x01, 0xD7, 0xFD, 0xA0, 0x02,
-	0x86, 0xFE, 0xA6, 0xFB, 0x85, 0x3E, 0xB7, 0x1A, 0xE4, 0xF3, 0x40,
-	0x06, 0x35, 0xFD, 0xE1, 0x00, 0xEB, 0xFF, 0xF1, 0xFF, 0x01, 0x00,
-	0x11, 0x00, 0x8A, 0xFF, 0x58, 0x01, 0x66, 0xFD, 0xBD, 0x03, 0x3C,
-	0xFC, 0x29, 0x00, 0x4A, 0x41, 0xB8, 0x13, 0x54, 0xF5, 0x22, 0x06,
-	0xF1, 0xFC, 0x27, 0x01, 0xC2, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0x0E,
-	0x00, 0x90, 0xFF, 0x64, 0x01, 0x12, 0xFD, 0xBB, 0x04, 0xE8, 0xF9,
-	0x81, 0x05, 0xCB, 0x42, 0x08, 0x0D, 0x35, 0xF7, 0xAD, 0x05, 0xE2,
-	0xFC, 0x52, 0x01, 0xA5, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x09, 0x00, 0xA0, 0xFF, 0x58, 0x01, 0xE6, 0xFC, 0x87, 0x05, 0xB0,
-	0xF7, 0x8D, 0x0B, 0xF2, 0x42, 0xD7, 0x06, 0x62, 0xF9, 0xEF, 0x04,
-	0x04, 0xFD, 0x63, 0x01, 0x93, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0xBB, 0xFF, 0x33, 0x01, 0xE9, 0xFC, 0x0F, 0x06, 0xBA, 0xF5,
-	0x24, 0x12, 0xC2, 0x41, 0x53, 0x01, 0xB2, 0xFB, 0xFB, 0x03, 0x4F,
-	0xFD, 0x5D, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF4, 0xFF,
-	0xE0, 0xFF, 0xF3, 0x00, 0x21, 0xFD, 0x41, 0x06, 0x2D, 0xF4, 0x16,
-	0x19, 0x45, 0x3F, 0x9C, 0xFC, 0x01, 0xFE, 0xE4, 0x02, 0xBB, 0xFD,
-	0x42, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE5, 0xFF, 0x10,
-	0x00, 0x9A, 0x00, 0x8F, 0xFD, 0x12, 0x06, 0x2E, 0xF3, 0x2A, 0x20,
-	0x92, 0x3B, 0xCC, 0xF8, 0x30, 0x00, 0xBD, 0x01, 0x3D, 0xFE, 0x17,
-	0x01, 0x95, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x47, 0x00,
-	0x2A, 0x00, 0x33, 0xFE, 0x7A, 0x05, 0xE1, 0xF2, 0x24, 0x27, 0xCD,
-	0x36, 0xEE, 0xF5, 0x21, 0x02, 0x9B, 0x00, 0xCB, 0xFE, 0xE1, 0x00,
-	0xA4, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0x84, 0x00, 0xA7,
-	0xFF, 0x08, 0xFF, 0x76, 0x04, 0x63, 0xF3, 0xC8, 0x2D, 0x22, 0x31,
-	0x06, 0xF4, 0xBF, 0x03, 0x8C, 0xFF, 0x5C, 0xFF, 0xA5, 0x00, 0xB5,
-	0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAD, 0xFF, 0xC1, 0x00, 0x1A, 0xFF,
-	0x05, 0x00, 0x0B, 0x03, 0xC9, 0xF4, 0xD8, 0x33, 0xC5, 0x2A, 0x0C,
-	0xF3, 0xFB, 0x04, 0xA0, 0xFE, 0xE5, 0xFF, 0x68, 0x00, 0xC9, 0xFF,
-	0x06, 0x00, 0x0D, 0x00, 0x9C, 0xFF, 0xFB, 0x00, 0x89, 0xFE, 0x1F,
-	0x01, 0x44, 0x01, 0x22, 0xF7, 0x20, 0x39, 0xF3, 0x23, 0xED, 0xF2,
-	0xCE, 0x05, 0xE1, 0xFD, 0x60, 0x00, 0x2D, 0x00, 0xDB, 0xFF, 0x03,
-	0x00, 0x10, 0x00, 0x90, 0xFF, 0x2D, 0x01, 0xFF, 0xFD, 0x46, 0x02,
-	0x34, 0xFF, 0x71, 0xFA, 0x6B, 0x3D, 0xE5, 0x1C, 0x90, 0xF3, 0x35,
-	0x06, 0x55, 0xFD, 0xC6, 0x00, 0xF9, 0xFF, 0xEC, 0xFF, 0x01, 0x00,
-	0x11, 0x00, 0x8B, 0xFF, 0x51, 0x01, 0x86, 0xFD, 0x68, 0x03, 0xF3,
-	0xFC, 0xAE, 0xFE, 0x92, 0x40, 0xDA, 0x15, 0xD5, 0xF4, 0x35, 0x06,
-	0x00, 0xFD, 0x14, 0x01, 0xCE, 0xFF, 0xFA, 0xFF, 0x00, 0x00, 0x0F,
-	0x00, 0x8D, 0xFF, 0x63, 0x01, 0x28, 0xFD, 0x71, 0x04, 0x9E, 0xFA,
-	0xC7, 0x03, 0x79, 0x42, 0x0B, 0x0F, 0x97, 0xF6, 0xDA, 0x05, 0xE2,
-	0xFC, 0x48, 0x01, 0xAD, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x0B, 0x00, 0x9A, 0xFF, 0x5F, 0x01, 0xEF, 0xFC, 0x4F, 0x05, 0x5A,
-	0xF8, 0x9F, 0x09, 0x0A, 0x43, 0xAE, 0x08, 0xB1, 0xF8, 0x30, 0x05,
-	0xF5, 0xFC, 0x61, 0x01, 0x97, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03,
-	0x00, 0xB1, 0xFF, 0x41, 0x01, 0xE3, 0xFC, 0xED, 0x05, 0x4C, 0xF6,
-	0x11, 0x10, 0x42, 0x42, 0xF1, 0x02, 0xFA, 0xFA, 0x4B, 0x04, 0x34,
-	0xFD, 0x61, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF8, 0xFF,
-	0xD4, 0xFF, 0x0A, 0x01, 0x0A, 0xFD, 0x3C, 0x06, 0x9A, 0xF4, 0xED,
-	0x16, 0x2A, 0x40, 0xF8, 0xFD, 0x4D, 0xFD, 0x3C, 0x03, 0x97, 0xFD,
-	0x4C, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEA, 0xFF, 0x00,
-	0x00, 0xB8, 0x00, 0x67, 0xFD, 0x2C, 0x06, 0x6B, 0xF3, 0xFC, 0x1D,
-	0xD3, 0x3C, 0xDF, 0xF9, 0x89, 0xFF, 0x18, 0x02, 0x13, 0xFE, 0x26,
-	0x01, 0x92, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD9, 0xFF, 0x36, 0x00,
-	0x4E, 0x00, 0xFB, 0xFD, 0xB4, 0x05, 0xE4, 0xF2, 0x04, 0x25, 0x5F,
-	0x38, 0xB6, 0xF6, 0x90, 0x01, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00,
-	0x9F, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC6, 0xFF, 0x71, 0x00, 0xD1,
-	0xFF, 0xC2, 0xFE, 0xD1, 0x04, 0x23, 0xF3, 0xC9, 0x2B, 0xF5, 0x32,
-	0x83, 0xF4, 0x49, 0x03, 0xDC, 0xFF, 0x30, 0xFF, 0xB8, 0x00, 0xB0,
-	0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB3, 0xFF, 0xAE, 0x00, 0x46, 0xFF,
-	0xB4, 0xFF, 0x85, 0x03, 0x42, 0xF4, 0x0E, 0x32, 0xCA, 0x2C, 0x41,
-	0xF3, 0xA5, 0x04, 0xE4, 0xFE, 0xBC, 0xFF, 0x7A, 0x00, 0xC3, 0xFF,
-	0x07, 0x00, 0x0D, 0x00, 0xA1, 0xFF, 0xEA, 0x00, 0xB5, 0xFE, 0xC6,
-	0x00, 0xD9, 0x01, 0x4F, 0xF6, 0x99, 0x37, 0x16, 0x26, 0xE0, 0xF2,
-	0x98, 0x05, 0x16, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0xD6, 0xFF, 0x04,
-	0x00, 0x0F, 0x00, 0x93, 0xFF, 0x1F, 0x01, 0x28, 0xFE, 0xEB, 0x01,
-	0xDD, 0xFF, 0x52, 0xF9, 0x36, 0x3C, 0x13, 0x1F, 0x4B, 0xF3, 0x20,
-	0x06, 0x7B, 0xFD, 0xA9, 0x00, 0x08, 0x00, 0xE7, 0xFF, 0x02, 0x00,
-	0x11, 0x00, 0x8C, 0xFF, 0x47, 0x01, 0xA9, 0xFD, 0x10, 0x03, 0xA8,
-	0xFD, 0x47, 0xFD, 0xBB, 0x3F, 0x01, 0x18, 0x62, 0xF4, 0x40, 0x06,
-	0x15, 0xFD, 0xFF, 0x00, 0xDA, 0xFF, 0xF6, 0xFF, 0x01, 0x00, 0x10,
-	0x00, 0x8B, 0xFF, 0x5F, 0x01, 0x41, 0xFD, 0x23, 0x04, 0x56, 0xFB,
-	0x1F, 0x02, 0x06, 0x42, 0x19, 0x11, 0x02, 0xF6, 0xFF, 0x05, 0xE5,
-	0xFC, 0x3B, 0x01, 0xB6, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00,
-	0x95, 0xFF, 0x62, 0x01, 0xFC, 0xFC, 0x10, 0x05, 0x09, 0xF9, 0xC1,
-	0x07, 0x03, 0x43, 0x94, 0x0A, 0x05, 0xF8, 0x6C, 0x05, 0xEA, 0xFC,
-	0x5C, 0x01, 0x9D, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
-	0x00, 0xA9, 0xFF, 0x4D, 0x01, 0xE1, 0xFC, 0xC4, 0x05, 0xE6, 0xF6,
-	0x08, 0x0E, 0xA5, 0x42, 0xA1, 0x04, 0x43, 0xFA, 0x97, 0x04, 0x1D,
-	0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFC, 0xFF,
-	0xC8, 0xFF, 0x1E, 0x01, 0xF8, 0xFC, 0x2D, 0x06, 0x13, 0xF5, 0xC8,
-	0x14, 0xF2, 0x40, 0x69, 0xFF, 0x97, 0xFC, 0x92, 0x03, 0x75, 0xFD,
-	0x55, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEF, 0xFF, 0xF2,
-	0xFF, 0xD4, 0x00, 0x45, 0xFD, 0x3B, 0x06, 0xB8, 0xF3, 0xCE, 0x1B,
-	0xFB, 0x3D, 0x08, 0xFB, 0xDE, 0xFE, 0x73, 0x02, 0xEB, 0xFD, 0x33,
-	0x01, 0x8F, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDE, 0xFF, 0x25, 0x00,
-	0x71, 0x00, 0xC8, 0xFD, 0xE5, 0x05, 0xFA, 0xF2, 0xDF, 0x22, 0xDB,
-	0x39, 0x94, 0xF7, 0xF7, 0x00, 0x4C, 0x01, 0x73, 0xFE, 0x03, 0x01,
-	0x9A, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCC, 0xFF, 0x5E, 0x00, 0xF9,
-	0xFF, 0x80, 0xFE, 0x23, 0x05, 0xF9, 0xF2, 0xC0, 0x29, 0xB8, 0x34,
-	0x16, 0xF5, 0xCB, 0x02, 0x2F, 0x00, 0x03, 0xFF, 0xCA, 0x00, 0xAA,
-	0xFF, 0x0B, 0x00, 0x08, 0x00, 0xB8, 0xFF, 0x9B, 0x00, 0x72, 0xFF,
-	0x65, 0xFF, 0xF6, 0x03, 0xD1, 0xF3, 0x31, 0x30, 0xC1, 0x2E, 0x8B,
-	0xF3, 0x45, 0x04, 0x2D, 0xFF, 0x92, 0xFF, 0x8D, 0x00, 0xBD, 0xFF,
-	0x08, 0x00, 0x0C, 0x00, 0xA6, 0xFF, 0xD8, 0x00, 0xE2, 0xFE, 0x6F,
-	0x00, 0x66, 0x02, 0x93, 0xF5, 0xFB, 0x35, 0x31, 0x28, 0xE7, 0xF2,
-	0x59, 0x05, 0x51, 0xFE, 0x17, 0x00, 0x50, 0x00, 0xD0, 0xFF, 0x05,
-	0x00, 0x0E, 0x00, 0x97, 0xFF, 0x0F, 0x01, 0x53, 0xFE, 0x90, 0x01,
-	0x81, 0x00, 0x4B, 0xF8, 0xE6, 0x3A, 0x3F, 0x21, 0x16, 0xF3, 0x02,
-	0x06, 0xA5, 0xFD, 0x8A, 0x00, 0x18, 0x00, 0xE2, 0xFF, 0x02, 0x00,
-	0x10, 0x00, 0x8D, 0xFF, 0x3C, 0x01, 0xCE, 0xFD, 0xB7, 0x02, 0x5A,
-	0xFE, 0xF7, 0xFB, 0xC6, 0x3E, 0x2C, 0x1A, 0xFC, 0xF3, 0x41, 0x06,
-	0x2E, 0xFD, 0xE7, 0x00, 0xE7, 0xFF, 0xF2, 0xFF, 0x01, 0x00, 0x10,
-	0x00, 0x8B, 0xFF, 0x5A, 0x01, 0x5E, 0xFD, 0xD2, 0x03, 0x0E, 0xFC,
-	0x8B, 0x00, 0x75, 0x41, 0x32, 0x13, 0x75, 0xF5, 0x1C, 0x06, 0xEE,
-	0xFC, 0x2B, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00,
-	0x91, 0xFF, 0x64, 0x01, 0x0D, 0xFD, 0xCD, 0x04, 0xBB, 0xF9, 0xF2,
-	0x05, 0xD9, 0x42, 0x88, 0x0C, 0x5E, 0xF7, 0xA1, 0x05, 0xE3, 0xFC,
-	0x54, 0x01, 0xA3, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
-	0x00, 0xA2, 0xFF, 0x56, 0x01, 0xE5, 0xFC, 0x94, 0x05, 0x87, 0xF7,
-	0x0A, 0x0C, 0xE6, 0x42, 0x64, 0x06, 0x8E, 0xF9, 0xDE, 0x04, 0x09,
-	0xFD, 0x64, 0x01, 0x92, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0xBD, 0xFF, 0x2F, 0x01, 0xEC, 0xFC, 0x16, 0x06, 0x98, 0xF5, 0xAB,
-	0x12, 0x9C, 0x41, 0xEE, 0x00, 0xE0, 0xFB, 0xE6, 0x03, 0x57, 0xFD,
-	0x5B, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF3, 0xFF, 0xE4,
-	0xFF, 0xED, 0x00, 0x27, 0xFD, 0x41, 0x06, 0x14, 0xF4, 0xA1, 0x19,
-	0x06, 0x3F, 0x49, 0xFC, 0x2E, 0xFE, 0xCD, 0x02, 0xC4, 0xFD, 0x3F,
-	0x01, 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE3, 0xFF, 0x14, 0x00,
-	0x92, 0x00, 0x9A, 0xFD, 0x0A, 0x06, 0x22, 0xF3, 0xB4, 0x20, 0x3C,
-	0x3B, 0x8B, 0xF8, 0x58, 0x00, 0xA7, 0x01, 0x48, 0xFE, 0x13, 0x01,
-	0x96, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x4C, 0x00, 0x20,
-	0x00, 0x42, 0xFE, 0x6A, 0x05, 0xE3, 0xF2, 0xAB, 0x27, 0x66, 0x36,
-	0xC0, 0xF5, 0x44, 0x02, 0x85, 0x00, 0xD7, 0xFE, 0xDD, 0x00, 0xA5,
-	0xFF, 0x0C, 0x00, 0x07, 0x00, 0xBE, 0xFF, 0x89, 0x00, 0x9D, 0xFF,
-	0x1A, 0xFF, 0x5E, 0x04, 0x76, 0xF3, 0x45, 0x2E, 0xAA, 0x30, 0xEB,
-	0xF3, 0xDB, 0x03, 0x79, 0xFF, 0x67, 0xFF, 0xA0, 0x00, 0xB7, 0xFF,
-	0x09, 0x00, 0x0B, 0x00, 0xAC, 0xFF, 0xC6, 0x00, 0x0E, 0xFF, 0x1A,
-	0x00, 0xEB, 0x02, 0xEF, 0xF4, 0x49, 0x34, 0x43, 0x2A, 0x02, 0xF3,
-	0x0F, 0x05, 0x90, 0xFE, 0xEF, 0xFF, 0x63, 0x00, 0xCA, 0xFF, 0x06,
-	0x00, 0x0E, 0x00, 0x9B, 0xFF, 0xFF, 0x00, 0x7E, 0xFE, 0x36, 0x01,
-	0x1E, 0x01, 0x5B, 0xF7, 0x7E, 0x39, 0x69, 0x23, 0xF3, 0xF2, 0xD9,
-	0x05, 0xD4, 0xFD, 0x69, 0x00, 0x29, 0x00, 0xDD, 0xFF, 0x03, 0x00,
-	0x10, 0x00, 0x90, 0xFF, 0x30, 0x01, 0xF5, 0xFD, 0x5C, 0x02, 0x09,
-	0xFF, 0xBC, 0xFA, 0xB5, 0x3D, 0x5A, 0x1C, 0xA3, 0xF3, 0x38, 0x06,
-	0x4D, 0xFD, 0xCD, 0x00, 0xF5, 0xFF, 0xED, 0xFF, 0x01, 0x00, 0x11,
-	0x00, 0x8B, 0xFF, 0x53, 0x01, 0x7E, 0xFD, 0x7D, 0x03, 0xC5, 0xFC,
-	0x0B, 0xFF, 0xC3, 0x40, 0x51, 0x15, 0xF4, 0xF4, 0x31, 0x06, 0xFC,
-	0xFC, 0x19, 0x01, 0xCB, 0xFF, 0xFB, 0xFF, 0x00, 0x00, 0x0F, 0x00,
-	0x8E, 0xFF, 0x63, 0x01, 0x22, 0xFD, 0x84, 0x04, 0x71, 0xFA, 0x34,
-	0x04, 0x90, 0x42, 0x89, 0x0E, 0xBE, 0xF6, 0xCF, 0x05, 0xE1, 0xFC,
-	0x4A, 0x01, 0xAB, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
-	0x00, 0x9B, 0xFF, 0x5D, 0x01, 0xEC, 0xFC, 0x5D, 0x05, 0x2F, 0xF8,
-	0x19, 0x0A, 0x07, 0x43, 0x37, 0x08, 0xDD, 0xF8, 0x21, 0x05, 0xF8,
-	0xFC, 0x62, 0x01, 0x96, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00,
-	0xB4, 0xFF, 0x3E, 0x01, 0xE4, 0xFC, 0xF6, 0x05, 0x26, 0xF6, 0x95,
-	0x10, 0x26, 0x42, 0x87, 0x02, 0x28, 0xFB, 0x37, 0x04, 0x3B, 0xFD,
-	0x60, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF7, 0xFF, 0xD7,
-	0xFF, 0x04, 0x01, 0x0F, 0xFD, 0x3E, 0x06, 0x7D, 0xF4, 0x76, 0x17,
-	0xF4, 0x3F, 0x9F, 0xFD, 0x7B, 0xFD, 0x26, 0x03, 0xA0, 0xFD, 0x4A,
-	0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE9, 0xFF, 0x04, 0x00,
-	0xB1, 0x00, 0x71, 0xFD, 0x26, 0x06, 0x5A, 0xF3, 0x88, 0x1E, 0x87,
-	0x3C, 0x98, 0xF9, 0xB3, 0xFF, 0x02, 0x02, 0x1E, 0xFE, 0x22, 0x01,
-	0x93, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD7, 0xFF, 0x3A, 0x00, 0x45,
-	0x00, 0x09, 0xFE, 0xA7, 0x05, 0xE1, 0xF2, 0x8D, 0x25, 0xFD, 0x37,
-	0x82, 0xF6, 0xB5, 0x01, 0xDC, 0x00, 0xAA, 0xFE, 0xEE, 0x00, 0xA0,
-	0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC4, 0xFF, 0x76, 0x00, 0xC7, 0xFF,
-	0xD3, 0xFE, 0xBC, 0x04, 0x31, 0xF3, 0x4A, 0x2C, 0x83, 0x32, 0x61,
-	0xF4, 0x68, 0x03, 0xC8, 0xFF, 0x3B, 0xFF, 0xB3, 0x00, 0xB1, 0xFF,
-	0x0A, 0x00, 0x0A, 0x00, 0xB1, 0xFF, 0xB3, 0x00, 0x3B, 0xFF, 0xC8,
-	0xFF, 0x68, 0x03, 0x61, 0xF4, 0x83, 0x32, 0x4A, 0x2C, 0x31, 0xF3,
-	0xBC, 0x04, 0xD3, 0xFE, 0xC7, 0xFF, 0x76, 0x00, 0xC4, 0xFF, 0x06,
-	0x00, 0x0D, 0x00, 0xA0, 0xFF, 0xEE, 0x00, 0xAA, 0xFE, 0xDC, 0x00,
-	0xB5, 0x01, 0x82, 0xF6, 0xFD, 0x37, 0x8D, 0x25, 0xE1, 0xF2, 0xA7,
-	0x05, 0x09, 0xFE, 0x45, 0x00, 0x3A, 0x00, 0xD7, 0xFF, 0x04, 0x00,
-	0x0F, 0x00, 0x93, 0xFF, 0x22, 0x01, 0x1E, 0xFE, 0x02, 0x02, 0xB3,
-	0xFF, 0x98, 0xF9, 0x87, 0x3C, 0x88, 0x1E, 0x5A, 0xF3, 0x26, 0x06,
-	0x71, 0xFD, 0xB1, 0x00, 0x04, 0x00, 0xE9, 0xFF, 0x02, 0x00, 0x11,
-	0x00, 0x8B, 0xFF, 0x4A, 0x01, 0xA0, 0xFD, 0x26, 0x03, 0x7B, 0xFD,
-	0x9F, 0xFD, 0xF4, 0x3F, 0x76, 0x17, 0x7D, 0xF4, 0x3E, 0x06, 0x0F,
-	0xFD, 0x04, 0x01, 0xD7, 0xFF, 0xF7, 0xFF, 0x01, 0x00, 0x10, 0x00,
-	0x8C, 0xFF, 0x60, 0x01, 0x3B, 0xFD, 0x37, 0x04, 0x28, 0xFB, 0x87,
-	0x02, 0x26, 0x42, 0x95, 0x10, 0x26, 0xF6, 0xF6, 0x05, 0xE4, 0xFC,
-	0x3E, 0x01, 0xB4, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x96,
-	0xFF, 0x62, 0x01, 0xF8, 0xFC, 0x21, 0x05, 0xDD, 0xF8, 0x37, 0x08,
-	0x07, 0x43, 0x19, 0x0A, 0x2F, 0xF8, 0x5D, 0x05, 0xEC, 0xFC, 0x5D,
-	0x01, 0x9B, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
-	0xAB, 0xFF, 0x4A, 0x01, 0xE1, 0xFC, 0xCF, 0x05, 0xBE, 0xF6, 0x89,
-	0x0E, 0x90, 0x42, 0x34, 0x04, 0x71, 0xFA, 0x84, 0x04, 0x22, 0xFD,
-	0x63, 0x01, 0x8E, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xCB,
-	0xFF, 0x19, 0x01, 0xFC, 0xFC, 0x31, 0x06, 0xF4, 0xF4, 0x51, 0x15,
-	0xC3, 0x40, 0x0B, 0xFF, 0xC5, 0xFC, 0x7D, 0x03, 0x7E, 0xFD, 0x53,
-	0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xED, 0xFF, 0xF5, 0xFF,
-	0xCD, 0x00, 0x4D, 0xFD, 0x38, 0x06, 0xA3, 0xF3, 0x5A, 0x1C, 0xB5,
-	0x3D, 0xBC, 0xFA, 0x09, 0xFF, 0x5C, 0x02, 0xF5, 0xFD, 0x30, 0x01,
-	0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDD, 0xFF, 0x29, 0x00, 0x69,
-	0x00, 0xD4, 0xFD, 0xD9, 0x05, 0xF3, 0xF2, 0x69, 0x23, 0x7E, 0x39,
-	0x5B, 0xF7, 0x1E, 0x01, 0x36, 0x01, 0x7E, 0xFE, 0xFF, 0x00, 0x9B,
-	0xFF, 0x0E, 0x00, 0x06, 0x00, 0xCA, 0xFF, 0x63, 0x00, 0xEF, 0xFF,
-	0x90, 0xFE, 0x0F, 0x05, 0x02, 0xF3, 0x43, 0x2A, 0x49, 0x34, 0xEF,
-	0xF4, 0xEB, 0x02, 0x1A, 0x00, 0x0E, 0xFF, 0xC6, 0x00, 0xAC, 0xFF,
-	0x0B, 0x00, 0x09, 0x00, 0xB7, 0xFF, 0xA0, 0x00, 0x67, 0xFF, 0x79,
-	0xFF, 0xDB, 0x03, 0xEB, 0xF3, 0xAA, 0x30, 0x45, 0x2E, 0x76, 0xF3,
-	0x5E, 0x04, 0x1A, 0xFF, 0x9D, 0xFF, 0x89, 0x00, 0xBE, 0xFF, 0x07,
-	0x00, 0x0C, 0x00, 0xA5, 0xFF, 0xDD, 0x00, 0xD7, 0xFE, 0x85, 0x00,
-	0x44, 0x02, 0xC0, 0xF5, 0x66, 0x36, 0xAB, 0x27, 0xE3, 0xF2, 0x6A,
-	0x05, 0x42, 0xFE, 0x20, 0x00, 0x4C, 0x00, 0xD1, 0xFF, 0x04, 0x00,
-	0x0F, 0x00, 0x96, 0xFF, 0x13, 0x01, 0x48, 0xFE, 0xA7, 0x01, 0x58,
-	0x00, 0x8B, 0xF8, 0x3C, 0x3B, 0xB4, 0x20, 0x22, 0xF3, 0x0A, 0x06,
-	0x9A, 0xFD, 0x92, 0x00, 0x14, 0x00, 0xE3, 0xFF, 0x02, 0x00, 0x10,
-	0x00, 0x8D, 0xFF, 0x3F, 0x01, 0xC4, 0xFD, 0xCD, 0x02, 0x2E, 0xFE,
-	0x49, 0xFC, 0x06, 0x3F, 0xA1, 0x19, 0x14, 0xF4, 0x41, 0x06, 0x27,
-	0xFD, 0xED, 0x00, 0xE4, 0xFF, 0xF3, 0xFF, 0x01, 0x00, 0x10, 0x00,
-	0x8B, 0xFF, 0x5B, 0x01, 0x57, 0xFD, 0xE6, 0x03, 0xE0, 0xFB, 0xEE,
-	0x00, 0x9C, 0x41, 0xAB, 0x12, 0x98, 0xF5, 0x16, 0x06, 0xEC, 0xFC,
-	0x2F, 0x01, 0xBD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x92,
-	0xFF, 0x64, 0x01, 0x09, 0xFD, 0xDE, 0x04, 0x8E, 0xF9, 0x64, 0x06,
-	0xE6, 0x42, 0x0A, 0x0C, 0x87, 0xF7, 0x94, 0x05, 0xE5, 0xFC, 0x56,
-	0x01, 0xA2, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
-	0xA3, 0xFF, 0x54, 0x01, 0xE3, 0xFC, 0xA1, 0x05, 0x5E, 0xF7, 0x88,
-	0x0C, 0xD9, 0x42, 0xF2, 0x05, 0xBB, 0xF9, 0xCD, 0x04, 0x0D, 0xFD,
-	0x64, 0x01, 0x91, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0,
-	0xFF, 0x2B, 0x01, 0xEE, 0xFC, 0x1C, 0x06, 0x75, 0xF5, 0x32, 0x13,
-	0x75, 0x41, 0x8B, 0x00, 0x0E, 0xFC, 0xD2, 0x03, 0x5E, 0xFD, 0x5A,
-	0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF2, 0xFF, 0xE7, 0xFF,
-	0xE7, 0x00, 0x2E, 0xFD, 0x41, 0x06, 0xFC, 0xF3, 0x2C, 0x1A, 0xC6,
-	0x3E, 0xF7, 0xFB, 0x5A, 0xFE, 0xB7, 0x02, 0xCE, 0xFD, 0x3C, 0x01,
-	0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE2, 0xFF, 0x18, 0x00, 0x8A,
-	0x00, 0xA5, 0xFD, 0x02, 0x06, 0x16, 0xF3, 0x3F, 0x21, 0xE6, 0x3A,
-	0x4B, 0xF8, 0x81, 0x00, 0x90, 0x01, 0x53, 0xFE, 0x0F, 0x01, 0x97,
-	0xFF, 0x0E, 0x00, 0x05, 0x00, 0xD0, 0xFF, 0x50, 0x00, 0x17, 0x00,
-	0x51, 0xFE, 0x59, 0x05, 0xE7, 0xF2, 0x31, 0x28, 0xFB, 0x35, 0x93,
-	0xF5, 0x66, 0x02, 0x6F, 0x00, 0xE2, 0xFE, 0xD8, 0x00, 0xA6, 0xFF,
-	0x0C, 0x00, 0x08, 0x00, 0xBD, 0xFF, 0x8D, 0x00, 0x92, 0xFF, 0x2D,
-	0xFF, 0x45, 0x04, 0x8B, 0xF3, 0xC1, 0x2E, 0x31, 0x30, 0xD1, 0xF3,
-	0xF6, 0x03, 0x65, 0xFF, 0x72, 0xFF, 0x9B, 0x00, 0xB8, 0xFF, 0x08,
-	0x00, 0x0B, 0x00, 0xAA, 0xFF, 0xCA, 0x00, 0x03, 0xFF, 0x2F, 0x00,
-	0xCB, 0x02, 0x16, 0xF5, 0xB8, 0x34, 0xC0, 0x29, 0xF9, 0xF2, 0x23,
-	0x05, 0x80, 0xFE, 0xF9, 0xFF, 0x5E, 0x00, 0xCC, 0xFF, 0x05, 0x00,
-	0x0E, 0x00, 0x9A, 0xFF, 0x03, 0x01, 0x73, 0xFE, 0x4C, 0x01, 0xF7,
-	0x00, 0x94, 0xF7, 0xDB, 0x39, 0xDF, 0x22, 0xFA, 0xF2, 0xE5, 0x05,
-	0xC8, 0xFD, 0x71, 0x00, 0x25, 0x00, 0xDE, 0xFF, 0x03, 0x00, 0x10,
-	0x00, 0x8F, 0xFF, 0x33, 0x01, 0xEB, 0xFD, 0x73, 0x02, 0xDE, 0xFE,
-	0x08, 0xFB, 0xFB, 0x3D, 0xCE, 0x1B, 0xB8, 0xF3, 0x3B, 0x06, 0x45,
-	0xFD, 0xD4, 0x00, 0xF2, 0xFF, 0xEF, 0xFF, 0x01, 0x00, 0x11, 0x00,
-	0x8A, 0xFF, 0x55, 0x01, 0x75, 0xFD, 0x92, 0x03, 0x97, 0xFC, 0x69,
-	0xFF, 0xF2, 0x40, 0xC8, 0x14, 0x13, 0xF5, 0x2D, 0x06, 0xF8, 0xFC,
-	0x1E, 0x01, 0xC8, 0xFF, 0xFC, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x8F,
-	0xFF, 0x64, 0x01, 0x1D, 0xFD, 0x97, 0x04, 0x43, 0xFA, 0xA1, 0x04,
-	0xA5, 0x42, 0x08, 0x0E, 0xE6, 0xF6, 0xC4, 0x05, 0xE1, 0xFC, 0x4D,
-	0x01, 0xA9, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
-	0x9D, 0xFF, 0x5C, 0x01, 0xEA, 0xFC, 0x6C, 0x05, 0x05, 0xF8, 0x94,
-	0x0A, 0x03, 0x43, 0xC1, 0x07, 0x09, 0xF9, 0x10, 0x05, 0xFC, 0xFC,
-	0x62, 0x01, 0x95, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB6,
-	0xFF, 0x3B, 0x01, 0xE5, 0xFC, 0xFF, 0x05, 0x02, 0xF6, 0x19, 0x11,
-	0x06, 0x42, 0x1F, 0x02, 0x56, 0xFB, 0x23, 0x04, 0x41, 0xFD, 0x5F,
-	0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF6, 0xFF, 0xDA, 0xFF,
-	0xFF, 0x00, 0x15, 0xFD, 0x40, 0x06, 0x62, 0xF4, 0x01, 0x18, 0xBB,
-	0x3F, 0x47, 0xFD, 0xA8, 0xFD, 0x10, 0x03, 0xA9, 0xFD, 0x47, 0x01,
-	0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE7, 0xFF, 0x08, 0x00, 0xA9,
-	0x00, 0x7B, 0xFD, 0x20, 0x06, 0x4B, 0xF3, 0x13, 0x1F, 0x36, 0x3C,
-	0x52, 0xF9, 0xDD, 0xFF, 0xEB, 0x01, 0x28, 0xFE, 0x1F, 0x01, 0x93,
-	0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD6, 0xFF, 0x3F, 0x00, 0x3C, 0x00,
-	0x16, 0xFE, 0x98, 0x05, 0xE0, 0xF2, 0x16, 0x26, 0x99, 0x37, 0x4F,
-	0xF6, 0xD9, 0x01, 0xC6, 0x00, 0xB5, 0xFE, 0xEA, 0x00, 0xA1, 0xFF,
-	0x0D, 0x00, 0x07, 0x00, 0xC3, 0xFF, 0x7A, 0x00, 0xBC, 0xFF, 0xE4,
-	0xFE, 0xA5, 0x04, 0x41, 0xF3, 0xCA, 0x2C, 0x0E, 0x32, 0x42, 0xF4,
-	0x85, 0x03, 0xB4, 0xFF, 0x46, 0xFF, 0xAE, 0x00, 0xB3, 0xFF, 0x09,
-	0x00, 0x0A, 0x00, 0xB0, 0xFF, 0xB8, 0x00, 0x30, 0xFF, 0xDC, 0xFF,
-	0x49, 0x03, 0x83, 0xF4, 0xF5, 0x32, 0xC9, 0x2B, 0x23, 0xF3, 0xD1,
-	0x04, 0xC2, 0xFE, 0xD1, 0xFF, 0x71, 0x00, 0xC6, 0xFF, 0x06, 0x00,
-	0x0D, 0x00, 0x9F, 0xFF, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00, 0x90,
-	0x01, 0xB6, 0xF6, 0x5F, 0x38, 0x04, 0x25, 0xE4, 0xF2, 0xB4, 0x05,
-	0xFB, 0xFD, 0x4E, 0x00, 0x36, 0x00, 0xD9, 0xFF, 0x04, 0x00, 0x0F,
-	0x00, 0x92, 0xFF, 0x26, 0x01, 0x13, 0xFE, 0x18, 0x02, 0x89, 0xFF,
-	0xDF, 0xF9, 0xD3, 0x3C, 0xFC, 0x1D, 0x6B, 0xF3, 0x2C, 0x06, 0x67,
-	0xFD, 0xB8, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0x02, 0x00, 0x11, 0x00,
-	0x8B, 0xFF, 0x4C, 0x01, 0x97, 0xFD, 0x3C, 0x03, 0x4D, 0xFD, 0xF8,
-	0xFD, 0x2A, 0x40, 0xED, 0x16, 0x9A, 0xF4, 0x3C, 0x06, 0x0A, 0xFD,
-	0x0A, 0x01, 0xD4, 0xFF, 0xF8, 0xFF, 0x01, 0x00, 0x10, 0x00, 0x8C,
-	0xFF, 0x61, 0x01, 0x34, 0xFD, 0x4B, 0x04, 0xFA, 0xFA, 0xF1, 0x02,
-	0x42, 0x42, 0x11, 0x10, 0x4C, 0xF6, 0xED, 0x05, 0xE3, 0xFC, 0x41,
-	0x01, 0xB1, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x97, 0xFF,
-	0x61, 0x01, 0xF5, 0xFC, 0x30, 0x05, 0xB1, 0xF8, 0xAE, 0x08, 0x0A,
-	0x43, 0x9F, 0x09, 0x5A, 0xF8, 0x4F, 0x05, 0xEF, 0xFC, 0x5F, 0x01,
-	0x9A, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xAD,
-	0xFF, 0x48, 0x01, 0xE2, 0xFC, 0xDA, 0x05, 0x97, 0xF6, 0x0B, 0x0F,
-	0x79, 0x42, 0xC7, 0x03, 0x9E, 0xFA, 0x71, 0x04, 0x28, 0xFD, 0x63,
-	0x01, 0x8D, 0xFF, 0x0F, 0x00 
-};
-
-static u16
-CoefficientSizes[] = {
-    /* Playback */
-    0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000,
-    /* Record */
-    0x0020, 0x1260, 0x0020, 0x1260, 0x0000, 0x0040, 0x1260, 0x0000,
-};
-
-#ifndef JUST_DATA
-
-static u16
-nm256_getStartOffset (u8 which)
-{
-    u16 offset = 0;
-
-    while (which-- > 0)
-	offset += CoefficientSizes[which];
-
-    return offset;
-}
-
-static void
-nm256_loadOneCoefficient (struct nm256_info *card, int devnum, u32 port, 
-			  u16 which)
-{
-    u32 coeffBuf = (which < 8) ? card->coeffBuf : card->allCoeffBuf;
-    u16 offset = nm256_getStartOffset (which);
-    u16 size = CoefficientSizes[which];
-
-    card->coeffsCurrent = 0;
-
-    if (nm256_debug)
-	printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d, size %d, port 0x%x\n",
-		coeffBuf, coeffBuf + size - 1, which, size, port);
-    nm256_writeBuffer8 (card, coefficients + offset, 1, coeffBuf, size);
-    nm256_writePort32 (card, 2, port + 0, coeffBuf);
-    /* ???  Record seems to behave differently than playback.  */
-    if (devnum == 0)
-	size--;
-    nm256_writePort32 (card, 2, port + 4, coeffBuf + size);
-}
-
-static void
-nm256_loadAllCoefficients (struct nm256_info *card)
-{
-    nm256_writeBuffer8 (card, coefficients, 1, card->allCoeffBuf,
-			  NM_TOTAL_COEFF_COUNT * 4);
-    card->coeffsCurrent = 1;
-}
-
-static void
-nm256_loadCoefficient (struct nm256_info *card, int which, int number)
-{
-    static u16 addrs[3] = { 0x1c, 0x21c, 0x408 };
-    /* The enable register for the specified engine.  */
-    u32 poffset = (which == 1 ? 0x200 : 1);
-
-    if (nm256_readPort8 (card, 2, poffset) & 1) {
-	printk (KERN_ERR "NM256: Engine was enabled while loading coefficients!\n");
-	return;
-    }
-
-    /* The recording engine uses coefficient values 8-15.  */
-    if (which == 1)
-	number += 8;
-
-    if (! nm256_cachedCoefficients (card))
-	nm256_loadOneCoefficient (card, which, addrs[which], number);
-    else {
-	u32 base = card->allCoeffBuf;
-	u32 offset = nm256_getStartOffset (number);
-	u32 endOffset = offset + CoefficientSizes[number];
-
-	if (nm256_debug)
-	    printk (KERN_DEBUG "loading coefficient %d at port 0x%x, offset %d (0x%x-0x%x)\n",
-		    number, addrs[which], offset, base + offset,
-		    base + endOffset - 1);
-
-	if (! card->coeffsCurrent)
-	    nm256_loadAllCoefficients (card);
-
-	nm256_writePort32 (card, 2, addrs[which], base + offset);
-	nm256_writePort32 (card, 2, addrs[which] + 4, base + endOffset - 1);
-    }
-}
-
-#endif /* JUST_DATA */
-
-#endif
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
index fc273e5..7781c13 100644
--- a/sound/oss/opl3.c
+++ b/sound/oss/opl3.c
@@ -34,7 +34,6 @@
 
 #include "sound_config.h"
 
-#include "opl3.h"
 #include "opl3_hw.h"
 
 #define MAX_VOICE	18
@@ -73,7 +72,6 @@
 	unsigned char   cmask;
 
 	int             is_opl4;
-	int            *osp;
 } opl_devinfo;
 
 static struct opl_devinfo *devc = NULL;
@@ -144,7 +142,7 @@
 	}
 }
 
-int opl3_detect(int ioaddr, int *osp)
+static int opl3_detect(int ioaddr)
 {
 	/*
 	 * This function returns 1 if the FM chip is present at the given I/O port
@@ -182,7 +180,6 @@
 		goto cleanup_devc;
 	}
 
-	devc->osp = osp;
 	devc->base = ioaddr;
 
 	/* Reset timers 1 and 2 */
@@ -1105,7 +1102,7 @@
 	.setup_voice	= opl3_setup_voice
 };
 
-int opl3_init(int ioaddr, int *osp, struct module *owner)
+static int opl3_init(int ioaddr, struct module *owner)
 {
 	int i;
 	int me;
@@ -1194,9 +1191,6 @@
 	return me;
 }
 
-EXPORT_SYMBOL(opl3_init);
-EXPORT_SYMBOL(opl3_detect);
-
 static int me;
 
 static int io = -1;
@@ -1209,12 +1203,12 @@
 
 	if (io != -1)	/* User loading pure OPL3 module */
 	{
-		if (!opl3_detect(io, NULL))
+		if (!opl3_detect(io))
 		{
 			return -ENODEV;
 		}
 
-		me = opl3_init(io, NULL, THIS_MODULE);
+		me = opl3_init(io, THIS_MODULE);
 	}
 
 	return 0;
diff --git a/sound/oss/opl3.h b/sound/oss/opl3.h
deleted file mode 100644
index 0bc9a4b..0000000
--- a/sound/oss/opl3.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int opl3_detect (int ioaddr, int *osp);
-int opl3_init(int ioaddr, int *osp, struct module *owner);
-
-void enable_opl3_mode(int left, int right, int both);
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
deleted file mode 100644
index e20051f..0000000
--- a/sound/oss/opl3sa2.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * sound/oss/opl3sa2.c
- *
- * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
- * NOTE: All traces of the name OPL3-SAx have now (December 2000) been
- *       removed from the driver code, as an email exchange with Yamaha
- *       provided the information that the YMF-719 is indeed just a
- *       re-badged 715.
- *
- * Copyright 1998-2001 Scott Murray <scott@spiteful.org>
- *
- * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
- * and others.  Now incorporates code/ideas from pss.c, also by Hannu
- * Savolainen.  Both of those files are distributed with the following
- * license:
- *
- * "Copyright (C) by Hannu Savolainen 1993-1997
- *
- *  OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- *  Version 2 (June 1991). See the "COPYING" file distributed with this software
- *  for more info."
- *
- * As such, in accordance with the above license, this file, opl3sa2.c, is
- * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
- * See the "COPYING" file distributed with this software for more information.
- *
- * Change History
- * --------------
- * Scott Murray            Original driver (Jun 14, 1998)
- * Paul J.Y. Lahaie        Changed probing / attach code order
- * Scott Murray            Added mixer support (Dec 03, 1998)
- * Scott Murray            Changed detection code to be more forgiving,
- *                         added force option as last resort,
- *                         fixed ioctl return values. (Dec 30, 1998)
- * Scott Murray            Simpler detection code should work all the time now
- *                         (with thanks to Ben Hutchings for the heuristic),
- *                         removed now unnecessary force option. (Jan 5, 1999)
- * Christoph Hellwig	   Adapted to module_init/module_exit (Mar 4, 2000)
- * Scott Murray            Reworked SA2 versus SA3 mixer code, updated chipset
- *                         version detection code (again!). (Dec 5, 2000)
- * Scott Murray            Adjusted master volume mixer scaling. (Dec 6, 2000)
- * Scott Murray            Based on a patch by Joel Yliluoma (aka Bisqwit),
- *                         integrated wide mixer and adjusted mic, bass, treble
- *                         scaling. (Dec 6, 2000)
- * Scott Murray            Based on a patch by Peter Englmaier, integrated
- *                         ymode and loopback options. (Dec 6, 2000)
- * Scott Murray            Inspired by a patch by Peter Englmaier, and based on
- *                         what ALSA does, added initialization code for the
- *                         default DMA and IRQ settings. (Dec 6, 2000)
- * Scott Murray            Added some more checks to the card detection code,
- *                         based on what ALSA does. (Dec 12, 2000)
- * Scott Murray            Inspired by similar patches from John Fremlin,
- *                         Jim Radford, Mike Rolig, and Ingmar Steen, added 2.4
- *                         ISA PnP API support, mainly based on bits from
- *                         sb_card.c and awe_wave.c. (Dec 12, 2000)
- * Scott Murray            Some small cleanups to the init code output.
- *                         (Jan 7, 2001)
- * Zwane Mwaikambo	   Added PM support. (Dec 4 2001)
- *
- * Adam Belay              Converted driver to new PnP Layer (Oct 12, 2002)
- * Zwane Mwaikambo	   Code, data structure cleanups. (Feb 15 2002)
- * Zwane Mwaikambo	   Free resources during auxiliary device probe
- * 			   failures (Apr 29 2002)
- *   
- */
-
-#include <linux/pnp.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include "sound_config.h"
-
-#include "ad1848.h"
-#include "mpu401.h"
-
-#define OPL3SA2_MODULE_NAME	"opl3sa2"
-#define PFX			OPL3SA2_MODULE_NAME ": "
-
-/* Useful control port indexes: */
-#define OPL3SA2_PM	     0x01
-#define OPL3SA2_SYS_CTRL     0x02
-#define OPL3SA2_IRQ_CONFIG   0x03
-#define OPL3SA2_DMA_CONFIG   0x06
-#define OPL3SA2_MASTER_LEFT  0x07
-#define OPL3SA2_MASTER_RIGHT 0x08
-#define OPL3SA2_MIC          0x09
-#define OPL3SA2_MISC         0x0A
-
-#define OPL3SA3_WIDE         0x14
-#define OPL3SA3_BASS         0x15
-#define OPL3SA3_TREBLE       0x16
-
-/* Useful constants: */
-#define DEFAULT_VOLUME 50
-#define DEFAULT_MIC    50
-#define DEFAULT_TIMBRE 0
-
-/* Power saving modes */
-#define OPL3SA2_PM_MODE0	0x00
-#define OPL3SA2_PM_MODE1	0x04	/* PSV */
-#define OPL3SA2_PM_MODE2	0x05	/* PSV | PDX */
-#define OPL3SA2_PM_MODE3	0x27	/* ADOWN | PSV | PDN | PDX */
-
-
-/* For checking against what the card returns: */
-#define VERSION_UNKNOWN 0
-#define VERSION_YMF711  1
-#define VERSION_YMF715  2
-#define VERSION_YMF715B 3
-#define VERSION_YMF715E 4
-/* also assuming that anything > 4 but <= 7 is a 715E */
-
-/* Chipset type constants for use below */
-#define CHIPSET_UNKNOWN -1
-#define CHIPSET_OPL3SA2 0
-#define CHIPSET_OPL3SA3 1
-static const char *CHIPSET_TABLE[] = {"OPL3-SA2", "OPL3-SA3"};
-
-#ifdef CONFIG_PNP
-#define OPL3SA2_CARDS_MAX 4
-#else
-#define OPL3SA2_CARDS_MAX 1
-#endif
-
-/* This should be pretty obvious */
-static int opl3sa2_cards_num;
-
-typedef struct {
-	/* device resources */
-	unsigned short cfg_port;
-	struct address_info cfg;
-	struct address_info cfg_mss;
-	struct address_info cfg_mpu;
-#ifdef CONFIG_PNP
-	/* PnP Stuff */
-	struct pnp_dev* pdev;
-	int activated;			/* Whether said devices have been activated */
-#endif
-	unsigned int	card;
-	int		chipset;	/* What's my version(s)? */
-	char		*chipset_name;
-
-	/* mixer data */
-	int		mixer;
-	unsigned int	volume_l;
-	unsigned int	volume_r;
-	unsigned int	mic;
-	unsigned int	bass_l;
-	unsigned int	bass_r;
-	unsigned int	treble_l;
-	unsigned int	treble_r;
-	unsigned int	wide_l;
-	unsigned int	wide_r;
-} opl3sa2_state_t;
-static opl3sa2_state_t opl3sa2_state[OPL3SA2_CARDS_MAX];
-
-	
-
-/* Our parameters */
-static int __initdata io	= -1;
-static int __initdata mss_io	= -1;
-static int __initdata mpu_io	= -1;
-static int __initdata irq	= -1;
-static int __initdata dma	= -1;
-static int __initdata dma2	= -1;
-static int __initdata ymode	= -1;
-static int __initdata loopback	= -1;
-
-#ifdef CONFIG_PNP
-/* PnP specific parameters */
-static int __initdata isapnp = 1;
-static int __initdata multiple = 1;
-
-/* Whether said devices have been activated */
-static int opl3sa2_activated[OPL3SA2_CARDS_MAX];
-#else
-static int __initdata isapnp; /* = 0 */
-static int __initdata multiple; /* = 0 */
-#endif
-
-MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
-MODULE_AUTHOR("Scott Murray <scott@spiteful.org>");
-MODULE_LICENSE("GPL");
-
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370.  Address must be even and must be from 0x100 to 0xFFE)");
-
-module_param(mss_io, int, 0);
-MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
-
-module_param(mpu_io, int, 0);
-MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)");
-
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
-
-module_param(dma, int, 0);
-MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
-
-module_param(dma2, int, 0);
-MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
-
-module_param(ymode, int, 0);
-MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)");
-
-module_param(loopback, int, 0);
-MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");
-
-#ifdef CONFIG_PNP
-module_param(isapnp, bool, 0);
-MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");
-
-module_param(multiple, bool, 0);
-MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards");
-#endif
-
-
-/*
- * Standard read and write functions
-*/
-
-static inline void opl3sa2_write(unsigned short port,
-				 unsigned char  index,
-				 unsigned char  data)
-{
-	outb_p(index, port);
-	outb(data, port + 1);
-}
-
-
-static inline void opl3sa2_read(unsigned short port,
-				unsigned char  index,
-				unsigned char* data)
-{
-	outb_p(index, port);
-	*data = inb(port + 1);
-}
-
-
-/*
- * All of the mixer functions...
- */
-
-static void opl3sa2_set_volume(opl3sa2_state_t* devc, int left, int right)
-{
-	static unsigned char scale[101] = {
-		0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
-		0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c,
-		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b,
-		0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09,
-		0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08,
-		0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
-		0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
-		0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00
-	};
-	unsigned char vol;
-
-	vol = scale[left];
-
-	/* If level is zero, turn on mute */
-	if(!left)
-		vol |= 0x80;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol);
-
-	vol = scale[right];
-
-	/* If level is zero, turn on mute */
-	if(!right)
-		vol |= 0x80;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol);
-}
-
-
-static void opl3sa2_set_mic(opl3sa2_state_t* devc, int level)
-{
-	unsigned char vol = 0x1F;
-
-	if((level >= 0) && (level <= 100))
-		vol = 0x1F - (unsigned char) (32 * level / 101);
-
-	/* If level is zero, turn on mute */
-	if(!level)
-		vol |= 0x80;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol);
-}
-
-
-static void opl3sa3_set_bass(opl3sa2_state_t* devc, int left, int right)
-{
-	unsigned char bass;
-
-	bass = left ? ((unsigned char) (8 * left / 101)) : 0; 
-	bass |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);
-}
-
-
-static void opl3sa3_set_treble(opl3sa2_state_t* devc, int left, int right)
-{	
-	unsigned char treble;
-
-	treble = left ? ((unsigned char) (8 * left / 101)) : 0; 
-	treble |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);
-}
-
-
-
-
-static void opl3sa2_mixer_reset(opl3sa2_state_t* devc)
-{
-	if (devc) {
-		opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
-		devc->volume_l = devc->volume_r = DEFAULT_VOLUME;
-
-		opl3sa2_set_mic(devc, DEFAULT_MIC);
-		devc->mic = DEFAULT_MIC;
-
-		if (devc->chipset == CHIPSET_OPL3SA3) {
-			opl3sa3_set_bass(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
-			devc->bass_l = devc->bass_r = DEFAULT_TIMBRE;
-			opl3sa3_set_treble(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
-			devc->treble_l = devc->treble_r = DEFAULT_TIMBRE;
-		}
-	}
-}
-
-static inline void arg_to_vol_mono(unsigned int vol, int* value)
-{
-	int left;
-	
-	left = vol & 0x00ff;
-	if (left > 100)
-		left = 100;
-	*value = left;
-}
-
-
-static inline void arg_to_vol_stereo(unsigned int vol, int* aleft, int* aright)
-{
-	arg_to_vol_mono(vol, aleft);
-	arg_to_vol_mono(vol >> 8, aright);
-}
-
-
-static inline int ret_vol_mono(int vol)
-{
-	return ((vol << 8) | vol);
-}
-
-
-static inline int ret_vol_stereo(int left, int right)
-{
-	return ((right << 8) | left);
-}
-
-
-static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, void __user *arg)
-{
-	int retval, value, cmdf = cmd & 0xff;
-	int __user *p = (int __user *)arg;
-
-	opl3sa2_state_t* devc = &opl3sa2_state[dev];
-	
-	switch (cmdf) {
-		case SOUND_MIXER_VOLUME:
-		case SOUND_MIXER_MIC:
-		case SOUND_MIXER_DEVMASK:
-		case SOUND_MIXER_STEREODEVS: 
-		case SOUND_MIXER_RECMASK:
-		case SOUND_MIXER_RECSRC:
-		case SOUND_MIXER_CAPS: 
-			break;
-
-		default:
-			return -EINVAL;
-	}
-	
-	if (((cmd >> 8) & 0xff) != 'M')
-		return -EINVAL;
-		
-	retval = 0;
-	if (_SIOC_DIR (cmd) & _SIOC_WRITE) {
-		switch (cmdf) {
-			case SOUND_MIXER_VOLUME:
-				retval = get_user(value, (unsigned __user *) arg);
-				if (retval)
-					break;
-				arg_to_vol_stereo(value, &devc->volume_l, &devc->volume_r);
-				opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
-				value = ret_vol_stereo(devc->volume_l, devc->volume_r);
-				retval = put_user(value, p);
-				break;
-		  
-			case SOUND_MIXER_MIC:
-				retval = get_user(value, (unsigned __user *) arg);
-				if (retval)
-					break;
-				arg_to_vol_mono(value, &devc->mic);
-				opl3sa2_set_mic(devc, devc->mic);
-				value = ret_vol_mono(devc->mic);
-				retval = put_user(value, p);
-				break;
-
-			default:
-				retval = -EINVAL;
-		}
-	}
-	else {
-		/*
-		 * Return parameters
-		 */
-		switch (cmdf) {
-			case SOUND_MIXER_DEVMASK:
-				retval = put_user(SOUND_MASK_VOLUME | SOUND_MASK_MIC, p);
-				break;
-		  
-			case SOUND_MIXER_STEREODEVS:
-				retval = put_user(SOUND_MASK_VOLUME, p);
-				break;
-		  
-			case SOUND_MIXER_RECMASK:
-				/* No recording devices */
-				retval = put_user(0, p);
-				break;
-
-			case SOUND_MIXER_CAPS:
-				retval = put_user(SOUND_CAP_EXCL_INPUT, p);
-				break;
-
-			case SOUND_MIXER_RECSRC:
-				/* No recording source */
-				retval = put_user(0, p);
-				break;
-
-			case SOUND_MIXER_VOLUME:
-				value = ret_vol_stereo(devc->volume_l, devc->volume_r);
-				retval = put_user(value, p);
-				break;
-			  
-			case SOUND_MIXER_MIC:
-				value = ret_vol_mono(devc->mic);
-				put_user(value, p);
-				break;
-
-			default:
-				retval = -EINVAL;
-		}
-	}
-	return retval;
-}
-/* opl3sa2_mixer_ioctl end */
-
-
-static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, void __user * arg)
-{
-	int value, retval, cmdf = cmd & 0xff;
-
-	opl3sa2_state_t* devc = &opl3sa2_state[dev];
-
-	switch (cmdf) {
-	case SOUND_MIXER_BASS:
-		value = ret_vol_stereo(devc->bass_l, devc->bass_r);
-		retval = put_user(value, (int __user *) arg);
-		break;
-		
-	case SOUND_MIXER_TREBLE:
-		value = ret_vol_stereo(devc->treble_l, devc->treble_r);
-		retval = put_user(value, (int __user *) arg);
-		break;
-
-	case SOUND_MIXER_DIGITAL1:
-		value = ret_vol_stereo(devc->wide_l, devc->wide_r);
-		retval = put_user(value, (int __user *) arg);
-		break;
-
-	default:
-		retval = -EINVAL;
-	}
-	return retval;
-}
-/* opl3sa3_mixer_ioctl end */
-
-
-static struct mixer_operations opl3sa2_mixer_operations =
-{
-	.owner	= THIS_MODULE,
-	.id	= "OPL3-SA2",
-	.name	= "Yamaha OPL3-SA2",
-	.ioctl	= opl3sa2_mixer_ioctl
-};
-
-static struct mixer_operations opl3sa3_mixer_operations =
-{
-	.owner	= THIS_MODULE,
-	.id	= "OPL3-SA3",
-	.name	= "Yamaha OPL3-SA3",
-	.ioctl	= opl3sa3_mixer_ioctl
-};
-
-/* End of mixer-related stuff */
-
-
-/*
- * Component probe, attach, unload functions
- */
-
-static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
-{
-	unload_mpu401(hw_config);
-}
-
-
-static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct resource *ports)
-{
-	int initial_mixers;
-
-	initial_mixers = num_mixers;
-	attach_ms_sound(hw_config, ports, THIS_MODULE);	/* Slot 0 */
-	if (hw_config->slots[0] != -1) {
-		/* Did the MSS driver install? */
-		if(num_mixers == (initial_mixers + 1)) {
-			/* The MSS mixer is installed, reroute mixers appropriately */
-			AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
-			AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
-			AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
-		}
-		else {
-			printk(KERN_ERR PFX "MSS mixer not installed?\n");
-		}
-	}
-}
-
-
-static inline void __exit unload_opl3sa2_mss(struct address_info* hw_config)
-{
-	unload_ms_sound(hw_config);
-}
-
-
-static int __init probe_opl3sa2(struct address_info* hw_config, int card)
-{
-	unsigned char misc;
-	unsigned char tmp;
-	unsigned char version;
-
-	/*
-	 * Try and allocate our I/O port range.
-	 */
-	if (!request_region(hw_config->io_base, 2, OPL3SA2_MODULE_NAME)) {
-		printk(KERN_ERR PFX "Control I/O port %#x not free\n",
-		       hw_config->io_base);
-		goto out_nodev;
-	}
-
-	/*
-	 * Check if writing to the read-only version bits of the miscellaneous
-	 * register succeeds or not (it should not).
-	 */
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
-	opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc ^ 0x07);
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &tmp);
-	if(tmp != misc) {
-		printk(KERN_ERR PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
-		       hw_config->io_base);
-		goto out_region;
-	}
-
-	/*
-	 * Check if the MIC register is accessible.
-	 */
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
-	opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, 0x8a);
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
-	if((tmp & 0x9f) != 0x8a) {
-		printk(KERN_ERR
-		       PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
-		       hw_config->io_base);
-		goto out_region;
-	}
-	opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, tmp);
-
-	/*
-	 * Determine chipset type (SA2 or SA3)
-	 *
-	 * This is done by looking at the chipset version in the lower 3 bits
-	 * of the miscellaneous register.
-	 */
-	version = misc & 0x07;
-	printk(KERN_DEBUG PFX "Chipset version = %#x\n", version);
-	switch (version) {
-		case 0:
-			opl3sa2_state[card].chipset = CHIPSET_UNKNOWN;
-			printk(KERN_ERR
-			       PFX "Unknown Yamaha audio controller version\n");
-			break;
-
-		case VERSION_YMF711:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA2;
-			printk(KERN_INFO PFX "Found OPL3-SA2 (YMF711)\n");
-			break;
-
-		case VERSION_YMF715:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
-			printk(KERN_INFO
-			       PFX "Found OPL3-SA3 (YMF715 or YMF719)\n");
-			break;
-
-		case VERSION_YMF715B:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
-			printk(KERN_INFO
-			       PFX "Found OPL3-SA3 (YMF715B or YMF719B)\n");
-			break;
-
-		case VERSION_YMF715E:
-		default:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
-			printk(KERN_INFO
-			       PFX "Found OPL3-SA3 (YMF715E or YMF719E)\n");
-			break;
-	}
-
-	if (opl3sa2_state[card].chipset != CHIPSET_UNKNOWN) {
-		/* Generate a pretty name */
-		opl3sa2_state[card].chipset_name = (char *)CHIPSET_TABLE[opl3sa2_state[card].chipset];
-		return 0;
-	}
-
-out_region:
-	release_region(hw_config->io_base, 2);
-out_nodev:
-	return -ENODEV;
-}
-
-
-static void __init attach_opl3sa2(struct address_info* hw_config, int card)
-{
-	/* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */
-	opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d);
-
-	/* Initialize DMA configuration */
-	if(hw_config->dma2 == hw_config->dma) {
-		/* Want DMA configuration DMA-B: -, DMA-A: WSS-P+WSS-R */
-		opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x03);
-	}
-	else {
-		/* Want DMA configuration DMA-B: WSS-R, DMA-A: WSS-P */
-		opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x21);
-	}
-}
-
-
-static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card)
-{
-	struct mixer_operations* mixer_operations;
-	opl3sa2_state_t* devc = &opl3sa2_state[card];
-
-	/* Install master mixer */
-	if (devc->chipset == CHIPSET_OPL3SA3) {
-		mixer_operations = &opl3sa3_mixer_operations;
-	}
-	else {
-		mixer_operations = &opl3sa2_mixer_operations;
-	}
-
-	devc->cfg_port = hw_config->io_base;
-	devc->mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
-					  mixer_operations->name,
-					  mixer_operations,
-					  sizeof(struct mixer_operations),
-					  devc);
-	if(devc->mixer < 0) {
-		printk(KERN_ERR PFX "Could not install %s master mixer\n",
-			 mixer_operations->name);
-	}
-	else {
-			opl3sa2_mixer_reset(devc);
-
-	}
-}
-
-
-static void opl3sa2_clear_slots(struct address_info* hw_config)
-{
-	int i;
-
-	for(i = 0; i < 6; i++) {
-		hw_config->slots[i] = -1;
-	}
-}
-
-
-static void __init opl3sa2_set_ymode(struct address_info* hw_config, int ymode)
-{
-	/*
-	 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
-	 * it's supported.
-	 *
-	 * 0: Desktop (aka normal)   5-12 cm speakers
-	 * 1: Notebook PC mode 1     3 cm speakers
-	 * 2: Notebook PC mode 2     1.5 cm speakers
-	 * 3: Hi-fi                  16-38 cm speakers
-	 */
-	if(ymode >= 0 && ymode <= 3) {
-		unsigned char sys_ctrl;
-
-		opl3sa2_read(hw_config->io_base, OPL3SA2_SYS_CTRL, &sys_ctrl);
-		sys_ctrl = (sys_ctrl & 0xcf) | ((ymode & 3) << 4);
-		opl3sa2_write(hw_config->io_base, OPL3SA2_SYS_CTRL, sys_ctrl);
-	}
-	else {
-		printk(KERN_ERR PFX "not setting ymode, it must be one of 0,1,2,3\n");
-	}
-}
-
-
-static void __init opl3sa2_set_loopback(struct address_info* hw_config, int loopback)
-{
-	if(loopback >= 0 && loopback <= 1) {
-		unsigned char misc;
-
-		opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
-		misc = (misc & 0xef) | ((loopback & 1) << 4);
-		opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc);
-	}
-	else {
-		printk(KERN_ERR PFX "not setting loopback, it must be either 0 or 1\n");
-	}
-}
-
-
-static void __exit unload_opl3sa2(struct address_info* hw_config, int card)
-{
-        /* Release control ports */
-	release_region(hw_config->io_base, 2);
-
-	/* Unload mixer */
-	if(opl3sa2_state[card].mixer >= 0)
-		sound_unload_mixerdev(opl3sa2_state[card].mixer);
-
-}
-
-#ifdef CONFIG_PNP
-static struct pnp_device_id pnp_opl3sa2_list[] = {
-	{.id = "YMH0021", .driver_data = 0},
-	{.id = ""}
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_opl3sa2_list);
-
-static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
-	int card = opl3sa2_cards_num;
-
-	/* we don't actually want to return an error as the user may have specified
-	 * no multiple card search
-	 */
-
-	if (opl3sa2_cards_num == OPL3SA2_CARDS_MAX)
-		return 0;
-	opl3sa2_activated[card] = 1;
-
-	/* Our own config: */
-	opl3sa2_state[card].cfg.io_base = pnp_port_start(dev, 4);
-	opl3sa2_state[card].cfg.irq     = pnp_irq(dev, 0);
-	opl3sa2_state[card].cfg.dma     = pnp_dma(dev, 0);
-	opl3sa2_state[card].cfg.dma2    = pnp_dma(dev, 1);
-
-	/* The MSS config: */
-	opl3sa2_state[card].cfg_mss.io_base      = pnp_port_start(dev, 1);
-	opl3sa2_state[card].cfg_mss.irq          = pnp_irq(dev, 0);
-	opl3sa2_state[card].cfg_mss.dma          = pnp_dma(dev, 0);
-	opl3sa2_state[card].cfg_mss.dma2         = pnp_dma(dev, 1);
-	opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
-
-	opl3sa2_state[card].cfg_mpu.io_base       = pnp_port_start(dev, 3);
-	opl3sa2_state[card].cfg_mpu.irq           = pnp_irq(dev, 0);
-	opl3sa2_state[card].cfg_mpu.dma           = -1;
-	opl3sa2_state[card].cfg_mpu.dma2          = -1;
-	opl3sa2_state[card].cfg_mpu.always_detect = 1; /* It's there, so use shared IRQs */
-
-	/* Call me paranoid: */
-	opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
-	opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
-	opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
-
-	opl3sa2_state[card].pdev = dev;
-	opl3sa2_cards_num++;
-
-	return 0;
-}
-
-static struct pnp_driver opl3sa2_driver = {
-	.name		= "opl3sa2",
-	.id_table	= pnp_opl3sa2_list,
-	.probe		= opl3sa2_pnp_probe,
-};
-
-#endif /* CONFIG_PNP */
-
-/* End of component functions */
-
-/*
- * Install OPL3-SA2 based card(s).
- *
- * Need to have ad1848 and mpu401 loaded ready.
- */
-static int __init init_opl3sa2(void)
-{
-	int card, max;
-
-	/* Sanitize isapnp and multiple settings */
-	isapnp = isapnp != 0 ? 1 : 0;
-	multiple = multiple != 0 ? 1 : 0;
-
-	max = (multiple && isapnp) ? OPL3SA2_CARDS_MAX : 1;
-
-#ifdef CONFIG_PNP
-	if (isapnp){
-		pnp_register_driver(&opl3sa2_driver);
-		if(!opl3sa2_cards_num){
-			printk(KERN_INFO PFX "No PnP cards found\n");
-			isapnp = 0;
-		}
-		max = opl3sa2_cards_num;
-	}
-#endif
-
-	for (card = 0; card < max; card++) {
-		/* If a user wants an I/O then assume they meant it */
-		struct resource *ports;
-		int base;
-		
-		if (!isapnp) {
-			if (io == -1 || irq == -1 || dma == -1 ||
-			    dma2 == -1 || mss_io == -1) {
-				printk(KERN_ERR
-				       PFX "io, mss_io, irq, dma, and dma2 must be set\n");
-				return -EINVAL;
-			}
-			opl3sa2_cards_num++;
-
-			/*
-			 * Our own config:
-			 * (NOTE: IRQ and DMA aren't used, so they're set to
-			 *  give pretty output from conf_printf. :)
-			 */
-			opl3sa2_state[card].cfg.io_base = io;
-			opl3sa2_state[card].cfg.irq     = irq;
-			opl3sa2_state[card].cfg.dma     = dma;
-			opl3sa2_state[card].cfg.dma2    = dma2;
-	
-			/* The MSS config: */
-			opl3sa2_state[card].cfg_mss.io_base      = mss_io;
-			opl3sa2_state[card].cfg_mss.irq          = irq;
-			opl3sa2_state[card].cfg_mss.dma          = dma;
-			opl3sa2_state[card].cfg_mss.dma2         = dma2;
-			opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
-
-			opl3sa2_state[card].cfg_mpu.io_base       = mpu_io;
-			opl3sa2_state[card].cfg_mpu.irq           = irq;
-			opl3sa2_state[card].cfg_mpu.dma           = -1;
-			opl3sa2_state[card].cfg_mpu.always_detect = 1; /* Use shared IRQs */
-
-			/* Call me paranoid: */
-			opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
-			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
-			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
-		}
-
-		/* FIXME: leak */
-		if (probe_opl3sa2(&opl3sa2_state[card].cfg, card))
-			return -ENODEV;
-
-		base = opl3sa2_state[card].cfg_mss.io_base;
-
-		if (!request_region(base, 4, "WSS config"))
-			goto failed;
-
-		ports = request_region(base + 4, 4, "ad1848");
-		if (!ports)
-			goto failed2;
-
-		if (!probe_ms_sound(&opl3sa2_state[card].cfg_mss, ports)) {
-			/*
-			 * If one or more cards are already registered, don't
-			 * return an error but print a warning.  Note, this
-			 * should never really happen unless the hardware or
-			 * ISA PnP screwed up.
-			 */
-			release_region(base + 4, 4);
-		failed2:
-			release_region(base, 4);
-		failed:
-			release_region(opl3sa2_state[card].cfg.io_base, 2);
-
-			if (opl3sa2_cards_num) {
-				printk(KERN_WARNING
-				       PFX "There was a problem probing one "
-				       " of the ISA PNP cards, continuing\n");
-				opl3sa2_cards_num--;
-				continue;
-			} else
-				return -ENODEV;
-		}
-
-		attach_opl3sa2(&opl3sa2_state[card].cfg, card);
-		conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg);
-		attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card);
-		attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss, ports);
-
-		/* ewww =) */
-		opl3sa2_state[card].card = card;
-
-		/*
-		 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
-		 * it's supported.
-		 */
-		if (ymode != -1) {
-			if (opl3sa2_state[card].chipset == CHIPSET_OPL3SA2) {
-				printk(KERN_ERR
-				       PFX "ymode not supported on OPL3-SA2\n");
-			}
-			else {
-				opl3sa2_set_ymode(&opl3sa2_state[card].cfg, ymode);
-			}
-		}
-
-
-		/* Set A/D input to Mono loopback if asked to. */
-		if (loopback != -1) {
-			opl3sa2_set_loopback(&opl3sa2_state[card].cfg, loopback);
-		}
-		
-		/* Attach MPU if we've been asked to do so, failure isn't fatal */
-		if (opl3sa2_state[card].cfg_mpu.io_base != -1) {
-			int base = opl3sa2_state[card].cfg_mpu.io_base;
-			struct resource *ports;
-			ports = request_region(base, 2, "mpu401");
-			if (!ports)
-				goto out;
-			if (!probe_mpu401(&opl3sa2_state[card].cfg_mpu, ports)) {
-				release_region(base, 2);
-				goto out;
-			}
-			if (attach_mpu401(&opl3sa2_state[card].cfg_mpu, THIS_MODULE)) {
-				printk(KERN_ERR PFX "failed to attach MPU401\n");
-				opl3sa2_state[card].cfg_mpu.slots[1] = -1;
-			}
-		}
-	}
-
-out:
-	if (isapnp) {
-		printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num);
-	}
-
-	return 0;
-}
-
-
-/*
- * Uninstall OPL3-SA2 based card(s).
- */
-static void __exit cleanup_opl3sa2(void)
-{
-	int card;
-
-	for(card = 0; card < opl3sa2_cards_num; card++) {
-	        if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
-			unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
- 		}
-		unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
-		unload_opl3sa2(&opl3sa2_state[card].cfg, card);
-#ifdef CONFIG_PNP
-		pnp_unregister_driver(&opl3sa2_driver);
-#endif
-	}
-}
-
-module_init(init_opl3sa2);
-module_exit(cleanup_opl3sa2);
-
-#ifndef MODULE
-static int __init setup_opl3sa2(char *str)
-{
-	/* io, irq, dma, dma2,... */
-#ifdef CONFIG_PNP
-	int ints[11];
-#else
-	int ints[9];
-#endif
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io       = ints[1];
-	irq      = ints[2];
-	dma      = ints[3];
-	dma2     = ints[4];
-	mss_io   = ints[5];
-	mpu_io   = ints[6];
-	ymode    = ints[7];
-	loopback = ints[8];
-#ifdef CONFIG_PNP
-	isapnp   = ints[9];
-	multiple = ints[10];
-#endif
-	return 1;
-}
-
-__setup("opl3sa2=", setup_opl3sa2);
-#endif
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 3bc1f6e..96adc47 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -11,12 +11,12 @@
  *  Built from:
  *	Low level code: <audio@tridentmicro.com> from ALSA
  *	Framework: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *	Extended by: Zach Brown <zab@redhat.com>  
+ *	Extended by: Zach Brown <zab@redhat.com>
  *
  *  Hacked up by:
  *	Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
  *	Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support
- *	Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support 
+ *	Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support
  *	Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support
  *	Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support
  *      Muli Ben-Yehuda <mulix@mulix.org>
@@ -54,33 +54,33 @@
  *	adapt to new pci joystick attachment interface
  *  v0.14.10f
  *      July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      patch from Eric Lemar (via Ian Soboroff): in suspend and resume, 
- *      fix wrong cast from pci_dev* to struct trident_card*. 
+ *      patch from Eric Lemar (via Ian Soboroff): in suspend and resume,
+ *      fix wrong cast from pci_dev* to struct trident_card*.
  *  v0.14.10e
  *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      rewrite the DMA buffer allocation/deallcoation functions, to make it 
- *      modular and fix a bug where we would call free_pages on memory 
- *      obtained with pci_alloc_consistent. Also remove unnecessary #ifdef 
+ *      rewrite the DMA buffer allocation/deallcoation functions, to make it
+ *      modular and fix a bug where we would call free_pages on memory
+ *      obtained with pci_alloc_consistent. Also remove unnecessary #ifdef
  *      CONFIG_PROC_FS and various other cleanups.
  *  v0.14.10d
  *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
  *      made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming
- *      my syslog with hundreds of messages. 
+ *      my syslog with hundreds of messages.
  *  v0.14.10c
  *      July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
  *      Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle
- *      and the coding style used in the rest of the file. 
+ *      and the coding style used in the rest of the file.
  *  v0.14.10b
  *      June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      add a missing unlock_set_fmt, remove a superflous lock/unlock pair 
- *      with nothing in between. 
+ *      add a missing unlock_set_fmt, remove a superflous lock/unlock pair
+ *      with nothing in between.
  *  v0.14.10a
- *      June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il> 
- *      use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns 
- *      per line, use 'do {} while (0)' in statement macros. 
+ *      June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns
+ *      per line, use 'do {} while (0)' in statement macros.
  *  v0.14.10
  *      June 6 2002 Lei Hu <Lei_hu@ali.com.tw>
- *      rewrite the part to read/write registers of audio codec for Ali5451 
+ *      rewrite the part to read/write registers of audio codec for Ali5451
  *  v0.14.9e
  *      January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport
  *      support to avoid resource conflict with pcigame.c
@@ -111,7 +111,7 @@
  *	Set EBUF1 and EBUF2 to still mode
  *	Add dc97/ac97 reset function
  *	Fix power management: ali_restore_regs
- *  unreleased 
+ *  unreleased
  *	Mar 09 2001 Matt Wu
  *	Add cache for ac97 access
  *  v0.14.7
@@ -120,7 +120,7 @@
  *	Fix bug: an extra tail will be played when playing
  *	Jan 05 2001 Matt Wu
  *	Implement multi-channels and S/PDIF in support for ALi 1535+
- *  v0.14.6 
+ *  v0.14.6
  *	Nov 1 2000 Ching-Ling Lee
  *	Fix the bug of memory leak when switching 5.1-channels to 2 channels.
  *	Add lock protection into dynamic changing format of data.
@@ -138,7 +138,7 @@
  *  v0.14.3 May 10 2000 Ollie Lho
  *	fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU
  *  v0.14.2 Mar 29 2000 Ching-Ling Lee
- *	Add clear to silence advance in trident_update_ptr 
+ *	Add clear to silence advance in trident_update_ptr
  *	fix invalid data of the end of the sound
  *  v0.14.1 Mar 24 2000 Ching-Ling Lee
  *	ALi 5451 support added, playback and recording O.K.
@@ -178,7 +178,7 @@
  *	SiS 7018 support added, playback O.K.
  *  v0.01 Alan Cox et. al.
  *	Initial Release in kernel 2.3.30, does not work
- * 
+ *
  *  ToDo
  *	Clean up of low level channel register access code. (done)
  *	Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done)
@@ -326,7 +326,7 @@
 
 		unsigned error;	/* number of over/underruns */
                 /* put process on wait queue when no more space in buffer */
-		wait_queue_head_t wait;	
+		wait_queue_head_t wait;
 
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
@@ -358,7 +358,7 @@
 struct trident_channel {
 	int num; /* channel number */
 	u32 lba; /* Loop Begine Address, where dma buffer starts */
-	u32 eso; /* End Sample Offset, wehre dma buffer ends */ 
+	u32 eso; /* End Sample Offset, wehre dma buffer ends */
 	         /* (in the unit of samples) */
 	u32 delta; /* delta value, sample rate / 48k for playback, */
 	           /* 48k/sample rate for recording */
@@ -417,7 +417,7 @@
 	/* soundcore stuff */
 	int dev_audio;
 
-	/* structures for abstraction of hardware facilities, codecs, */ 
+	/* structures for abstraction of hardware facilities, codecs, */
 	/* banks and channels */
 	struct ac97_codec *ac97_codec[NR_AC97];
 	struct trident_pcm_bank banks[NR_BANKS];
@@ -479,7 +479,7 @@
 static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
 
 static int trident_open_mixdev(struct inode *inode, struct file *file);
-static int trident_ioctl_mixdev(struct inode *inode, struct file *file, 
+static int trident_ioctl_mixdev(struct inode *inode, struct file *file,
 				unsigned int cmd, unsigned long arg);
 
 static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val);
@@ -496,10 +496,10 @@
 static void ali_disable_special_channel(struct trident_card *card, int ch);
 static void ali_setup_spdif_out(struct trident_card *card, int flag);
 static int ali_write_5_1(struct trident_state *state,
-			 const char __user *buffer, 
-			 int cnt_for_multi_channel, unsigned int *copy_count, 
+			 const char __user *buffer,
+			 int cnt_for_multi_channel, unsigned int *copy_count,
 			 unsigned int *state_cnt);
-static int ali_allocate_other_states_resources(struct trident_state *state, 
+static int ali_allocate_other_states_resources(struct trident_state *state,
 					       int chan_nums);
 static void ali_free_other_states_resources(struct trident_state *state);
 
@@ -722,7 +722,7 @@
 	if (channel < 31 || channel > 63)
 		return;
 
-	if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX || 
+	if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||
 	    card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) {
 		b = inb(TRID_REG(card, T4D_REC_CH));
 		if ((b & ~0x80) == channel)
@@ -742,7 +742,7 @@
 	int idx;
 
 	/* The cyberpro 5050 has only 32 voices and one bank */
-	/* .. at least they are not documented (if you want to call that 
+	/* .. at least they are not documented (if you want to call that
 	 * crap documentation), perhaps broken ? */
 
 	bank = &card->banks[BANK_A];
@@ -802,7 +802,7 @@
 	/* enable, if it was disabled */
 	if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) {
 		printk(KERN_INFO "cyberpro5050: enabling audio controller\n");
-		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE, 
+		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE,
 			     portDat | CYBER_BMSK_AUENZ_ENABLE);
 		/* check again if hardware is enabled now */
 		portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
@@ -811,7 +811,7 @@
 		printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n");
 		ret = -1;
 	} else {
-		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE, 
+		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE,
 			     CYBER_BMSK_AUDIO_INT_ENABLE);
 		cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01);
 		cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20);
@@ -827,7 +827,7 @@
 /*  called with spin lock held */
 
 static int
-trident_load_channel_registers(struct trident_card *card, u32 * data, 
+trident_load_channel_registers(struct trident_card *card, u32 * data,
 			       unsigned int channel)
 {
 	int i;
@@ -845,7 +845,7 @@
 			continue;
 		outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i));
 	}
-	if (card->pci_id == PCI_DEVICE_ID_ALI_5451 || 
+	if (card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
 	    card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
 		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1));
 		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2));
@@ -884,7 +884,7 @@
 		break;
 	case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
 		data[0] = (channel->delta << 24);
-		data[2] = ((channel->delta << 16) & 0xff000000) | 
+		data[2] = ((channel->delta << 16) & 0xff000000) |
 			(channel->eso & 0x00ffffff);
 		data[3] = channel->fm_vol & 0xffff;
 		break;
@@ -989,13 +989,13 @@
 	if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
 		channel->attribute = 0;
 		if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-			if ((channel->num == ALI_SPDIF_IN_CHANNEL) || 
+			if ((channel->num == ALI_SPDIF_IN_CHANNEL) ||
 			    (channel->num == ALI_PCM_IN_CHANNEL))
 				ali_disable_special_channel(state->card, channel->num);
-			else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL)) 
+			else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL))
 				  & ALI_SPDIF_OUT_CH_ENABLE)
 				 && (channel->num == ALI_SPDIF_OUT_CHANNEL)) {
-				ali_set_spdif_out_rate(state->card, 
+				ali_set_spdif_out_rate(state->card,
 						       state->dmabuf.rate);
 				state->dmabuf.channel->delta = 0x1000;
 			}
@@ -1063,7 +1063,7 @@
 
 	channel->lba = dmabuf->dma_handle;
 	channel->delta = compute_rate_rec(dmabuf->rate);
-	if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && 
+	if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) &&
 	    (channel->num == ALI_SPDIF_IN_CHANNEL)) {
 		rate = ali_get_spdif_in_rate(card);
 		if (rate == 0) {
@@ -1180,8 +1180,8 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&card->lock, flags);
-	if ((dmabuf->mapped || 
-	     dmabuf->count < (signed) dmabuf->dmasize) && 
+	if ((dmabuf->mapped ||
+	     dmabuf->count < (signed) dmabuf->dmasize) &&
 	    dmabuf->ready) {
 		dmabuf->enable |= ADC_RUNNING;
 		trident_enable_voice_irq(card, chan_num);
@@ -1261,7 +1261,7 @@
 	void *rawbuf = NULL;
 	struct page *page, *pend;
 
-	if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order, 
+	if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
 					    &dmabuf->dma_handle)))
 		return -ENOMEM;
 
@@ -1272,7 +1272,7 @@
 	dmabuf->rawbuf = rawbuf;
 	dmabuf->buforder = order;
 
-	/* now mark the pages as reserved; otherwise */ 
+	/* now mark the pages as reserved; otherwise */
 	/* remap_pfn_range doesn't do what we want */
 	pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
 	for (page = virt_to_page(rawbuf); page <= pend; page++)
@@ -1310,7 +1310,7 @@
 		pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
 		for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
 			ClearPageReserved(page);
-		pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder, 
+		pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
 				    dmabuf->rawbuf, dmabuf->dma_handle);
 		dmabuf->rawbuf = NULL;
 	}
@@ -1368,7 +1368,7 @@
 					dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
 					/* release the auxiliary DMA buffers */
 					for (i -= 2; i >= 0; i--)
-						dealloc_dmabuf(&state->other_states[i]->dmabuf, 
+						dealloc_dmabuf(&state->other_states[i]->dmabuf,
 							       state->card->pci_dev);
 					unlock_set_fmt(state);
 					return ret;
@@ -1398,7 +1398,7 @@
 		dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt];
 		dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
 
-		memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80, 
+		memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80,
 		       dmabuf->dmasize);
 
 		spin_lock_irqsave(&s->card->lock, flags);
@@ -1453,7 +1453,7 @@
 	swptr = dmabuf->swptr;
 	spin_unlock_irqrestore(&state->card->lock, flags);
 
-	if (swptr == 0 || swptr == dmabuf->dmasize / 2 || 
+	if (swptr == 0 || swptr == dmabuf->dmasize / 2 ||
 	    swptr == dmabuf->dmasize)
 		return;
 
@@ -1511,7 +1511,7 @@
 
 		/* No matter how much data is left in the buffer, we have to wait until
 		   CSO == ESO/2 or CSO == ESO when address engine interrupts */
-		if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 || 
+		if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
 		    state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
 			diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize;
 			diff = diff % (dmabuf->dmasize);
@@ -1532,7 +1532,7 @@
 	return 0;
 }
 
-/* update buffer manangement pointers, especially, */ 
+/* update buffer manangement pointers, especially, */
 /* dmabuf->count and dmabuf->hwptr */
 static void
 trident_update_ptr(struct trident_state *state)
@@ -1559,11 +1559,11 @@
 		} else {
 			dmabuf->count += diff;
 
-			if (dmabuf->count < 0 || 
+			if (dmabuf->count < 0 ||
 			    dmabuf->count > dmabuf->dmasize) {
-				/* buffer underrun or buffer overrun, */ 
-				/* we have no way to recover it here, just */ 
-				/* stop the machine and let the process */ 
+				/* buffer underrun or buffer overrun, */
+				/* we have no way to recover it here, just */
+				/* stop the machine and let the process */
 				/* force hwptr and swptr to sync */
 				__stop_adc(state);
 				dmabuf->error++;
@@ -1582,7 +1582,7 @@
 		} else {
 			dmabuf->count -= diff;
 
-			if (dmabuf->count < 0 || 
+			if (dmabuf->count < 0 ||
 			    dmabuf->count > dmabuf->dmasize) {
 				/* buffer underrun or buffer overrun, we have no way to recover
 				   it here, just stop the machine and let the process force hwptr
@@ -1608,13 +1608,13 @@
 						if (state->chans_num == 6) {
 							clear_cnt = clear_cnt / 2;
 							swptr = swptr / 2;
-							memset(state->other_states[0]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[0]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
-							memset(state->other_states[1]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[1]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
-							memset(state->other_states[2]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[2]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
-							memset(state->other_states[3]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[3]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
 						}
 						dmabuf->endcleared = 1;
@@ -1627,13 +1627,13 @@
 					if (state->chans_num == 6) {
 						clear_cnt = clear_cnt / 2;
 						swptr = swptr / 2;
-						memset(state->other_states[0]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[0]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
-						memset(state->other_states[1]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[1]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
-						memset(state->other_states[2]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[2]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
-						memset(state->other_states[3]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[3]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
 					}
 					dmabuf->endcleared = 1;
@@ -1665,7 +1665,7 @@
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk(KERN_WARNING "trident: spurious channel " 
+				printk(KERN_WARNING "trident: spurious channel "
 				       "irq %d.\n", channel);
 				trident_stop_voice(card, channel);
 				trident_disable_voice_irq(card, channel);
@@ -1694,7 +1694,7 @@
 
 	if (opt == 1) {		// MUTE
 		dwTemp ^= 0x8000;
-		ali_ac97_write(card->ac97_codec[0], 
+		ali_ac97_write(card->ac97_codec[0],
 			       0x02, dwTemp);
 	} else if (opt == 2) {	// Down
 		if (mute)
@@ -1706,7 +1706,7 @@
 		dwTemp &= 0xe0e0;
 		dwTemp |= (volume[0]) | (volume[1] << 8);
 		ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
-		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | 
+		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
 			(((32 - volume[1]) * 25 / 8) << 8);
 	} else if (opt == 4) {	// Up
 		if (mute)
@@ -1718,7 +1718,7 @@
 		dwTemp &= 0xe0e0;
 		dwTemp |= (volume[0]) | (volume[1] << 8);
 		ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
-		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | 
+		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
 			(((32 - volume[1]) * 25 / 8) << 8);
 	} else {
 		/* Nothing needs doing */
@@ -1801,7 +1801,7 @@
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk(KERN_WARNING "cyber5050: spurious " 
+				printk(KERN_WARNING "cyber5050: spurious "
 				       "channel irq %d.\n", channel);
 				trident_stop_voice(card, channel);
 				trident_disable_voice_irq(card, channel);
@@ -1836,21 +1836,21 @@
 				ali_queue_task(card, gpio & 0x07);
 		}
 		event = inl(TRID_REG(card, T4D_MISCINT));
-		outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), 
+		outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
 		     TRID_REG(card, T4D_MISCINT));
 		spin_unlock(&card->lock);
 		return IRQ_HANDLED;
 	}
 
 	/* manually clear interrupt status, bad hardware design, blame T^2 */
-	outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), 
+	outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
 	     TRID_REG(card, T4D_MISCINT));
 	spin_unlock(&card->lock);
 	return IRQ_HANDLED;
 }
 
-/* in this loop, dmabuf.count signifies the amount of data that is waiting */ 
-/* to be copied to the user's buffer.  it is filled by the dma machine and */ 
+/* in this loop, dmabuf.count signifies the amount of data that is waiting */
+/* to be copied to the user's buffer.  it is filled by the dma machine and */
 /* drained by this loop. */
 static ssize_t
 trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
@@ -1878,8 +1878,8 @@
 	while (count > 0) {
 		spin_lock_irqsave(&state->card->lock, flags);
 		if (dmabuf->count > (signed) dmabuf->dmasize) {
-			/* buffer overrun, we are recovering from */ 
-			/* sleep_on_timeout, resync hwptr and swptr, */ 
+			/* buffer overrun, we are recovering from */
+			/* sleep_on_timeout, resync hwptr and swptr, */
 			/* make process flush the buffer */
 			dmabuf->count = dmabuf->dmasize;
 			dmabuf->swptr = dmabuf->hwptr;
@@ -1894,7 +1894,7 @@
 			cnt = count;
 		if (cnt <= 0) {
 			unsigned long tmo;
-			/* buffer is empty, start the dma machine and */ 
+			/* buffer is empty, start the dma machine and */
 			/* wait for data to be recorded */
 			start_adc(state);
 			if (file->f_flags & O_NONBLOCK) {
@@ -1904,8 +1904,8 @@
 			}
 
 			mutex_unlock(&state->sem);
-			/* No matter how much space left in the buffer, */ 
-			/* we have to wait until CSO == ESO/2 or CSO == ESO */ 
+			/* No matter how much space left in the buffer, */
+			/* we have to wait until CSO == ESO/2 or CSO == ESO */
 			/* when address engine interrupts */
 			tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
 			tmo >>= sample_shift[dmabuf->fmt];
@@ -2005,7 +2005,7 @@
 	while (count > 0) {
 		spin_lock_irqsave(&state->card->lock, flags);
 		if (dmabuf->count < 0) {
-			/* buffer underrun, we are recovering from */ 
+			/* buffer underrun, we are recovering from */
 			/* sleep_on_timeout, resync hwptr and swptr */
 			dmabuf->count = 0;
 			dmabuf->swptr = dmabuf->hwptr;
@@ -2020,7 +2020,7 @@
 			cnt = count;
 		if (cnt <= 0) {
 			unsigned long tmo;
-			/* buffer is full, start the dma machine and */ 
+			/* buffer is full, start the dma machine and */
 			/* wait for data to be played */
 			start_dac(state);
 			if (file->f_flags & O_NONBLOCK) {
@@ -2028,8 +2028,8 @@
 					ret = -EAGAIN;
 				goto out;
 			}
-			/* No matter how much data left in the buffer, */ 
-			/* we have to wait until CSO == ESO/2 or CSO == ESO */ 
+			/* No matter how much data left in the buffer, */
+			/* we have to wait until CSO == ESO/2 or CSO == ESO */
 			/* when address engine interrupts */
 			lock_set_fmt(state);
 			tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
@@ -2037,15 +2037,15 @@
 			unlock_set_fmt(state);
 			mutex_unlock(&state->sem);
 
-			/* There are two situations when sleep_on_timeout */ 
-			/* returns, one is when the interrupt is serviced */ 
-			/* correctly and the process is waked up by ISR */ 
-			/* ON TIME. Another is when timeout is expired, which */ 
-			/* means that either interrupt is NOT serviced */ 
-			/* correctly (pending interrupt) or it is TOO LATE */ 
-			/* for the process to be scheduled to run */ 
-			/* (scheduler latency) which results in a (potential) */ 
-			/* buffer underrun. And worse, there is NOTHING we */ 
+			/* There are two situations when sleep_on_timeout */
+			/* returns, one is when the interrupt is serviced */
+			/* correctly and the process is waked up by ISR */
+			/* ON TIME. Another is when timeout is expired, which */
+			/* means that either interrupt is NOT serviced */
+			/* correctly (pending interrupt) or it is TOO LATE */
+			/* for the process to be scheduled to run */
+			/* (scheduler latency) which results in a (potential) */
+			/* buffer underrun. And worse, there is NOTHING we */
 			/* can do to prevent it. */
 			if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
 				pr_debug(KERN_ERR "trident: playback schedule "
@@ -2054,8 +2054,8 @@
 					 dmabuf->fragsize, dmabuf->count,
 					 dmabuf->hwptr, dmabuf->swptr);
 
-				/* a buffer underrun, we delay the recovery */ 
-				/* until next time the while loop begin and */ 
+				/* a buffer underrun, we delay the recovery */
+				/* until next time the while loop begin and */
 				/* we REALLY have data to play */
 			}
 			if (signal_pending(current)) {
@@ -2079,7 +2079,7 @@
 		if (state->chans_num == 6) {
 			copy_count = 0;
 			state_cnt = 0;
-			if (ali_write_5_1(state, buffer, cnt, &copy_count, 
+			if (ali_write_5_1(state, buffer, cnt, &copy_count,
 					  &state_cnt) == -EFAULT) {
 				if (state_cnt) {
 					swptr = (swptr + state_cnt) % dmabuf->dmasize;
@@ -2096,7 +2096,7 @@
 				goto out;
 			}
 		} else {
-			if (copy_from_user(dmabuf->rawbuf + swptr, 
+			if (copy_from_user(dmabuf->rawbuf + swptr,
 					   buffer, cnt)) {
 				if (!ret)
 					ret = -EFAULT;
@@ -2172,7 +2172,7 @@
 			if (dmabuf->count >= (signed) dmabuf->fragsize)
 				mask |= POLLOUT | POLLWRNORM;
 		} else {
-			if ((signed) dmabuf->dmasize >= dmabuf->count + 
+			if ((signed) dmabuf->dmasize >= dmabuf->count +
 			    (signed) dmabuf->fragsize)
 				mask |= POLLOUT | POLLWRNORM;
 		}
@@ -2227,7 +2227,7 @@
 }
 
 static int
-trident_ioctl(struct inode *inode, struct file *file, 
+trident_ioctl(struct inode *inode, struct file *file,
 	      unsigned int cmd, unsigned long arg)
 {
 	struct trident_state *state = (struct trident_state *)file->private_data;
@@ -2348,7 +2348,7 @@
 
 
 	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */
-		ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | 
+		ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
 			       AFMT_U8, p);
 		break;
 
@@ -2379,7 +2379,7 @@
 			}
 		}
 		unlock_set_fmt(state);
-		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : 
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
 			       AFMT_U8, p);
 		break;
 
@@ -2438,7 +2438,7 @@
 				stop_adc(state);
 				dmabuf->ready = 0;
 				if (val >= 2) {
-					if (!((file->f_mode & FMODE_WRITE) && 
+					if (!((file->f_mode & FMODE_WRITE) &&
 					      (val == 6)))
 						val = 2;
 					dmabuf->fmt |= TRIDENT_FMT_STEREO;
@@ -2504,7 +2504,7 @@
 		abinfo.fragstotal = dmabuf->numfrag;
 		abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? 
+		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2524,7 +2524,7 @@
 		abinfo.fragstotal = dmabuf->numfrag;
 		abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? 
+		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2533,7 +2533,7 @@
 		break;
 
 	case SNDCTL_DSP_GETCAPS:
-		ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | 
+		ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
 			       DSP_CAP_MMAP | DSP_CAP_BIND, p);
 		break;
 
@@ -2553,7 +2553,7 @@
 		}
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
-				if (!dmabuf->ready && 
+				if (!dmabuf->ready &&
 				    (ret = prog_dmabuf_record(state)))
 					break;
 				start_adc(state);
@@ -2562,7 +2562,7 @@
 		}
 		if (file->f_mode & FMODE_WRITE) {
 			if (val & PCM_ENABLE_OUTPUT) {
-				if (!dmabuf->ready && 
+				if (!dmabuf->ready &&
 				    (ret = prog_dmabuf_playback(state)))
 					break;
 				start_dac(state);
@@ -2589,7 +2589,7 @@
 		if (dmabuf->mapped)
 			dmabuf->count &= dmabuf->fragsize - 1;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? 
+		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2612,7 +2612,7 @@
 		if (dmabuf->mapped)
 			dmabuf->count &= dmabuf->fragsize - 1;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? 
+		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2641,17 +2641,17 @@
 		break;
 
 	case SOUND_PCM_READ_CHANNELS:
-		ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, 
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
 			       p);
 		break;
 
 	case SOUND_PCM_READ_BITS:
-		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : 
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
 			       AFMT_U8, p);
 		break;
 
 	case SNDCTL_DSP_GETCHANNELMASK:
-		ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR | 
+		ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR |
 			       DSP_BIND_CENTER_LFE,  p);
 		break;
 
@@ -2671,10 +2671,10 @@
 		} else {
 			dmabuf->ready = 0;
 			if (file->f_mode & FMODE_READ)
-				dmabuf->channel->attribute = (CHANNEL_REC | 
+				dmabuf->channel->attribute = (CHANNEL_REC |
 							      SRC_ENABLE);
 			if (file->f_mode & FMODE_WRITE)
-				dmabuf->channel->attribute = (CHANNEL_SPC_PB | 
+				dmabuf->channel->attribute = (CHANNEL_SPC_PB |
 							      SRC_ENABLE);
 			dmabuf->channel->attribute |= mask2attr[ffs(val)];
 		}
@@ -2702,6 +2702,7 @@
 	struct trident_card *card = devs;
 	struct trident_state *state = NULL;
 	struct dmabuf *dmabuf = NULL;
+	unsigned long flags;
 
 	/* Added by Matt Wu 01-05-2001 */
 	/* TODO: there's some redundacy here wrt the check below */
@@ -2765,8 +2766,8 @@
 	init_waitqueue_head(&dmabuf->wait);
 	file->private_data = state;
 
-	/* set default sample format. According to OSS Programmer's */ 
-	/* Guide  /dev/dsp should be default to unsigned 8-bits, mono, */ 
+	/* set default sample format. According to OSS Programmer's */
+	/* Guide  /dev/dsp should be default to unsigned 8-bits, mono, */
 	/* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */
 	if (file->f_mode & FMODE_WRITE) {
 		dmabuf->fmt &= ~TRIDENT_FMT_MASK;
@@ -2779,11 +2780,13 @@
 			/* set default channel attribute to normal playback */
 			dmabuf->channel->attribute = CHANNEL_PB;
 		}
+		spin_lock_irqsave(&card->lock, flags);
 		trident_set_dac_rate(state, 8000);
+		spin_unlock_irqrestore(&card->lock, flags);
 	}
 
 	if (file->f_mode & FMODE_READ) {
-		/* FIXME: Trident 4d can only record in signed 16-bits stereo, */ 
+		/* FIXME: Trident 4d can only record in signed 16-bits stereo, */
 		/* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */
 		dmabuf->fmt &= ~TRIDENT_FMT_MASK;
 		if ((minor & 0x0f) == SND_DEV_DSP16)
@@ -2794,10 +2797,12 @@
 		if (card->pci_id == PCI_DEVICE_ID_SI_7018) {
 			/* set default channel attribute to 0x8a80, record from
 			   PCM L/R FIFO and mono = (left + right + 1)/2 */
-			dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR | 
+			dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR |
 						      MONO_MIX);
 		}
+		spin_lock_irqsave(&card->lock, flags);
 		trident_set_adc_rate(state, 8000);
+		spin_unlock_irqrestore(&card->lock, flags);
 
 		/* Added by Matt Wu 01-05-2001 */
 		if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
@@ -3020,7 +3025,7 @@
 			break;
 		if (wsemabits == 0) {
 		      unlock:
-			outl(((u32) (wcontrol & 0x1eff) | 0x00004000), 
+			outl(((u32) (wcontrol & 0x1eff) | 0x00004000),
 			     TRID_REG(card, ALI_AC97_WRITE));
 			continue;
 		}
@@ -3104,7 +3109,7 @@
 	ncount = 10;
 
 	while (1) {
-		if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) 
+		if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ)
 		    != 0)
 			break;
 		if (ncount <= 0)
@@ -3112,7 +3117,7 @@
 		if (ncount-- == 1) {
 			pr_debug("ali_ac97_read :try clear busy flag\n");
 			aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE));
-			outl((aud_reg & 0xffff7fff), 
+			outl((aud_reg & 0xffff7fff),
 			     TRID_REG(card, ALI_AC97_WRITE));
 		}
 		udelay(10);
@@ -3159,7 +3164,7 @@
 
 	wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
 	wcontrol &= 0xff00;
-	wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */ 
+	wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */
 	                            /* ali1535+ write */
 	outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE));
 
@@ -3177,7 +3182,7 @@
 			break;
 		if (ncount-- == 1) {
 			pr_debug("ali_ac97_set :try clear busy flag!!\n");
-			outw(wcontrol & 0x7fff, 
+			outw(wcontrol & 0x7fff,
 			     TRID_REG(card, ALI_AC97_WRITE));
 		}
 		udelay(10);
@@ -3382,7 +3387,7 @@
 	bval |= 0x1F;
 	outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1));
 
-	while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) && 
+	while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) &&
 	       count <= 50000) {
 		count++;
 
@@ -3669,14 +3674,14 @@
 	spin_lock_irqsave(&card->lock, flags);
 
 	ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT));
-	//ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));    
+	//ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));
 	ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A));
 
 	//disable all IRQ bits
 	outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT));
 
 	for (i = 1; i < ALI_MIXER_REGS; i++)
-		ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0], 
+		ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0],
 							    i * 2);
 
 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {
@@ -3688,7 +3693,7 @@
 	for (i = 0; i < ALI_CHANNELS; i++) {
 		outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
 		for (j = 0; j < ALI_CHANNEL_REGS; j++)
-			ali_registers.channel_regs[i][j] = inl(TRID_REG(card, 
+			ali_registers.channel_regs[i][j] = inl(TRID_REG(card,
 									j * 4 + 0xe0));
 	}
 
@@ -3707,18 +3712,18 @@
 	spin_lock_irqsave(&card->lock, flags);
 
 	for (i = 1; i < ALI_MIXER_REGS; i++)
-		ali_ac97_write(card->ac97_codec[0], i * 2, 
+		ali_ac97_write(card->ac97_codec[0], i * 2,
 			       ali_registers.mixer_regs[i]);
 
 	for (i = 0; i < ALI_CHANNELS; i++) {
 		outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
 		for (j = 0; j < ALI_CHANNEL_REGS; j++)
-			outl(ali_registers.channel_regs[i][j], 
+			outl(ali_registers.channel_regs[i][j],
 			     TRID_REG(card, j * 4 + 0xe0));
 	}
 
 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {
-		if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) || 
+		if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) ||
 		    (i * 4 == T4D_START_A))
 			continue;
 		outl(ali_registers.global_regs[i], TRID_REG(card, i * 4));
@@ -3763,7 +3768,7 @@
 
 	bank = &card->banks[BANK_A];
 
-	if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & 
+	if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) &
 	    (ALI_SPDIF_OUT_CH_ENABLE)) {
 		idx = ALI_SPDIF_OUT_CHANNEL;
 		if (!(bank->bitmap & (1 << idx))) {
@@ -3774,7 +3779,7 @@
 		}
 	}
 
-	for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST; 
+	for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST;
 	     idx++) {
 		if (!(bank->bitmap & (1 << idx))) {
 			struct trident_channel *channel = &bank->channels[idx];
@@ -3785,9 +3790,9 @@
 	}
 
 	/* no more free channels avaliable */
-#if 0 
+#if 0
 	printk(KERN_ERR "ali: no more channels available on Bank A.\n");
-#endif /* 0 */ 
+#endif /* 0 */
 	return NULL;
 }
 
@@ -3812,9 +3817,9 @@
 	}
 
 	/* no free recordable channels avaliable */
-#if 0 
+#if 0
 	printk(KERN_ERR "ali: no recordable channels available on Bank A.\n");
-#endif /* 0 */ 
+#endif /* 0 */
 	return NULL;
 }
 
@@ -3837,14 +3842,14 @@
 		break;
 	}
 
-	/* select spdif_out */ 
+	/* select spdif_out */
 	ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS;
 
-	ch_st_sel |= 0x80;	/* select right */ 
+	ch_st_sel |= 0x80;	/* select right */
 	outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
 	outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2));
 
-	ch_st_sel &= (~0x80);	/* select left */ 
+	ch_st_sel &= (~0x80);	/* select left */
 	outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
 	outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2));
 }
@@ -3881,14 +3886,14 @@
 	}
 }
 
-/* Updating the values of counters of other_states' DMAs without lock 
+/* Updating the values of counters of other_states' DMAs without lock
 protection is no harm because all DMAs of multi-channels and interrupt
 depend on a master state's DMA, and changing the counters of the master
 state DMA is protected by a spinlock.
 */
 static int
-ali_write_5_1(struct trident_state *state, const char __user *buf, 
-	      int cnt_for_multi_channel, unsigned int *copy_count, 
+ali_write_5_1(struct trident_state *state, const char __user *buf,
+	      int cnt_for_multi_channel, unsigned int *copy_count,
 	      unsigned int *state_cnt)
 {
 
@@ -3904,10 +3909,10 @@
 
 	if ((i = state->multi_channels_adjust_count) > 0) {
 		if (i == 1) {
-			if (copy_from_user(dmabuf->rawbuf + swptr, 
+			if (copy_from_user(dmabuf->rawbuf + swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 			i--;
 			(*state_cnt) += sample_s;
@@ -3916,10 +3921,10 @@
 			i = i - (state->chans_num - other_dma_nums);
 		for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) {
 			dmabuf_temp = &state->other_states[i]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 		}
 		if (cnt_for_multi_channel == 0)
@@ -3928,39 +3933,39 @@
 	if (cnt_for_multi_channel > 0) {
 		loop = cnt_for_multi_channel / (state->chans_num * sample_s);
 		for (i = 0; i < loop; i++) {
-			if (copy_from_user(dmabuf->rawbuf + swptr, buffer, 
+			if (copy_from_user(dmabuf->rawbuf + swptr, buffer,
 					   sample_s * 2))
 				return -EFAULT;
-			seek_offset(swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(swptr, buffer, cnt_for_multi_channel,
 				    sample_s * 2, *copy_count);
 			(*state_cnt) += (sample_s * 2);
 
 			dmabuf_temp = &state->other_states[0]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 
 			dmabuf_temp = &state->other_states[1]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 
 			dmabuf_temp = &state->other_states[2]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 
 			dmabuf_temp = &state->other_states[3]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 		}
 
@@ -3969,15 +3974,15 @@
 
 			if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s))
 				return -EFAULT;
-			seek_offset(swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 			(*state_cnt) += sample_s;
 
 			if (cnt_for_multi_channel > 0) {
-				if (copy_from_user(dmabuf->rawbuf + swptr, 
+				if (copy_from_user(dmabuf->rawbuf + swptr,
 						   buffer, sample_s))
 					return -EFAULT;
-				seek_offset(swptr, buffer, cnt_for_multi_channel, 
+				seek_offset(swptr, buffer, cnt_for_multi_channel,
 					    sample_s, *copy_count);
 				(*state_cnt) += sample_s;
 
@@ -3986,12 +3991,12 @@
 					loop = state->multi_channels_adjust_count - diff;
 					for (i = 0; i < loop; i++) {
 						dmabuf_temp = &state->other_states[i]->dmabuf;
-						if (copy_from_user(dmabuf_temp->rawbuf + 
-								   dmabuf_temp->swptr, 
+						if (copy_from_user(dmabuf_temp->rawbuf +
+								   dmabuf_temp->swptr,
 								   buffer, sample_s))
 							return -EFAULT;
-						seek_offset(dmabuf_temp->swptr, buffer, 
-							    cnt_for_multi_channel, 
+						seek_offset(dmabuf_temp->swptr, buffer,
+							    cnt_for_multi_channel,
 							    sample_s, *copy_count);
 					}
 				}
@@ -4048,11 +4053,11 @@
 		ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
 		break;
 	case '1':
-		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | 
+		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
 				    ALI_SPDIF_OUT_PCM);
 		break;
 	case '2':
-		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | 
+		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
 				    ALI_SPDIF_OUT_NON_PCM);
 		break;
 	case '3':
@@ -4077,7 +4082,7 @@
 
 	for (card = devs; card != NULL; card = card->next)
 		for (i = 0; i < NR_AC97; i++)
-			if (card->ac97_codec[i] != NULL && 
+			if (card->ac97_codec[i] != NULL &&
 			    card->ac97_codec[i]->dev_mixer == minor)
 				goto match;
 
@@ -4091,7 +4096,7 @@
 }
 
 static int
-trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, 
+trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
 		     unsigned long arg)
 {
 	struct ac97_codec *codec = (struct ac97_codec *) file->private_data;
@@ -4185,9 +4190,9 @@
 		/* disable AC97 GPIO interrupt */
 		outl(0x00, TRID_REG(card, SI_AC97_GPIO));
 		/* when power up the AC link is in cold reset mode so stop it */
-		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID, 
+		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID,
 		     TRID_REG(card, SI_SERIAL_INTF_CTRL));
-		/* it take a long time to recover from a cold reset */ 
+		/* it take a long time to recover from a cold reset */
 		/* (especially when you have more than one codec) */
 		udelay(2000);
 		ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
@@ -4207,9 +4212,9 @@
 		/* disable AC97 GPIO interrupt */
 		outl(0x00, TRID_REG(card, SI_AC97_GPIO));
 		/* when power up, the AC link is in cold reset mode, so stop it */
-		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT, 
+		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT,
 		     TRID_REG(card, SI_SERIAL_INTF_CTRL));
-		/* it take a long time to recover from a cold reset (especially */ 
+		/* it take a long time to recover from a cold reset (especially */
 		/* when you have more than one codec) */
 		udelay(2000);
 		ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
@@ -4221,7 +4226,7 @@
 		if ((codec = ac97_alloc_codec()) == NULL)
 			return -ENOMEM;
 
-		/* initialize some basic codec information, other fields */ 
+		/* initialize some basic codec information, other fields */
 		/* will be filled in ac97_probe_codec */
 		codec->private_data = card;
 		codec->id = num_ac97;
@@ -4352,8 +4357,8 @@
 static inline void trident_unregister_gameport(struct trident_card *card) { }
 #endif /* SUPPORT_JOYSTICK */
 
-/* install the driver, we do not allocate hardware channel nor DMA buffer */ 
-/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ 
+/* install the driver, we do not allocate hardware channel nor DMA buffer */
+/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
 /* open/read/write/ioctl/mmap) */
 static int __devinit
 trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
@@ -4376,9 +4381,9 @@
 	else
 		dma_mask = TRIDENT_DMA_MASK;
 	if (pci_set_dma_mask(pci_dev, dma_mask)) {
-		printk(KERN_ERR "trident: architecture does not support" 
-		       " %s PCI busmaster DMA\n", 
-		       pci_dev->device == PCI_DEVICE_ID_ALI_5451 ? 
+		printk(KERN_ERR "trident: architecture does not support"
+		       " %s PCI busmaster DMA\n",
+		       pci_dev->device == PCI_DEVICE_ID_ALI_5451 ?
 		       "32-bit" : "30-bit");
 		goto out;
 	}
@@ -4422,7 +4427,7 @@
 
 	pci_set_master(pci_dev);
 
-	printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", 
+	printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
 	       card_names[pci_id->driver_data], card->iobase, card->irq);
 
 	if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
@@ -4449,9 +4454,9 @@
 
 		/* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
 		card->hwvolctl = 0;
-		pci_dev_m1533 = pci_find_device(PCI_VENDOR_ID_AL, 
-						PCI_DEVICE_ID_AL_M1533, 
-						pci_dev_m1533);
+		pci_dev_m1533 = pci_get_device(PCI_VENDOR_ID_AL,
+					       PCI_DEVICE_ID_AL_M1533,
+					       pci_dev_m1533);
 		rc = -ENODEV;
 		if (pci_dev_m1533 == NULL)
 			goto out_proc_fs;
@@ -4465,6 +4470,8 @@
 			bits &= 0xbf;	/*clear bit 6 */
 			pci_write_config_byte(pci_dev_m1533, 0x7b, bits);
 		}
+		pci_dev_put(pci_dev_m1533);
+
 	} else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
 		card->alloc_pcm_channel = cyber_alloc_pcm_channel;
 		card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel;
@@ -4482,7 +4489,7 @@
 	rc = -ENODEV;
 	if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED,
 			card_names[pci_id->driver_data], card)) {
-		printk(KERN_ERR "trident: unable to allocate irq %d\n", 
+		printk(KERN_ERR "trident: unable to allocate irq %d\n",
 		       card->irq);
 		goto out_proc_fs;
 	}
@@ -4533,7 +4540,7 @@
 				printk(KERN_INFO "trident: Running on Alpha system "
 				       "type Nautilus\n");
 				ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
-				ali_ac97_set(card, 0, AC97_POWER_CONTROL, 
+				ali_ac97_set(card, 0, AC97_POWER_CONTROL,
 					     ac97_data | ALI_EAPD_POWER_DOWN);
 			}
 		}
@@ -4566,7 +4573,7 @@
 	devs = NULL;
 out_release_region:
 	release_region(iobase, 256);
-	return rc; 
+	return rc;
 }
 
 static void __devexit
@@ -4634,8 +4641,8 @@
 static int __init
 trident_init_module(void)
 {
-	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro " 
-	       "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " " 
+	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
+	       "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " "
 	       __DATE__ "\n");
 
 	return pci_register_driver(&trident_pci_driver);
diff --git a/usr/.gitignore b/usr/.gitignore
index be186a8..69b2e89 100644
--- a/usr/.gitignore
+++ b/usr/.gitignore
@@ -5,3 +5,4 @@
 initramfs_data.cpio
 initramfs_data.cpio.gz
 initramfs_list
+include